From 45d92b43e3613ecf26b20215f2db08d7162dbe63 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 09:24:58 +0200 Subject: [PATCH 1/8] merge `need_type_info_err(_const)` --- .../infer/error_reporting/need_type_info.rs | 204 ++++++++++-------- compiler/rustc_infer/src/infer/mod.rs | 5 +- compiler/rustc_middle/src/infer/unify_key.rs | 4 +- .../borrow_check/diagnostics/region_name.rs | 6 +- .../src/traits/error_reporting/mod.rs | 23 +- compiler/rustc_typeck/src/check/fn_ctxt.rs | 2 +- compiler/rustc_typeck/src/check/writeback.rs | 11 +- .../infer/cannot-infer-const-args.full.stderr | 4 +- .../infer/cannot-infer-const-args.min.stderr | 4 +- .../infer/method-chain.full.stderr | 4 +- .../infer/method-chain.min.stderr | 4 +- .../infer/uninferred-consts.full.stderr | 4 +- .../infer/uninferred-consts.min.stderr | 4 +- 13 files changed, 148 insertions(+), 131 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f87406c2ce469..f17492674ab4c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -176,7 +176,10 @@ fn closure_return_type_suggestion( suggestion, Applicability::HasPlaceholders, ); - err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr)); + err.span_label( + span, + InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr), + ); } /// Given a closure signature, return a `String` containing a list of all its argument types. @@ -220,60 +223,119 @@ impl Into for TypeAnnotationNeeded { impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn extract_type_name( &self, - ty: Ty<'tcx>, + arg: GenericArg<'tcx>, highlight: Option, ) -> (String, Option, Cow<'static, str>, Option, Option<&'static str>) { - if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() { - let mut inner = self.inner.borrow_mut(); - let ty_vars = &inner.type_variables(); - let var_origin = ty_vars.var_origin(ty_vid); - if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind { - let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id)); - let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id { - let parent_name = self - .tcx - .def_key(parent_def_id) - .disambiguated_data - .data - .get_opt_name() - .map(|parent_symbol| parent_symbol.to_string()); - - (parent_name, Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id))) - } else { - (None, None) - }; + match arg.unpack() { + GenericArgKind::Type(ty) => { + if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() { + let mut inner = self.inner.borrow_mut(); + let ty_vars = &inner.type_variables(); + let var_origin = ty_vars.var_origin(ty_vid); + if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = + var_origin.kind + { + let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id)); + let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id + { + let parent_name = self + .tcx + .def_key(parent_def_id) + .disambiguated_data + .data + .get_opt_name() + .map(|parent_symbol| parent_symbol.to_string()); + + ( + parent_name, + Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), + ) + } else { + (None, None) + }; + + if name != kw::SelfUpper { + return ( + name.to_string(), + Some(var_origin.span), + "type parameter".into(), + parent_name, + parent_desc, + ); + } + } + } - if name != kw::SelfUpper { - return ( - name.to_string(), - Some(var_origin.span), - "type parameter".into(), - parent_name, - parent_desc, - ); + let mut s = String::new(); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; } + let _ = ty.print(printer); + (s, None, ty.prefix_string(), None, None) } - } + GenericArgKind::Const(ct) => { + if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { + let origin = + self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; + if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = + origin.kind + { + let parent_def_id = self.tcx.parent(def_id); + let (parent_name, parent_descr) = if let Some(parent_def_id) = parent_def_id + { + let parent_name = self + .tcx + .def_key(parent_def_id) + .disambiguated_data + .data + .get_opt_name() + .map(|parent_symbol| parent_symbol.to_string()); + + ( + parent_name, + Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), + ) + } else { + (None, None) + }; + + return ( + name.to_string(), + Some(origin.span), + "const parameter".into(), + parent_name, + parent_descr, + ); + } + } - let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); - if let Some(highlight) = highlight { - printer.region_highlight_mode = highlight; + let mut s = String::new(); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + let _ = ct.print(printer); + (s, None, "".into(), None, None) + } + GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), } - let _ = ty.print(printer); - (s, None, ty.prefix_string(), None, None) } - // FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well. pub fn need_type_info_err( &self, body_id: Option, span: Span, - ty: Ty<'tcx>, + ty: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None); + let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(ty, None); + let kind_str = match ty.unpack() { + GenericArgKind::Type(_) => "type", + GenericArgKind::Const(_) => "the value", + GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), + }; let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span); let ty_to_string = |ty: Ty<'tcx>| -> String { @@ -545,55 +607,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Avoid multiple labels pointing at `span`. err.span_label( span, - InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr), + InferCtxt::missing_type_msg(kind_str, &name, &descr, parent_name, parent_descr), ); } err } - // FIXME(const_generics): We should either try and merge this with `need_type_info_err` - // or improve the errors created here. - // - // Unlike for type inference variables, we don't yet store the origin of const inference variables. - // This is needed for to get a more relevant error span. - pub fn need_type_info_err_const( - &self, - body_id: Option, - span: Span, - ct: &'tcx ty::Const<'tcx>, - error_code: TypeAnnotationNeeded, - ) -> DiagnosticBuilder<'tcx> { - let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span); - if let Some(body_id) = body_id { - let expr = self.tcx.hir().expect_expr(body_id.hir_id); - local_visitor.visit_expr(expr); - } - - let mut param_name = None; - let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { - let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; - if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind { - param_name = Some(param); - } - origin.span - } else { - local_visitor.target_span - }; - - let error_code = error_code.into(); - let mut err = - self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code); - - if let Some(param_name) = param_name { - err.note(&format!("cannot infer the value of the const parameter `{}`", param_name)); - } else { - err.note("unable to infer the value of a const parameter"); - } - - err - } - /// If the `FnSig` for the method call can be found and type arguments are identified as /// needed, suggest annotating the call, otherwise point out the resulting type of the call. fn annotate_method_call( @@ -647,7 +667,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None); + let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(ty.into(), None); let mut err = struct_span_err!( self.tcx.sess, @@ -656,18 +676,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "type inside {} must be known in this context", kind, ); - err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr)); + err.span_label( + span, + InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr), + ); err } fn missing_type_msg( + kind_str: &str, type_name: &str, descr: &str, parent_name: Option, parent_descr: Option<&str>, - ) -> Cow<'static, str> { + ) -> String { if type_name == "_" { - "cannot infer type".into() + format!("cannot infer {}", kind_str) } else { let parent_desc = if let Some(parent_name) = parent_name { let parent_type_descr = if let Some(parent_descr) = parent_descr { @@ -681,7 +705,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "".to_string() }; - format!("cannot infer type for {} `{}`{}", descr, type_name, parent_desc).into() + let preposition = if "value" == kind_str { "of" } else { "for" }; + // For example: "cannot infer type for type parameter `T`" + format!( + "cannot infer {} {} {} `{}`{}", + kind_str, preposition, descr, type_name, parent_desc + ) + .into() } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2cbdc954e2007..d7bfab8a7f85d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1163,7 +1163,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } GenericParamDefKind::Const { .. } => { let origin = ConstVariableOrigin { - kind: ConstVariableOriginKind::ConstParameterDefinition(param.name), + kind: ConstVariableOriginKind::ConstParameterDefinition( + param.name, + param.def_id, + ), span, }; let const_var_id = diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index a60a17befeffd..499f92b404116 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -4,6 +4,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify::{ self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue, }; +use rustc_span::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -124,8 +125,7 @@ pub struct ConstVariableOrigin { pub enum ConstVariableOriginKind { MiscVariable, ConstInference, - // FIXME(const_generics): Consider storing the `DefId` of the param here. - ConstParameterDefinition(Symbol), + ConstParameterDefinition(Symbol, DefId), SubstitutionPlaceholder, } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index da7bc1564c013..d96020fe36106 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -396,7 +396,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ) -> Option { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); - let type_name = self.infcx.extract_type_name(&ty, Some(highlight)).0; + let type_name = self.infcx.extract_type_name(ty.into(), Some(highlight)).0; debug!( "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -646,7 +646,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0; + let type_name = self.infcx.extract_type_name(return_ty.into(), Some(highlight)).0; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); @@ -698,7 +698,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0; + let type_name = self.infcx.extract_type_name(yield_ty.into(), Some(highlight)).0; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index bda4351b2f2d8..4cc9a1ecdc81b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -20,7 +20,6 @@ use rustc_hir::Node; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{ self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, @@ -1513,10 +1512,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit(); + self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0282).emit(); return; } - let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); + let mut err = + self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0283); err.note(&format!("cannot satisfy `{}`", predicate)); if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); @@ -1580,17 +1580,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { return; } - match arg.unpack() { - GenericArgKind::Lifetime(lt) => { - span_bug!(span, "unexpected well formed predicate: {:?}", lt) - } - GenericArgKind::Type(ty) => { - self.need_type_info_err(body_id, span, ty, ErrorCode::E0282) - } - GenericArgKind::Const(ct) => { - self.need_type_info_err_const(body_id, span, ct, ErrorCode::E0282) - } - } + self.need_type_info_err(body_id, span, arg, ErrorCode::E0282) } ty::PredicateAtom::Subtype(data) => { @@ -1601,7 +1591,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info_err(body_id, span, a, ErrorCode::E0282) + self.need_type_info_err(body_id, span, a.into(), ErrorCode::E0282) } ty::PredicateAtom::Projection(data) => { let trait_ref = ty::Binder::bind(data).to_poly_trait_ref(self.tcx); @@ -1612,7 +1602,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } if self_ty.needs_infer() && ty.needs_infer() { // We do this for the `foo.collect()?` case to produce a suggestion. - let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284); + let mut err = + self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0284); err.note(&format!("cannot satisfy `{}`", predicate)); err } else { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt.rs b/compiler/rustc_typeck/src/check/fn_ctxt.rs index a03b8064b5909..31010753474be 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt.rs @@ -2991,7 +2991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info_err((**self).body_id, sp, ty, E0282) + self.need_type_info_err((**self).body_id, sp, ty.into(), E0282) .note("type must be known at this point") .emit(); } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index b55f62ee436e1..ccff9b5cdb4b4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -653,7 +653,12 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_type_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282) + .need_type_info_err( + Some(self.body.id()), + self.span.to_span(self.tcx), + t.into(), + E0282, + ) .emit(); } } @@ -661,10 +666,10 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err_const( + .need_type_info_err( Some(self.body.id()), self.span.to_span(self.tcx), - c, + c.into(), E0282, ) .emit(); diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr index 84e75cc376416..a5f7705804e02 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:12:5 | LL | foo(); - | ^^^ - | - = note: cannot infer the value of the const parameter `X` + | ^^^ cannot infer the value for const parameter `X` declared on the function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr index 84e75cc376416..a5f7705804e02 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:12:5 | LL | foo(); - | ^^^ - | - = note: cannot infer the value of the const parameter `X` + | ^^^ cannot infer the value for const parameter `X` declared on the function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr index e65bc3f109681..0344b364166d7 100644 --- a/src/test/ui/const-generics/infer/method-chain.full.stderr +++ b/src/test/ui/const-generics/infer/method-chain.full.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/method-chain.rs:21:33 | LL | Foo.bar().bar().bar().bar().baz(); - | ^^^ - | - = note: cannot infer the value of the const parameter `N` + | ^^^ cannot infer the value for const parameter `N` declared on the associated function `baz` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr index e65bc3f109681..0344b364166d7 100644 --- a/src/test/ui/const-generics/infer/method-chain.min.stderr +++ b/src/test/ui/const-generics/infer/method-chain.min.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/method-chain.rs:21:33 | LL | Foo.bar().bar().bar().bar().baz(); - | ^^^ - | - = note: cannot infer the value of the const parameter `N` + | ^^^ cannot infer the value for const parameter `N` declared on the associated function `baz` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr index e47b6bd5dc691..47ffc7e7157cc 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/uninferred-consts.rs:14:9 | LL | Foo.foo(); - | ^^^ - | - = note: cannot infer the value of the const parameter `N` + | ^^^ cannot infer the value for const parameter `N` declared on the associated function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr index e47b6bd5dc691..47ffc7e7157cc 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr @@ -2,9 +2,7 @@ error[E0282]: type annotations needed --> $DIR/uninferred-consts.rs:14:9 | LL | Foo.foo(); - | ^^^ - | - = note: cannot infer the value of the const parameter `N` + | ^^^ cannot infer the value for const parameter `N` declared on the associated function `foo` error: aborting due to previous error From 0abb1abf04da1dd5a709614f443b57d973d438ba Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 10:06:32 +0200 Subject: [PATCH 2/8] unused path --- .../rustc_infer/src/infer/error_reporting/need_type_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f17492674ab4c..bea1ab519f1d6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -316,7 +316,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ct.print(printer); - (s, None, "".into(), None, None) + (s, None, "value".into(), None, None) } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), } From 3dbfdb0182c7b8bbace4b5d8d4445aac4291351a Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 10:44:11 +0200 Subject: [PATCH 3/8] use the correct span when dealing with inference variables --- .../src/infer/error_reporting/need_type_info.rs | 14 +++++++++----- .../infer/cannot-infer-const-args.full.stderr | 2 +- .../infer/cannot-infer-const-args.min.stderr | 2 +- src/test/ui/const-generics/infer/issue-77092.rs | 16 ++++++++++++++++ .../ui/const-generics/infer/issue-77092.stderr | 9 +++++++++ .../infer/method-chain.full.stderr | 2 +- .../const-generics/infer/method-chain.min.stderr | 2 +- .../infer/uninferred-consts.full.stderr | 2 +- .../infer/uninferred-consts.min.stderr | 2 +- 9 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/const-generics/infer/issue-77092.rs create mode 100644 src/test/ui/const-generics/infer/issue-77092.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bea1ab519f1d6..b7debba68b58e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { (s, None, ty.prefix_string(), None, None) } GenericArgKind::Const(ct) => { - if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { + let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = @@ -308,15 +308,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { parent_descr, ); } - } + + Some(origin.span).filter(|s| !s.is_dummy()) + } else { + bug!("unexpect const: {:?}", ct); + }; let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } let _ = ct.print(printer); - (s, None, "value".into(), None, None) + (s, span, "the constant".into(), None, None) } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), } @@ -705,7 +709,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "".to_string() }; - let preposition = if "value" == kind_str { "of" } else { "for" }; + let preposition = if "the value" == kind_str { "of" } else { "for" }; // For example: "cannot infer type for type parameter `T`" format!( "cannot infer {} {} {} `{}`{}", diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr index a5f7705804e02..b438ed3ad6508 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:12:5 | LL | foo(); - | ^^^ cannot infer the value for const parameter `X` declared on the function `foo` + | ^^^ cannot infer the value of const parameter `X` declared on the function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr index a5f7705804e02..b438ed3ad6508 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:12:5 | LL | foo(); - | ^^^ cannot infer the value for const parameter `X` declared on the function `foo` + | ^^^ cannot infer the value of const parameter `X` declared on the function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/issue-77092.rs b/src/test/ui/const-generics/infer/issue-77092.rs new file mode 100644 index 0000000000000..9a1dd1a825895 --- /dev/null +++ b/src/test/ui/const-generics/infer/issue-77092.rs @@ -0,0 +1,16 @@ +#![feature(min_const_generics)] + +use std::convert::TryInto; + +fn take_array_from_mut(data: &mut [T], start: usize) -> &mut [T; N] { + (&mut data[start .. start + N]).try_into().unwrap() +} + +fn main() { + let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + + for i in 1 .. 4 { + println!("{:?}", take_array_from_mut(&mut arr, i)); + //~^ ERROR type annotations needed + } +} diff --git a/src/test/ui/const-generics/infer/issue-77092.stderr b/src/test/ui/const-generics/infer/issue-77092.stderr new file mode 100644 index 0000000000000..e84ff8baeea53 --- /dev/null +++ b/src/test/ui/const-generics/infer/issue-77092.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-77092.rs:13:26 + | +LL | println!("{:?}", take_array_from_mut(&mut arr, i)); + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{_: usize}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr index 0344b364166d7..1fb0b23cf1157 100644 --- a/src/test/ui/const-generics/infer/method-chain.full.stderr +++ b/src/test/ui/const-generics/infer/method-chain.full.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/method-chain.rs:21:33 | LL | Foo.bar().bar().bar().bar().baz(); - | ^^^ cannot infer the value for const parameter `N` declared on the associated function `baz` + | ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr index 0344b364166d7..1fb0b23cf1157 100644 --- a/src/test/ui/const-generics/infer/method-chain.min.stderr +++ b/src/test/ui/const-generics/infer/method-chain.min.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/method-chain.rs:21:33 | LL | Foo.bar().bar().bar().bar().baz(); - | ^^^ cannot infer the value for const parameter `N` declared on the associated function `baz` + | ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr index 47ffc7e7157cc..7a451903e9630 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/uninferred-consts.rs:14:9 | LL | Foo.foo(); - | ^^^ cannot infer the value for const parameter `N` declared on the associated function `foo` + | ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo` error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr index 47ffc7e7157cc..7a451903e9630 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/uninferred-consts.rs:14:9 | LL | Foo.foo(); - | ^^^ cannot infer the value for const parameter `N` declared on the associated function `foo` + | ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo` error: aborting due to previous error From 0e84b6105376742072e85ae2b85a6a1fd9a9045d Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 11:00:44 +0200 Subject: [PATCH 4/8] use relevant span when unifying `ConstVarValue`s --- .../src/infer/error_reporting/need_type_info.rs | 3 ++- compiler/rustc_middle/src/infer/unify_key.rs | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index b7debba68b58e..b00adec822e51 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -309,7 +309,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } - Some(origin.span).filter(|s| !s.is_dummy()) + debug_assert!(!origin.span.is_dummy()); + Some(origin.span) } else { bug!("unexpect const: {:?}", ct); }; diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 499f92b404116..4d884dde39387 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -6,7 +6,7 @@ use rustc_data_structures::unify::{ }; use rustc_span::def_id::DefId; use rustc_span::symbol::Symbol; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use std::cmp; use std::marker::PhantomData; @@ -176,17 +176,17 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>); fn unify_values(value1: &Self, value2: &Self) -> Result { - let val = match (value1.val, value2.val) { + let (val, span) = match (value1.val, value2.val) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => { - Ok(value1.val) + (value1.val, value1.origin.span) } (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => { - Ok(value2.val) + (value2.val, value2.origin.span) } // If both sides are *unknown*, it hardly matters, does it? @@ -200,14 +200,14 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - Ok(ConstVariableValue::Unknown { universe }) + (ConstVariableValue::Unknown { universe }, value1.origin.span) } - }?; + }; Ok(ConstVarValue { origin: ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, - span: DUMMY_SP, + span: span, }, val, }) From e5430e5306a2f3706797d5e453860875abe463ed Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 24 Sep 2020 22:01:46 +0200 Subject: [PATCH 5/8] the two hardest things in programming, names and... --- .../infer/error_reporting/need_type_info.rs | 194 +++++++++++------- .../borrow_check/diagnostics/region_name.rs | 6 +- 2 files changed, 118 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index b00adec822e51..ce249404e8ead 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -178,7 +178,7 @@ fn closure_return_type_suggestion( ); err.span_label( span, - InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr), + InferCtxt::cannot_infer_msg("type", &name, &descr, parent_name, parent_descr), ); } @@ -220,12 +220,23 @@ impl Into for TypeAnnotationNeeded { } } +/// Information about a constant or a type containing inference variables. +pub struct InferDiagnosticsData { + pub name: String, + pub span: Option, + pub description: Cow<'static, str>, + pub parent_name: Option, + pub parent_description: Option<&'static str>, +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - pub fn extract_type_name( + /// Extracts data used by diagnostic for either types or constants + /// which were stuck during inference. + pub fn extract_infer_data( &self, arg: GenericArg<'tcx>, highlight: Option, - ) -> (String, Option, Cow<'static, str>, Option, Option<&'static str>) { + ) -> InferDiagnosticsData { match arg.unpack() { GenericArgKind::Type(ty) => { if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() { @@ -236,32 +247,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { var_origin.kind { let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id)); - let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id - { - let parent_name = self - .tcx - .def_key(parent_def_id) - .disambiguated_data - .data - .get_opt_name() - .map(|parent_symbol| parent_symbol.to_string()); - - ( - parent_name, - Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), - ) - } else { - (None, None) - }; + let (parent_name, parent_description) = + if let Some(parent_def_id) = parent_def_id { + let parent_name = self + .tcx + .def_key(parent_def_id) + .disambiguated_data + .data + .get_opt_name() + .map(|parent_symbol| parent_symbol.to_string()); + + ( + parent_name, + Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), + ) + } else { + (None, None) + }; if name != kw::SelfUpper { - return ( - name.to_string(), - Some(var_origin.span), - "type parameter".into(), + return InferDiagnosticsData { + name: name.to_string(), + span: Some(var_origin.span), + description: "type parameter".into(), parent_name, - parent_desc, - ); + parent_description, + }; } } } @@ -272,56 +283,67 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ty.print(printer); - (s, None, ty.prefix_string(), None, None) + InferDiagnosticsData { + name: s, + span: None, + description: ty.prefix_string(), + parent_name: None, + parent_description: None, + } } GenericArgKind::Const(ct) => { - let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { + if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = origin.kind { let parent_def_id = self.tcx.parent(def_id); - let (parent_name, parent_descr) = if let Some(parent_def_id) = parent_def_id - { - let parent_name = self - .tcx - .def_key(parent_def_id) - .disambiguated_data - .data - .get_opt_name() - .map(|parent_symbol| parent_symbol.to_string()); - - ( - parent_name, - Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), - ) - } else { - (None, None) - }; - - return ( - name.to_string(), - Some(origin.span), - "const parameter".into(), + let (parent_name, parent_description) = + if let Some(parent_def_id) = parent_def_id { + let parent_name = self + .tcx + .def_key(parent_def_id) + .disambiguated_data + .data + .get_opt_name() + .map(|parent_symbol| parent_symbol.to_string()); + + ( + parent_name, + Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)), + ) + } else { + (None, None) + }; + + return InferDiagnosticsData { + name: name.to_string(), + span: Some(origin.span), + description: "const parameter".into(), parent_name, - parent_descr, - ); + parent_description, + }; } debug_assert!(!origin.span.is_dummy()); - Some(origin.span) + let mut s = String::new(); + let mut printer = + ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + let _ = ct.print(printer); + InferDiagnosticsData { + name: s, + span: Some(origin.span), + description: "the constant".into(), + parent_name: None, + parent_description: None, + } } else { bug!("unexpect const: {:?}", ct); - }; - - let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); - if let Some(highlight) = highlight { - printer.region_highlight_mode = highlight; } - let _ = ct.print(printer); - (s, span, "the constant".into(), None, None) } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), } @@ -331,18 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, body_id: Option, span: Span, - ty: GenericArg<'tcx>, + arg: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx> { - let ty = self.resolve_vars_if_possible(&ty); - let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(ty, None); + let ty = self.resolve_vars_if_possible(&arg); + let arg_data = self.extract_infer_data(arg, None); let kind_str = match ty.unpack() { GenericArgKind::Type(_) => "type", GenericArgKind::Const(_) => "the value", GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), }; - let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span); + let mut local_visitor = FindHirNodeVisitor::new(&self, arg.into(), span); let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); @@ -372,7 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let err_span = if let Some(pattern) = local_visitor.found_arg_pattern { pattern.span - } else if let Some(span) = name_sp { + } else if let Some(span) = arg_data.span { // `span` here lets us point at `sum` instead of the entire right hand side expr: // error[E0282]: type annotations needed // --> file2.rs:3:15 @@ -419,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => String::new(), }; - // When `name` corresponds to a type argument, show the path of the full type we're + // When `arg_data.name` corresponds to a type argument, show the path of the full type we're // trying to infer. In the following example, `ty_msg` contains // " in `std::result::Result`": // ``` @@ -458,11 +480,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &mut err, &decl.output, self.tcx.hir().body(body_id), - &descr, - &name, + &arg_data.description, + &arg_data.name, &ret, - parent_name, - parent_descr, + arg_data.parent_name, + arg_data.parent_description, ); // We don't want to give the other suggestions when the problem is the // closure return type. @@ -476,15 +498,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // nudge them in the right direction. format!("a boxed closure type like `Box {}>`", args, ret) } - Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => { + Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { let ty = ty_to_string(ty); format!("the explicit type `{}`, with the type parameters specified", ty) } - Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => { + Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { let ty = ty_to_string(ty); format!( "the explicit type `{}`, where the type parameter `{}` is specified", - ty, name, + ty, arg_data.name, ) } _ => "a type".to_string(), @@ -601,7 +623,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | ^^^ cannot infer type for `S` // | // = note: type must be known at this point - let span = name_sp.unwrap_or(err_span); + let span = arg_data.span.unwrap_or(err_span); if !err .span .span_labels() @@ -612,7 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Avoid multiple labels pointing at `span`. err.span_label( span, - InferCtxt::missing_type_msg(kind_str, &name, &descr, parent_name, parent_descr), + InferCtxt::cannot_infer_msg( + kind_str, + &arg_data.name, + &arg_data.description, + arg_data.parent_name, + arg_data.parent_description, + ), ); } @@ -672,7 +700,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(ty.into(), None); + let data = self.extract_infer_data(ty.into(), None); let mut err = struct_span_err!( self.tcx.sess, @@ -683,12 +711,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err.span_label( span, - InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr), + InferCtxt::cannot_infer_msg( + "type", + &data.name, + &data.description, + data.parent_name, + data.parent_description, + ), ); err } - fn missing_type_msg( + fn cannot_infer_msg( kind_str: &str, type_name: &str, descr: &str, @@ -710,6 +744,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "".to_string() }; + // FIXME: We really shouldn't be dealing with strings here + // but instead use a sensible enum for cases like this. let preposition = if "the value" == kind_str { "of" } else { "for" }; // For example: "cannot infer type for type parameter `T`" format!( diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index d96020fe36106..e7ab97515b668 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -396,7 +396,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ) -> Option { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); - let type_name = self.infcx.extract_type_name(ty.into(), Some(highlight)).0; + let type_name = self.infcx.extract_infer_data(ty.into(), Some(highlight)).name; debug!( "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -646,7 +646,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_type_name(return_ty.into(), Some(highlight)).0; + let type_name = self.infcx.extract_infer_data(return_ty.into(), Some(highlight)).name; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); @@ -698,7 +698,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_type_name(yield_ty.into(), Some(highlight)).0; + let type_name = self.infcx.extract_infer_data(yield_ty.into(), Some(highlight)).name; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); From ff7009a4d279c1e5ce1248ca373b91678ad6709c Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 24 Sep 2020 22:03:39 +0200 Subject: [PATCH 6/8] nit --- compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index e7ab97515b668..86e8675afb2fb 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -404,7 +404,6 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); if type_name.find(&format!("'{}", counter)).is_some() { // Only add a label if we can confirm that a region was labelled. - Some(RegionNameHighlight::CannotMatchHirTy(span, type_name)) } else { None From 32195ac8f4271b8a05923859baa1d3411408effb Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 26 Sep 2020 10:28:15 +0200 Subject: [PATCH 7/8] rename functions --- .../infer/error_reporting/need_type_info.rs | 24 ++++++++-------- .../borrow_check/diagnostics/region_name.rs | 9 ++++-- .../src/traits/error_reporting/mod.rs | 28 ++++++++++++++----- compiler/rustc_typeck/src/check/fn_ctxt.rs | 2 +- compiler/rustc_typeck/src/check/writeback.rs | 4 +-- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index ce249404e8ead..6302139c27d82 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -221,7 +221,7 @@ impl Into for TypeAnnotationNeeded { } /// Information about a constant or a type containing inference variables. -pub struct InferDiagnosticsData { +pub struct InferenceDiagnosticsData { pub name: String, pub span: Option, pub description: Cow<'static, str>, @@ -232,11 +232,11 @@ pub struct InferDiagnosticsData { impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Extracts data used by diagnostic for either types or constants /// which were stuck during inference. - pub fn extract_infer_data( + pub fn extract_inference_diagnostics_data( &self, arg: GenericArg<'tcx>, highlight: Option, - ) -> InferDiagnosticsData { + ) -> InferenceDiagnosticsData { match arg.unpack() { GenericArgKind::Type(ty) => { if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() { @@ -266,7 +266,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; if name != kw::SelfUpper { - return InferDiagnosticsData { + return InferenceDiagnosticsData { name: name.to_string(), span: Some(var_origin.span), description: "type parameter".into(), @@ -283,7 +283,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ty.print(printer); - InferDiagnosticsData { + InferenceDiagnosticsData { name: s, span: None, description: ty.prefix_string(), @@ -317,7 +317,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { (None, None) }; - return InferDiagnosticsData { + return InferenceDiagnosticsData { name: name.to_string(), span: Some(origin.span), description: "const parameter".into(), @@ -334,7 +334,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ct.print(printer); - InferDiagnosticsData { + InferenceDiagnosticsData { name: s, span: Some(origin.span), description: "the constant".into(), @@ -349,16 +349,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - pub fn need_type_info_err( + pub fn emit_inference_failure_err( &self, body_id: Option, span: Span, arg: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx> { - let ty = self.resolve_vars_if_possible(&arg); - let arg_data = self.extract_infer_data(arg, None); - let kind_str = match ty.unpack() { + let arg = self.resolve_vars_if_possible(&arg); + let arg_data = self.extract_inference_diagnostics_data(arg, None); + let kind_str = match arg.unpack() { GenericArgKind::Type(_) => "type", GenericArgKind::Const(_) => "the value", GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), @@ -700,7 +700,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let data = self.extract_infer_data(ty.into(), None); + let data = self.extract_inference_diagnostics_data(ty.into(), None); let mut err = struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index 86e8675afb2fb..5f64eb3dba8ac 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -396,7 +396,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ) -> Option { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); - let type_name = self.infcx.extract_infer_data(ty.into(), Some(highlight)).name; + let type_name = + self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name; debug!( "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -645,7 +646,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_infer_data(return_ty.into(), Some(highlight)).name; + let type_name = + self.infcx.extract_inference_diagnostics_data(return_ty.into(), Some(highlight)).name; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); @@ -697,7 +699,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); - let type_name = self.infcx.extract_infer_data(yield_ty.into(), Some(highlight)).name; + let type_name = + self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name; let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4cc9a1ecdc81b..1b234a1535c97 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1512,11 +1512,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0282).emit(); + self.emit_inference_failure_err( + body_id, + span, + self_ty.into(), + ErrorCode::E0282, + ) + .emit(); return; } - let mut err = - self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0283); + let mut err = self.emit_inference_failure_err( + body_id, + span, + self_ty.into(), + ErrorCode::E0283, + ); err.note(&format!("cannot satisfy `{}`", predicate)); if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); @@ -1580,7 +1590,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { return; } - self.need_type_info_err(body_id, span, arg, ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282) } ty::PredicateAtom::Subtype(data) => { @@ -1591,7 +1601,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info_err(body_id, span, a.into(), ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282) } ty::PredicateAtom::Projection(data) => { let trait_ref = ty::Binder::bind(data).to_poly_trait_ref(self.tcx); @@ -1602,8 +1612,12 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } if self_ty.needs_infer() && ty.needs_infer() { // We do this for the `foo.collect()?` case to produce a suggestion. - let mut err = - self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0284); + let mut err = self.emit_inference_failure_err( + body_id, + span, + self_ty.into(), + ErrorCode::E0284, + ); err.note(&format!("cannot satisfy `{}`", predicate)); err } else { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt.rs b/compiler/rustc_typeck/src/check/fn_ctxt.rs index 31010753474be..79d6c7dbfdae2 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt.rs @@ -2991,7 +2991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info_err((**self).body_id, sp, ty.into(), E0282) + self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282) .note("type must be known at this point") .emit(); } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index ccff9b5cdb4b4..6fd7277a1c332 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -653,7 +653,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_type_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err( + .emit_inference_failure_err( Some(self.body.id()), self.span.to_span(self.tcx), t.into(), @@ -666,7 +666,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err( + .emit_inference_failure_err( Some(self.body.id()), self.span.to_span(self.tcx), c.into(), From 9a607c0a2781197b88ff2535b852b53d3f0e4145 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 26 Sep 2020 10:31:34 +0200 Subject: [PATCH 8/8] unused into --- .../rustc_infer/src/infer/error_reporting/need_type_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 6302139c27d82..2f3089f1a92c1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), }; - let mut local_visitor = FindHirNodeVisitor::new(&self, arg.into(), span); + let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span); let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);