diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 90d12ea832857..daef0d19d68c3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::{ }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError; use rustc_trait_selection::traits::ObligationCtxt; use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; @@ -464,6 +465,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( *trace, infcx.tcx.param_env(generic_param_scope), 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 e176fc589995f..31d3ed3df3364 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; @@ -639,6 +640,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( }))), terr, false, + TypeErrorRole::Elsewhere, ); return Err(diag.emit()); } @@ -1060,6 +1062,7 @@ fn report_trait_method_mismatch<'tcx>( }))), terr, false, + TypeErrorRole::Elsewhere, ); diag.emit() @@ -1852,6 +1855,7 @@ fn compare_const_predicate_entailment<'tcx>( }))), terr, 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 61e203a1ff668..a13b04acf63c2 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -92,7 +92,7 @@ use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; -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::traits::ObligationCtxt; use tracing::debug; @@ -651,6 +651,7 @@ pub fn check_function_signature<'tcx>( }))), err, 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 6b1cceefbeea1..ebdeb461ca744 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::{Ident, kw}; use rustc_span::{DUMMY_SP, Span, sym}; -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; @@ -830,6 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), self.param_env, terr, + TypeErrorRole::Elsewhere, ); err.span_label( full_call_span, @@ -942,8 +945,12 @@ 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, self.param_env, *e); + let mut err = self.err_ctxt().report_and_explain_type_error( + trace, + self.param_env, + *e, + TypeErrorRole::Elsewhere, + ); suggest_confusable(&mut err); reported = Some(err.emit()); return false; @@ -971,7 +978,12 @@ 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, self.param_env, err); + let mut err = self.err_ctxt().report_and_explain_type_error( + trace, + self.param_env, + err, + TypeErrorRole::Elsewhere, + ); self.emit_coerce_suggestions( &mut err, provided_args[provided_idx], @@ -1148,6 +1160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(self.param_env.and(trace.values)), e, true, + TypeErrorRole::Elsewhere, ); } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index ef431c852e94b..112ffb407d407 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -531,7 +531,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { Err(terr) => { if self.tcx.features().arbitrary_self_types() { self.err_ctxt() - .report_mismatched_types( + .report_mismatched_self_types( &cause, self.param_env, method_self_ty, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ee197ce07ca71..dd11b3555d92d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -35,6 +35,7 @@ use rustc_span::{BytePos, DUMMY_SP, Span}; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::error_reporting::infer::TypeErrorRole; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; @@ -2371,6 +2372,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }))), terr, 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 5a62a4c3bd5fe..f9aa2e45d26bd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -92,6 +92,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 { @@ -159,6 +168,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeTrace::types(cause, expected, actual), param_env, err, + TypeErrorRole::Elsewhere, + ) + } + + pub fn report_mismatched_self_types( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + expected: Ty<'tcx>, + actual: Ty<'tcx>, + err: TypeError<'tcx>, + ) -> Diag<'a> { + self.report_and_explain_type_error( + TypeTrace::types(cause, expected, actual), + param_env, + err, + TypeErrorRole::SelfType, ) } @@ -174,6 +200,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeTrace::consts(cause, expected, actual), param_env, err, + TypeErrorRole::Elsewhere, ) } @@ -1376,6 +1403,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { mut values: Option>>, terr: TypeError<'tcx>, prefer_label: bool, + role: TypeErrorRole, ) { let span = cause.span; @@ -1839,6 +1867,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + 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) @@ -2026,8 +2058,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'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( @@ -2043,6 +2079,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(param_env.and(trace.values)), terr, 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 9fd7dccc57ccb..9095d87442f51 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -17,8 +17,8 @@ use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol}; use rustc_type_ir::Upcast as _; use tracing::{debug, instrument}; -use super::ObligationCauseAsDiagArg; use super::nice_region_error::find_anon_type; +use super::{ObligationCauseAsDiagArg, TypeErrorRole}; use crate::error_reporting::TypeErrCtxt; use crate::error_reporting::infer::ObligationCauseExt; use crate::errors::{ @@ -299,6 +299,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trace, self.tcx.param_env(generic_param_scope), terr, + TypeErrorRole::Elsewhere, ); match (*sub, *sup) { (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} @@ -654,6 +655,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trace, self.tcx.param_env(generic_param_scope), terr, + TypeErrorRole::Elsewhere, ); } _ => { 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 4fb02f609438e..1a712285c1ac6 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 @@ -38,7 +38,7 @@ use super::{ UnsatisfiedConst, }; use crate::error_reporting::TypeErrCtxt; -use crate::error_reporting::infer::TyCategory; +use crate::error_reporting::infer::{TyCategory, TypeErrorRole}; use crate::error_reporting::traits::report_dyn_incompatibility; use crate::errors::{ AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, @@ -727,6 +727,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)), false, + TypeErrorRole::Elsewhere ); diag } @@ -1455,6 +1456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), err, false, + TypeErrorRole::Elsewhere, ); self.note_obligation_cause(&mut diag, obligation); diag.emit() @@ -2741,6 +2743,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeTrace::trait_refs(&cause, expected_trait_ref, found_trait_ref), obligation.param_env, terr, + TypeErrorRole::Elsewhere, ) } @@ -2832,6 +2835,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref), obligation.param_env, ty::error::TypeError::Mismatch, + TypeErrorRole::Elsewhere, )); } if found.len() != expected.len() { diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr index 9af2a08f3712d..225bc1884cc6a 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr @@ -39,12 +39,16 @@ error[E0308]: mismatched types | LL | assert_eq!(foo.a::<&Foo>(), 2); | ^^^ expected `&Foo`, found `Foo` + | + = note: this error occurred while resolving the `self` type of this method call error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:53:16 | LL | assert_eq!(foo.b::<&Foo>(), 1); | ^^^ expected `&Foo`, found `Foo` + | + = note: this error occurred while resolving the `self` type of this method call error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:60:16 @@ -54,6 +58,7 @@ LL | assert_eq!(smart_ptr.a::<&Foo>(), 2); | = note: expected reference `&Foo` found struct `SmartPtr<'_, Foo, >` + = note: this error occurred while resolving the `self` type of this method call error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16 @@ -63,6 +68,7 @@ LL | assert_eq!(smart_ptr.b::<&Foo>(), 1); | = note: expected reference `&Foo` found struct `SmartPtr<'_, Foo, >` + = note: this error occurred while resolving the `self` type of this method call error: aborting due to 8 previous errors 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 6e864f44aa348..fca7b5dacc0a6 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -57,6 +57,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[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs.rs:78:5 @@ -66,6 +68,7 @@ LL | foo.get::>(); | = note: expected struct `Rc` found struct `Foo` + = note: this error occurred while resolving the `self` type of this method call error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs.rs:84:5 @@ -75,6 +78,7 @@ LL | smart_ptr.get::>(); | = note: expected struct `SmartPtr2<'_, Foo>` found struct `SmartPtr<'_, Foo>` + = note: this error occurred while resolving the `self` type of this method call error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs.rs:86:5 @@ -84,6 +88,7 @@ LL | smart_ptr.get::<&Foo>(); | = note: expected reference `&Foo` found struct `SmartPtr<'_, Foo, >` + = note: this error occurred while resolving the `self` type of this method call error[E0271]: type mismatch resolving `::Receiver == Foo` --> $DIR/arbitrary-self-from-method-substs.rs:92:9