From 45d92b43e3613ecf26b20215f2db08d7162dbe63 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 09:24:58 +0200 Subject: [PATCH] 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 f87406c2ce4..f17492674ab 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 @@ fn into(self) -> rustc_errors::DiagnosticId { 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 @@ pub fn need_type_info_err( // 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 @@ pub fn need_type_info_err_in_generator( 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 @@ pub fn need_type_info_err_in_generator( "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 @@ fn missing_type_msg( "".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 2cbdc954e20..d7bfab8a7f8 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1163,7 +1163,10 @@ pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg } 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 a60a17befef..499f92b4041 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::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 da7bc1564c0..d96020fe361 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 @@ fn highlight_if_we_cannot_match_hir_ty( ) -> 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 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti 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 @@ fn give_name_if_anonymous_region_appears_in_yield_ty( 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 bda4351b2f2..4cc9a1ecdc8 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_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 @@ fn maybe_report_ambiguity( // 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 @@ fn maybe_report_ambiguity( 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 @@ fn maybe_report_ambiguity( 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 @@ fn maybe_report_ambiguity( } 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 a03b8064b59..31010753474 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt.rs @@ -2991,7 +2991,7 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'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 b55f62ee436..ccff9b5cdb4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -653,7 +653,12 @@ fn new( 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 @@ fn report_type_error(&self, t: Ty<'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 84e75cc3764..a5f7705804e 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 84e75cc3764..a5f7705804e 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 e65bc3f1096..0344b364166 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 e65bc3f1096..0344b364166 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 e47b6bd5dc6..47ffc7e7157 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 e47b6bd5dc6..47ffc7e7157 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 -- 2.44.0