diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index f8ae9adebe3..394a263fbb5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::{ use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; +use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -124,16 +125,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into_iter() .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); - for (base_trait_ref, span) in regular_traits_refs_spans { + for (base_trait_ref, original_span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx); - for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { + for ClauseWithSupertraitSpan { pred, original_span, supertrait_span } in + traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)]) + .filter_only_self() + { debug!("observing object predicate `{pred:?}`"); let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { let pred = bound_predicate.rebind(pred); - associated_types.entry(span).or_default().extend( + associated_types.entry(original_span).or_default().extend( tcx.associated_items(pred.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) @@ -172,10 +176,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - projection_bounds.push((pred, span)); + projection_bounds.push((pred, original_span)); } - self.check_elaborated_projection_mentions_input_lifetimes(pred, span); + self.check_elaborated_projection_mentions_input_lifetimes( + pred, + original_span, + supertrait_span, + ); } _ => (), } @@ -371,6 +379,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, pred: ty::PolyProjectionPredicate<'tcx>, span: Span, + supertrait_span: Span, ) { let tcx = self.tcx(); @@ -407,6 +416,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_name, br_name ) + .with_span_label(supertrait_span, "due to this supertrait") }, ); } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index fd4e8f1cd4e..d20cb368278 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -179,6 +179,10 @@ pub struct Clause<'tcx>( ); impl<'tcx> rustc_type_ir::inherent::Clause> for Clause<'tcx> { + fn as_predicate(self) -> Predicate<'tcx> { + self.as_predicate() + } + fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self { self.instantiate_supertrait(tcx, trait_ref) } diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 61736633cfa..dac45ff2aba 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -44,6 +44,46 @@ pub trait Elaboratable { ) -> Self; } +pub struct ClauseWithSupertraitSpan { + pub pred: I::Predicate, + // Span of the original elaborated predicate. + pub original_span: I::Span, + // Span of the supertrait predicatae that lead to this clause. + pub supertrait_span: I::Span, +} +impl ClauseWithSupertraitSpan { + pub fn new(pred: I::Predicate, span: I::Span) -> Self { + ClauseWithSupertraitSpan { pred, original_span: span, supertrait_span: span } + } +} +impl Elaboratable for ClauseWithSupertraitSpan { + fn predicate(&self) -> ::Predicate { + self.pred + } + + fn child(&self, clause: ::Clause) -> Self { + ClauseWithSupertraitSpan { + pred: clause.as_predicate(), + original_span: self.original_span, + supertrait_span: self.supertrait_span, + } + } + + fn child_with_derived_cause( + &self, + clause: ::Clause, + supertrait_span: ::Span, + _parent_trait_pred: crate::Binder>, + _index: usize, + ) -> Self { + ClauseWithSupertraitSpan { + pred: clause.as_predicate(), + original_span: self.original_span, + supertrait_span: supertrait_span, + } + } +} + pub fn elaborate>( cx: I, obligations: impl IntoIterator, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 59a83ea5412..69665df4bfc 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -460,6 +460,8 @@ pub trait Clause>: + IntoKind>> + Elaboratable { + fn as_predicate(self) -> I::Predicate; + fn as_trait_clause(self) -> Option>> { self.kind() .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None }) diff --git a/tests/ui/traits/object/elaborated-predicates-unconstrained-late-bound.stderr b/tests/ui/traits/object/elaborated-predicates-unconstrained-late-bound.stderr index bb3cc4b3fd7..067eaf5e7f3 100644 --- a/tests/ui/traits/object/elaborated-predicates-unconstrained-late-bound.stderr +++ b/tests/ui/traits/object/elaborated-predicates-unconstrained-late-bound.stderr @@ -1,6 +1,9 @@ error[E0582]: binding for associated type `T` references lifetime `'a`, which does not appear in the trait input types --> $DIR/elaborated-predicates-unconstrained-late-bound.rs:19:21 | +LL | trait A: B {} + | ----- due to this supertrait +... LL | Erase:: A<&'a _>>(x.as_str()) | ^^^^^^^^^^^^^^^^