diff options
Diffstat (limited to 'compiler/rustc_infer/src/infer/error_reporting')
10 files changed, 356 insertions, 149 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index eb5afe828..9ff703e52 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -51,6 +51,7 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa use crate::infer; use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; +use crate::infer::ExpectedFound; use crate::traits::error_reporting::report_object_safety_error; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, @@ -69,12 +70,12 @@ use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ - self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable, - TypeSuperVisitable, TypeVisitable, + self, error::TypeError, Binder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, }; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; -use std::ops::ControlFlow; +use std::ops::{ControlFlow, Deref}; use std::{cmp, fmt, iter}; mod note; @@ -84,6 +85,31 @@ pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; +/// A helper for building type related errors. The `typeck_results` +/// field is only populated during an in-progress typeck. +/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`. +pub struct TypeErrCtxt<'a, 'tcx> { + pub infcx: &'a InferCtxt<'tcx>, + pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, +} + +impl TypeErrCtxt<'_, '_> { + /// This is just to avoid a potential footgun of accidentally + /// dropping `typeck_results` by calling `InferCtxt::err_ctxt` + #[deprecated(note = "you already have a `TypeErrCtxt`")] + #[allow(unused)] + pub fn err_ctxt(&self) -> ! { + bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call"); + } +} + +impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> { + type Target = InferCtxt<'tcx>; + fn deref(&self) -> &InferCtxt<'tcx> { + &self.infcx + } +} + pub(super) fn note_and_explain_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut Diagnostic, @@ -303,7 +329,38 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( err } -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { + pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> { + if let ty::Opaque(def_id, substs) = ty.kind() { + let future_trait = self.tcx.require_lang_item(LangItem::Future, None); + // Future::Output + let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; + + let bounds = self.tcx.bound_explicit_item_bounds(*def_id); + + for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) { + let output = predicate + .kind() + .map_bound(|kind| match kind { + ty::PredicateKind::Projection(projection_predicate) + if projection_predicate.projection_ty.item_def_id == item_def_id => + { + projection_predicate.term.ty() + } + _ => None, + }) + .transpose(); + if output.is_some() { + // We don't account for multiple `Future::Output = Ty` constraints. + return output; + } + } + } + None + } +} + +impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn report_region_errors( &self, generic_param_scope: LocalDefId, @@ -577,13 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { // don't show type `_` if span.desugaring_kind() == Some(DesugaringKind::ForLoop) - && let ty::Adt(def, substs) = ty.kind() - && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) + && let ty::Adt(def, substs) = ty.kind() + && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) { err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0))); } else { - err.span_label(span, format!("this expression has type `{}`", ty)); - } + err.span_label(span, format!("this expression has type `{}`", ty)); + } } if let Some(ty::error::ExpectedFound { found, .. }) = exp_found && ty.is_box() && ty.boxed_ty() == found @@ -619,8 +676,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id); let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind { let arg_expr = args.first().expect("try desugaring call w/out arg"); - self.in_progress_typeck_results.and_then(|typeck_results| { - typeck_results.borrow().expr_ty_opt(arg_expr) + self.typeck_results.as_ref().and_then(|typeck_results| { + typeck_results.expr_ty_opt(arg_expr) }) } else { bug!("try desugaring w/out call expr as scrutinee"); @@ -726,10 +783,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => { if let ObligationCauseCode::BindingObligation(_, span) | ObligationCauseCode::ExprBindingObligation(_, span, ..) - = cause.code().peel_derives() + = cause.code().peel_derives() && let TypeError::RegionsPlaceholderMismatch = terr { - err.span_note(*span, "the lifetime requirement is introduced here"); + err.span_note( * span, + "the lifetime requirement is introduced here"); } } } @@ -1653,8 +1711,114 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ), Mismatch::Fixed(s) => (s.into(), s.into(), None), }; - match (&terr, expected == found) { - (TypeError::Sorts(values), extra) => { + + enum Similar<'tcx> { + Adts { expected: ty::AdtDef<'tcx>, found: ty::AdtDef<'tcx> }, + PrimitiveFound { expected: ty::AdtDef<'tcx>, found: Ty<'tcx> }, + PrimitiveExpected { expected: Ty<'tcx>, found: ty::AdtDef<'tcx> }, + } + + let similarity = |ExpectedFound { expected, found }: ExpectedFound<Ty<'tcx>>| { + if let ty::Adt(expected, _) = expected.kind() && let Some(primitive) = found.primitive_symbol() { + let path = self.tcx.def_path(expected.did()).data; + let name = path.last().unwrap().data.get_opt_name(); + if name == Some(primitive) { + return Some(Similar::PrimitiveFound { expected: *expected, found }); + } + } else if let Some(primitive) = expected.primitive_symbol() && let ty::Adt(found, _) = found.kind() { + let path = self.tcx.def_path(found.did()).data; + let name = path.last().unwrap().data.get_opt_name(); + if name == Some(primitive) { + return Some(Similar::PrimitiveExpected { expected, found: *found }); + } + } else if let ty::Adt(expected, _) = expected.kind() && let ty::Adt(found, _) = found.kind() { + if !expected.did().is_local() && expected.did().krate == found.did().krate { + // Most likely types from different versions of the same crate + // are in play, in which case this message isn't so helpful. + // A "perhaps two different versions..." error is already emitted for that. + return None; + } + let f_path = self.tcx.def_path(found.did()).data; + let e_path = self.tcx.def_path(expected.did()).data; + + if let (Some(e_last), Some(f_last)) = (e_path.last(), f_path.last()) && e_last == f_last { + return Some(Similar::Adts{expected: *expected, found: *found}); + } + } + None + }; + + match terr { + // If two types mismatch but have similar names, mention that specifically. + TypeError::Sorts(values) if let Some(s) = similarity(values) => { + let diagnose_primitive = + |prim: Ty<'tcx>, + shadow: Ty<'tcx>, + defid: DefId, + diagnostic: &mut Diagnostic| { + let name = shadow.sort_string(self.tcx); + diagnostic.note(format!( + "{prim} and {name} have similar names, but are actually distinct types" + )); + diagnostic + .note(format!("{prim} is a primitive defined by the language")); + let def_span = self.tcx.def_span(defid); + let msg = if defid.is_local() { + format!("{name} is defined in the current crate") + } else { + let crate_name = self.tcx.crate_name(defid.krate); + format!("{name} is defined in crate `{crate_name}") + }; + diagnostic.span_note(def_span, msg); + }; + + let diagnose_adts = + |expected_adt : ty::AdtDef<'tcx>, + found_adt: ty::AdtDef<'tcx>, + diagnostic: &mut Diagnostic| { + let found_name = values.found.sort_string(self.tcx); + let expected_name = values.expected.sort_string(self.tcx); + + let found_defid = found_adt.did(); + let expected_defid = expected_adt.did(); + + diagnostic.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types")); + for (defid, name) in + [(found_defid, found_name), (expected_defid, expected_name)] + { + let def_span = self.tcx.def_span(defid); + + let msg = if found_defid.is_local() && expected_defid.is_local() { + let module = self + .tcx + .parent_module_from_def_id(defid.expect_local()) + .to_def_id(); + let module_name = self.tcx.def_path(module).to_string_no_crate_verbose(); + format!("{name} is defined in module `crate{module_name}` of the current crate") + } else if defid.is_local() { + format!("{name} is defined in the current crate") + } else { + let crate_name = self.tcx.crate_name(defid.krate); + format!("{name} is defined in crate `{crate_name}`") + }; + diagnostic.span_note(def_span, msg); + } + }; + + match s { + Similar::Adts{expected, found} => { + diagnose_adts(expected, found, diag) + } + Similar::PrimitiveFound{expected, found: prim} => { + diagnose_primitive(prim, values.expected, expected.did(), diag) + } + Similar::PrimitiveExpected{expected: prim, found} => { + diagnose_primitive(prim, values.found, found.did(), diag) + } + } + } + TypeError::Sorts(values) => { + let extra = expected == found; let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { (true, ty::Opaque(def_id, _)) => { let sm = self.tcx.sess.source_map(); @@ -1707,10 +1871,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } } - (TypeError::ObjectUnsafeCoercion(_), _) => { + TypeError::ObjectUnsafeCoercion(_) => { diag.note_unsuccessful_coercion(found, expected); } - (_, _) => { + _ => { debug!( "note_type_err: exp_found={:?}, expected={:?} found={:?}", exp_found, expected, found @@ -1755,7 +1919,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter + // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { @@ -1847,36 +2011,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> { - if let ty::Opaque(def_id, substs) = ty.kind() { - let future_trait = self.tcx.require_lang_item(LangItem::Future, None); - // Future::Output - let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; - - let bounds = self.tcx.bound_explicit_item_bounds(*def_id); - - for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - let predicate = predicate.subst(self.tcx, substs); - let output = predicate - .kind() - .map_bound(|kind| match kind { - ty::PredicateKind::Projection(projection_predicate) - if projection_predicate.projection_ty.item_def_id == item_def_id => - { - projection_predicate.term.ty() - } - _ => None, - }) - .transpose(); - if output.is_some() { - // We don't account for multiple `Future::Output = Ty` constraints. - return output; - } - } - } - None - } - /// A possible error is to forget to add `.await` when using futures: /// /// ```compile_fail,E0308 @@ -2051,8 +2185,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, diag: &mut Diagnostic, ) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found) + { + diag.span_suggestion( + span, + msg, + // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&` + format!("{}.as_ref()", snippet.trim_start_matches('&')), + Applicability::MachineApplicable, + ); + } + } + + pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> { if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) = - (exp_found.expected.kind(), exp_found.found.kind()) + (expected.kind(), found.kind()) { if let ty::Adt(found_def, found_substs) = *found_ty.kind() { if exp_def == &found_def { @@ -2090,21 +2238,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => show_suggestion = false, } } - if let (Ok(snippet), true) = - (self.tcx.sess.source_map().span_to_snippet(span), show_suggestion) - { - diag.span_suggestion( - span, - *msg, - // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&` - format!("{}.as_ref()", snippet.trim_start_matches('&')), - Applicability::MachineApplicable, - ); + if show_suggestion { + return Some(*msg); } } } } } + None } pub fn report_and_explain_type_error( @@ -2130,6 +2271,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str) } FailureCode::Error0308(failure_str) => { + fn escape_literal(s: &str) -> String { + let mut escaped = String::with_capacity(s.len()); + let mut chrs = s.chars().peekable(); + while let Some(first) = chrs.next() { + match (first, chrs.peek()) { + ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => { + escaped.push('\\'); + escaped.push(delim); + chrs.next(); + } + ('"' | '\'', _) => { + escaped.push('\\'); + escaped.push(first) + } + (c, _) => escaped.push(c), + }; + } + escaped + } let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str); if let Some((expected, found)) = trace.values.ty() { match (expected.kind(), found.kind()) { @@ -2151,7 +2311,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_suggestion( span, "if you meant to write a `char` literal, use single quotes", - format!("'{}'", code), + format!("'{}'", escape_literal(code)), Applicability::MachineApplicable, ); } @@ -2166,7 +2326,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_suggestion( span, "if you meant to write a `str` literal, use double quotes", - format!("\"{}\"", code), + format!("\"{}\"", escape_literal(code)), Applicability::MachineApplicable, ); } @@ -2317,7 +2477,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: Option<SubregionOrigin<'tcx>>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. let generics = self.tcx.generics_of(generic_param_scope); @@ -2333,7 +2493,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let ast_generics = self.tcx.hir().get_generics(hir_id.owner); + let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id); let bounds = ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id)); // `sp` only covers `T`, change it so that it covers @@ -2374,6 +2534,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), GenericKind::Projection(ref p) => format!("the associated type `{}`", p), + GenericKind::Opaque(def_id, substs) => { + format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs)) + } }; if let Some(SubregionOrigin::CompareImplItemObligation { @@ -2453,7 +2616,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for h in self.tcx.hir().parent_iter(param.hir_id) { break 'origin match h.1 { Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::TyAlias(..), + kind: hir::ImplItemKind::Type(..), generics, .. }) @@ -2692,7 +2855,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } -struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'a, 'tcx>); +struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>); impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { @@ -2779,7 +2942,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> { } } -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { fn report_inference_failure( &self, var_origin: RegionVariableOrigin, @@ -2967,7 +3130,7 @@ impl TyCategory { } } -impl<'tcx> InferCtxt<'_, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { /// Given a [`hir::Block`], get the span of its last expression or /// statement, peeling off any inner blocks. pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { @@ -2994,7 +3157,9 @@ impl<'tcx> InferCtxt<'_, 'tcx> { _ => rustc_span::DUMMY_SP, } } +} +impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// Be helpful when the user wrote `{... expr; }` and taking the `;` off /// is enough to fix the error. pub fn could_remove_semicolon( @@ -3011,7 +3176,7 @@ impl<'tcx> InferCtxt<'_, 'tcx> { let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { return None; }; - let last_expr_ty = self.in_progress_typeck_results?.borrow().expr_ty_opt(*last_expr)?; + let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?; let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { _ if last_expr_ty.references_error() => return None, _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => { @@ -3094,8 +3259,9 @@ impl<'tcx> InferCtxt<'_, 'tcx> { let mut find_compatible_candidates = |pat: &hir::Pat<'_>| { if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind && let Some(pat_ty) = self - .in_progress_typeck_results - .and_then(|typeck_results| typeck_results.borrow().node_type_opt(*hir_id)) + .typeck_results + .as_ref() + .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id)) { let pat_ty = self.resolve_vars_if_possible(pat_ty); if self.same_type_modulo_infer(pat_ty, expected_ty) 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 cb2be9358..7b3178e61 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 @@ -2,8 +2,10 @@ use crate::errors::{ AmbigousImpl, AmbigousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator, SourceKindMultiSuggestion, SourceKindSubdiag, }; +use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; +use rustc_errors::IntoDiagnostic; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -15,10 +17,9 @@ use rustc_middle::hir::nested_filter; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, InferConst}; +use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults}; -use rustc_session::SessionDiagnostic; use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span}; use std::borrow::Cow; @@ -151,7 +152,7 @@ impl UnderspecifiedArgKind { } } -fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'_, 'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { +fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { let mut printer = FmtPrinter::new(infcx.tcx, ns); let ty_getter = move |ty_vid| { if infcx.probe_ty_var(ty_vid).is_ok() { @@ -182,7 +183,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'_, 'tcx>, ns: Namespace) -> FmtPr printer } -fn ty_to_string<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String { +fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String { let printer = fmt_printer(infcx, Namespace::TypeNS); let ty = infcx.resolve_vars_if_possible(ty); match ty.kind() { @@ -201,7 +202,7 @@ fn ty_to_string<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String { /// We don't want to directly use `ty_to_string` for closures as their type isn't really /// something users are familiar with. Directly printing the `fn_sig` of closures also /// doesn't work as they actually use the "rust-call" API. -fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String { +fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String { let ty::Closure(_, substs) = ty.kind() else { unreachable!() }; let fn_sig = substs.as_closure().sig(); let args = fn_sig @@ -225,7 +226,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String format!("fn({}){}", args, ret) } -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +impl<'tcx> InferCtxt<'tcx> { /// Extracts data used by diagnostic for either types or constants /// which were stuck during inference. pub fn extract_inference_diagnostics_data( @@ -317,7 +318,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - /// Used as a fallback in [InferCtxt::emit_inference_failure_err] + /// Used as a fallback in [TypeErrCtxt::emit_inference_failure_err] /// in case we weren't able to get a better error. fn bad_inference_failure_err( &self, @@ -364,7 +365,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), } } +} +impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn emit_inference_failure_err( &self, body_id: Option<hir::BodyId>, @@ -376,14 +379,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let arg = self.resolve_vars_if_possible(arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); - let Some(typeck_results) = self.in_progress_typeck_results else { + let Some(typeck_results) = &self.typeck_results else { // If we don't have any typeck results we're outside // of a body, so we won't be able to get better info // here. return self.bad_inference_failure_err(failure_span, arg_data, error_code); }; - let typeck_results = typeck_results.borrow(); - let typeck_results = &typeck_results; let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); if let Some(body_id) = body_id { @@ -435,6 +436,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { generics_def_id, def_id: _, generic_args, + have_turbofish, } => { let generics = self.tcx.generics_of(generics_def_id); let is_type = matches!(arg.unpack(), GenericArgKind::Type(_)); @@ -482,11 +484,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .unwrap() .into_buffer(); - infer_subdiags.push(SourceKindSubdiag::GenericSuggestion { - span: insert_span, - arg_count: generic_args.len(), - args, - }); + if !have_turbofish { + infer_subdiags.push(SourceKindSubdiag::GenericSuggestion { + span: insert_span, + arg_count: generic_args.len(), + args, + }); + } } InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => { let printer = fmt_printer(self, Namespace::ValueNS); @@ -560,7 +564,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), } } +} +impl<'tcx> InferCtxt<'tcx> { pub fn need_type_info_err_in_generator( &self, kind: hir::GeneratorKind, @@ -616,6 +622,7 @@ enum InferSourceKind<'tcx> { generics_def_id: DefId, def_id: DefId, generic_args: &'tcx [GenericArg<'tcx>], + have_turbofish: bool, }, FullyQualifiedMethodCall { receiver: &'tcx Expr<'tcx>, @@ -650,7 +657,7 @@ impl<'tcx> InferSource<'tcx> { } impl<'tcx> InferSourceKind<'tcx> { - fn ty_localized_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> (&'static str, String) { + fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) { match *self { InferSourceKind::LetBinding { ty, .. } | InferSourceKind::ClosureArg { ty, .. } @@ -676,6 +683,7 @@ struct InsertableGenericArgs<'tcx> { substs: SubstsRef<'tcx>, generics_def_id: DefId, def_id: DefId, + have_turbofish: bool, } /// A visitor which searches for the "best" spot to use in the inference error. @@ -686,7 +694,7 @@ struct InsertableGenericArgs<'tcx> { /// While doing so, the currently best spot is stored in `infer_source`. /// For details on how we rank spots, see [Self::source_cost] struct FindInferSourceVisitor<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'tcx>, typeck_results: &'a TypeckResults<'tcx>, target: GenericArg<'tcx>, @@ -698,7 +706,7 @@ struct FindInferSourceVisitor<'a, 'tcx> { impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { fn new( - infcx: &'a InferCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'tcx>, typeck_results: &'a TypeckResults<'tcx>, target: GenericArg<'tcx>, ) -> Self { @@ -894,11 +902,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // impl is currently the `DefId` of `Output` in the trait definition // which makes this somewhat difficult and prevents us from just // using `self.path_inferred_subst_iter` here. - hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) => { - if let Some(ty) = self.opt_node_type(expr.hir_id) { - if let ty::Adt(_, substs) = ty.kind() { - return Box::new(self.resolved_path_inferred_subst_iter(path, substs)); - } + hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) + // FIXME(TaKO8Ki): Ideally we should support this. For that + // we have to map back from the self type to the + // type alias though. That's difficult. + // + // See the `need_type_info/issue-103053.rs` test for + // a example. + if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => { + if let Some(ty) = self.opt_node_type(expr.hir_id) + && let ty::Adt(_, substs) = ty.kind() + { + return Box::new(self.resolved_path_inferred_subst_iter(path, substs)); } } hir::ExprKind::MethodCall(segment, ..) => { @@ -916,6 +931,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { substs, generics_def_id: def_id, def_id, + have_turbofish: false, } }; return Box::new(insertable.into_iter()); @@ -933,6 +949,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { substs: SubstsRef<'tcx>, ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a { let tcx = self.infcx.tcx; + let have_turbofish = path.segments.iter().any(|segment| { + segment.args.map_or(false, |args| args.args.iter().any(|arg| arg.is_ty_or_const())) + }); // The last segment of a path often has `Res::Err` and the // correct `Res` is the one of the whole path. // @@ -942,7 +961,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let generics_def_id = tcx.res_generics_def_id(path.res)?; let generics = tcx.generics_of(generics_def_id); if generics.has_impl_trait() { - None? + None?; } let insert_span = path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi()); @@ -951,6 +970,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { substs, generics_def_id, def_id: path.res.def_id(), + have_turbofish, } }; @@ -970,6 +990,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { substs, generics_def_id, def_id: res.def_id(), + have_turbofish, }) }) .chain(last_segment_using_path_data) @@ -998,7 +1019,13 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } let span = tcx.hir().span(segment.hir_id); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); - InsertableGenericArgs { insert_span, substs, generics_def_id: def_id, def_id } + InsertableGenericArgs { + insert_span, + substs, + generics_def_id: def_id, + def_id, + have_turbofish: false, + } }; let parent_def_id = generics.parent.unwrap(); @@ -1021,7 +1048,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } // There cannot be inference variables in the self type, // so there's nothing for us to do here. - Res::SelfTy { .. } => {} + Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {} _ => warn!( "unexpected path: def={:?} substs={:?} path={:?}", def, substs, path, @@ -1121,7 +1148,13 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { for args in self.expr_inferred_subst_iter(expr) { debug!(?args); - let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; + let InsertableGenericArgs { + insert_span, + substs, + generics_def_id, + def_id, + have_turbofish, + } = args; let generics = tcx.generics_of(generics_def_id); if let Some(argument_index) = generics .own_substs(substs) @@ -1144,6 +1177,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { generics_def_id, def_id, generic_args, + have_turbofish, }, }); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 3a4320a9a..da0271a34 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -11,7 +11,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::SubregionOrigin; use crate::infer::TyCtxt; -use rustc_errors::AddSubdiagnostic; +use rustc_errors::AddToDiagnostic; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir::Ty; use rustc_middle::ty::Region; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 1410e2b63..c5f2a1a3f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -2,7 +2,9 @@ //! to hold. use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq}; -use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag}; +use crate::errors::{ + DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; @@ -56,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { note_and_explain::SuffixKind::Continues, ); let mut impl_span = None; - let mut trait_subdiags = Vec::new(); + let mut implicit_static_lifetimes = Vec::new(); if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) { // If an impl is local, then maybe this isn't what they want. Try to // be as helpful as possible with implicit lifetimes. @@ -90,10 +92,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Otherwise, point at all implicit static lifetimes for span in &traits { - trait_subdiags.push(TraitSubdiag::Note { span: *span }); + implicit_static_lifetimes + .push(ImplicitStaticLifetimeSubdiag::Note { span: *span }); // It would be nice to put this immediately under the above note, but they get // pushed to the end. - trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() }); + implicit_static_lifetimes + .push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() }); } } } else { @@ -105,8 +109,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { cause_span: cause.span, unmet_lifetime_reqs: multispan_subdiag, expl, - impl_note: ImplNote { impl_span }, - trait_subdiags, + does_not_outlive_static_from_impl: impl_span + .map(|span| DoesNotOutliveStaticFromImpl::Spanned { span }) + .unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned), + implicit_static_lifetimes, }; let reported = self.tcx().sess.emit_err(err); Some(reported) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 53d9acf7d..aaf5a7af0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -1,6 +1,6 @@ +use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::lexical_region_resolve::RegionResolutionError::*; -use crate::infer::InferCtxt; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::source_map::Span; @@ -19,34 +19,34 @@ pub use find_anon_type::find_anon_type; pub use static_impl_trait::{suggest_new_region_bound, HirTraitObjectVisitor, TraitObjectVisitor}; pub use util::find_param_with_region; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { - pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool { +impl<'cx, 'tcx> TypeErrCtxt<'cx, 'tcx> { + pub fn try_report_nice_region_error(&'cx self, error: &RegionResolutionError<'tcx>) -> bool { NiceRegionError::new(self, error.clone()).try_report().is_some() } } pub struct NiceRegionError<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, + cx: &'cx TypeErrCtxt<'cx, 'tcx>, error: Option<RegionResolutionError<'tcx>>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, } impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { - pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { - Self { infcx, error: Some(error), regions: None } + pub fn new(cx: &'cx TypeErrCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { + Self { cx, error: Some(error), regions: None } } pub fn new_from_span( - infcx: &'cx InferCtxt<'cx, 'tcx>, + cx: &'cx TypeErrCtxt<'cx, 'tcx>, span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, ) -> Self { - Self { infcx, error: None, regions: Some((span, sub, sup)) } + Self { cx, error: None, regions: Some((span, sub, sup)) } } fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx + self.cx.tcx } pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d4db07512..a58516829 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -226,12 +226,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { false }; - let expected_trait_ref = self.infcx.resolve_vars_if_possible(ty::TraitRef { + let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: expected_substs, }); let actual_trait_ref = self - .infcx + .cx .resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs }); // Search the expected and actual trait references to see (a) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index ae56bea6f..9bf755d7f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -185,8 +185,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() { let parent_id = tcx.hir().get_parent_item(*hir_id); - let parent_id = tcx.hir().local_def_id_to_hir_id(parent_id); - if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { + if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { @@ -287,8 +286,8 @@ pub fn suggest_new_region_bound( ) { debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; + let consider = "consider changing"; + let declare = "to declare that"; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); let explicit_static = arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg)); @@ -306,6 +305,10 @@ pub fn suggest_new_region_bound( return; }; + // Get the identity type for this RPIT + let did = item_id.owner_id.to_def_id(); + let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + if let Some(span) = opaque .bounds .iter() @@ -322,7 +325,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), + &format!("{consider} `{ty}`'s {explicit_static}"), &lifetime_name, Applicability::MaybeIncorrect, ); @@ -352,12 +355,7 @@ pub fn suggest_new_region_bound( } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), + &format!("{declare} `{ty}` {captures}, {explicit}",), &plus_lt, Applicability::MaybeIncorrect, ); @@ -368,7 +366,7 @@ pub fn suggest_new_region_bound( err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "{declare} trait object {captures}, {explicit}", + "{declare} the trait object {captures}, {explicit}", declare = declare, captures = captures, explicit = explicit, @@ -385,7 +383,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( lt.span, - &format!("{} trait object's {}", consider, explicit_static), + &format!("{} the trait object's {}", consider, explicit_static), &lifetime_name, Applicability::MaybeIncorrect, ); @@ -415,7 +413,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + { Some(Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. @@ -425,7 +424,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } Some(Node::TraitItem(trait_item)) => { let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did) { + match tcx.hir().find_by_def_id(trait_did.def_id) { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { // The method being called is defined in the `trait`, but the `'static` // obligation comes from the `impl`. Find that `impl` so that we can point @@ -486,7 +485,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { tcx, ctxt.param_env, ctxt.assoc_item.def_id, - self.infcx.resolve_vars_if_possible(ctxt.substs), + self.cx.resolve_vars_if_possible(ctxt.substs), ) else { return false; }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index a6a39d062..5d536e982 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -84,12 +84,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let expected_highlight = HighlightBuilder::build(self.tcx(), expected); let expected = self - .infcx + .cx .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight)) .name; let found_highlight = HighlightBuilder::build(self.tcx(), found); let found = - self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; + self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; err.span_label(sp, &format!("found `{}`", found)); err.span_label(trait_sp, &format!("expected `{}`", expected)); @@ -156,7 +156,8 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { [segment] if matches!( segment.res, - Res::SelfTy { trait_: _, alias_to: _ } + Res::SelfTyParam { .. } + | Res::SelfTyAlias { .. } | Res::Def(hir::def::DefKind::TyParam, _) ) => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 3e9d491af..f1461d701 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let ret_ty = fn_ty.fn_sig(self.tcx()).output(); let span = hir_sig.decl.output.span(); let future_output = if hir_sig.header.is_async() { - ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose() + ret_ty.map_bound(|ty| self.cx.get_impl_future_output_ty(ty)).transpose() } else { None }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index adaa47c01..41b115f33 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -1,8 +1,8 @@ use crate::errors::RegionOriginNote; -use crate::infer::error_reporting::note_and_explain_region; -use crate::infer::{self, InferCtxt, SubregionOrigin}; +use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; +use crate::infer::{self, SubregionOrigin}; use rustc_errors::{ - fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, }; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Region}; use super::ObligationCauseAsDiagArg; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { match *origin { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { @@ -19,26 +19,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { expected_found: self.values_str(trace.values), } .add_to_diagnostic(err), - infer::Reborrow(span) => RegionOriginNote::Plain { span, msg: fluent::infer::reborrow } - .add_to_diagnostic(err), + infer::Reborrow(span) => { + RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err) + } infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); RegionOriginNote::WithName { span, - msg: fluent::infer::reborrow, + msg: fluent::infer_reborrow, name: &var_name.to_string(), continues: false, } .add_to_diagnostic(err); } infer::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound } + RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } .add_to_diagnostic(err); } infer::DataBorrowed(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::infer::data_borrowed, + msg: fluent::infer_data_borrowed, name: &self.ty_to_string(ty), continues: false, } @@ -47,7 +48,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::infer::reference_outlives_referent, + msg: fluent::infer_reference_outlives_referent, name: &self.ty_to_string(ty), continues: false, } @@ -56,22 +57,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: fluent::infer::relate_param_bound, + msg: fluent::infer_relate_param_bound, name: &self.ty_to_string(ty), continues: opt_span.is_some(), } .add_to_diagnostic(err); if let Some(span) = opt_span { - RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 } + RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } .add_to_diagnostic(err); } } infer::RelateRegionParamBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound } + RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } .add_to_diagnostic(err); } infer::CompareImplItemObligation { span, .. } => { - RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation } + RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } .add_to_diagnostic(err); } infer::CheckAssociatedTypeBounds { ref parent, .. } => { @@ -80,7 +81,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { span, - msg: fluent::infer::ascribe_user_type_prove_predicate, + msg: fluent::infer_ascribe_user_type_prove_predicate, } .add_to_diagnostic(err); } |