diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 8a4e89d47bdc0..9439788079208 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{ }; use rustc_span::Span; use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::ObligationCtxt; @@ -482,12 +483,11 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( .try_report_from_nll() .or_else(|| { if let SubregionOrigin::Subtype(trace) = cause { - Some( - infcx.err_ctxt().report_and_explain_type_error( - *trace, - TypeError::RegionsPlaceholderMismatch, - ), - ) + Some(infcx.err_ctxt().report_and_explain_type_error( + *trace, + TypeError::RegionsPlaceholderMismatch, + TypeErrorRole::Elsewhere, + )) } else { None } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2afed04c5bcd5..6222633b9ea64 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_span::Span; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -612,6 +613,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( terr, false, false, + TypeErrorRole::Elsewhere, ); return Err(diag.emit()); } @@ -1036,6 +1038,7 @@ fn report_trait_method_mismatch<'tcx>( terr, false, false, + TypeErrorRole::Elsewhere, ); return diag.emit(); @@ -1843,6 +1846,7 @@ fn compare_const_predicate_entailment<'tcx>( terr, false, false, + TypeErrorRole::Elsewhere, ); return Err(diag.emit()); }; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 6820a44f141bd..2a83d72719c0f 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -93,7 +93,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; -use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _; +use rustc_trait_selection::error_reporting::infer::{ObligationCauseExt as _, TypeErrorRole}; use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::ObligationCtxt; @@ -656,6 +656,7 @@ pub fn check_function_signature<'tcx>( err, false, false, + TypeErrorRole::Elsewhere, ); return Err(diag.emit()); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bdf84f332166d..39b8abecd321f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -24,7 +24,9 @@ use rustc_middle::{bug, span_bug}; use rustc_session::Session; use rustc_span::symbol::{kw, Ident}; use rustc_span::{sym, Span, DUMMY_SP}; -use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; +use rustc_trait_selection::error_reporting::infer::{ + FailureCode, ObligationCauseExt, TypeErrorRole, +}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; use tracing::debug; @@ -826,6 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_arg_tys[mismatch_idx.into()].0, ), terr, + TypeErrorRole::Elsewhere, ); err.span_label( full_call_span, @@ -909,7 +912,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { - let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e); + let mut err = self.err_ctxt().report_and_explain_type_error( + trace, + *e, + TypeErrorRole::Elsewhere, + ); suggest_confusable(&mut err); reported = Some(err.emit()); return false; @@ -937,7 +944,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); - let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); + let mut err = self.err_ctxt().report_and_explain_type_error( + trace, + *err, + TypeErrorRole::Elsewhere, + ); self.emit_coerce_suggestions( &mut err, provided_args[*provided_idx], @@ -1113,6 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { e, false, true, + TypeErrorRole::Elsewhere, ); } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 10a22eee7b74a..b34266191f1f1 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -521,7 +521,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // to the feature, like the self type can't reference method args. if self.tcx.features().arbitrary_self_types { self.err_ctxt() - .report_mismatched_types(&cause, method_self_ty, self_ty, terr) + .report_mismatched_self_types(&cause, method_self_ty, self_ty, terr) .emit(); } else { // This has/will have errored in wfcheck, which we cannot depend on from here, as typeck on functions diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e41f89a3c9da9..397c9a14d3793 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -35,6 +35,7 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; @@ -2336,6 +2337,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { terr, false, false, + TypeErrorRole::Elsewhere, ); diag.emit(); self.abort.set(true); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 65d21518491da..5cb12e1ae6f9e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -87,6 +87,15 @@ pub mod nice_region_error; pub mod region; pub mod sub_relations; +/// A hint about where a type error occurred, for better diagnostics. +#[derive(Debug, PartialEq)] +pub enum TypeErrorRole { + /// This type error occurred while resolving the "self" type of a method + SelfType, + /// This type error occurred in any other context. + Elsewhere, +} + /// Makes a valid string literal from a string by escaping special characters (" and \), /// unless they are already escaped. fn escape_literal(s: &str) -> String { @@ -149,7 +158,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { actual: Ty<'tcx>, err: TypeError<'tcx>, ) -> Diag<'a> { - self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err) + self.report_and_explain_type_error( + TypeTrace::types(cause, true, expected, actual), + err, + TypeErrorRole::Elsewhere, + ) + } + + pub fn report_mismatched_self_types( + &self, + cause: &ObligationCause<'tcx>, + expected: Ty<'tcx>, + actual: Ty<'tcx>, + err: TypeError<'tcx>, + ) -> Diag<'a> { + self.report_and_explain_type_error( + TypeTrace::types(cause, true, expected, actual), + err, + TypeErrorRole::SelfType, + ) } pub fn report_mismatched_consts( @@ -159,7 +186,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { actual: ty::Const<'tcx>, err: TypeError<'tcx>, ) -> Diag<'a> { - self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err) + self.report_and_explain_type_error( + TypeTrace::consts(cause, true, expected, actual), + err, + TypeErrorRole::Elsewhere, + ) } pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { @@ -1140,6 +1171,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { terr: TypeError<'tcx>, swap_secondary_and_primary: bool, prefer_label: bool, + role: TypeErrorRole, ) { let span = cause.span(); @@ -1601,6 +1633,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.check_and_note_conflicting_crates(diag, terr); + if role == TypeErrorRole::SelfType { + diag.note("this error occurred while resolving the `self` type of this method call"); + } + self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id()); if let Some(exp_found) = exp_found && let exp_found = TypeError::Sorts(exp_found) @@ -1783,8 +1819,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, trace: TypeTrace<'tcx>, terr: TypeError<'tcx>, + role: TypeErrorRole, ) -> Diag<'a> { - debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); + debug!( + "report_and_explain_type_error(trace={:?}, terr={:?}, role={:?})", + trace, terr, role + ); let span = trace.cause.span(); let failure_code = trace.cause.as_failure_code_diag( @@ -1793,7 +1833,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.type_error_additional_suggestions(&trace, terr), ); let mut diag = self.dcx().create_err(failure_code); - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false); + self.note_type_err( + &mut diag, + &trace.cause, + None, + Some(trace.values), + terr, + false, + false, + role, + ); diag } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..5122d754797bc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -18,7 +18,7 @@ use rustc_type_ir::Upcast as _; use tracing::{debug, instrument}; use super::nice_region_error::find_anon_type; -use super::ObligationCauseAsDiagArg; +use super::{ObligationCauseAsDiagArg, TypeErrorRole}; use crate::error_reporting::infer::ObligationCauseExt; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -295,7 +295,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut err = match origin { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - let mut err = self.report_and_explain_type_error(trace, terr); + let mut err = + self.report_and_explain_type_error(trace, terr, TypeErrorRole::Elsewhere); match (*sub, *sup) { (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} (ty::RePlaceholder(_), _) => { @@ -638,7 +639,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } infer::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; - return self.report_and_explain_type_error(trace, terr); + return self.report_and_explain_type_error(trace, terr, TypeErrorRole::Elsewhere); } _ => { return self.report_concrete_failure( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 5918686213a78..e114b11a829a7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -35,7 +35,7 @@ use super::suggestions::get_explanation_based_on_obligation; use super::{ ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate, UnsatisfiedConst, }; -use crate::error_reporting::infer::TyCategory; +use crate::error_reporting::infer::{TyCategory, TypeErrorRole}; use crate::error_reporting::traits::report_object_safety_error; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -667,6 +667,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)), false, false, + TypeErrorRole::Elsewhere ); diag } @@ -1410,6 +1411,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err, true, false, + TypeErrorRole::Elsewhere, ); self.note_obligation_cause(&mut diag, obligation); diag.emit() @@ -2556,6 +2558,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.report_and_explain_type_error( TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref), terr, + TypeErrorRole::Elsewhere, ) } @@ -2653,6 +2656,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found_trait_ref, ), ty::error::TypeError::Mismatch, + TypeErrorRole::Elsewhere, ) } else if found.len() == expected.len() { self.report_closure_arg_mismatch( diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr index 44e553f1a06ca..99556377e4709 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -3,6 +3,8 @@ error[E0308]: mismatched types | LL | foo.get::<&Foo>(); | ^^^ expected `&Foo`, found `Foo` + | + = note: this error occurred while resolving the `self` type of this method call error: aborting due to 1 previous error