Skip to content

Commit f16d211

Browse files
Elaborate supertrait span correctly to label the error better
1 parent 809121f commit f16d211

File tree

5 files changed

+64
-5
lines changed

5 files changed

+64
-5
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::{
1313
use rustc_span::{ErrorGuaranteed, Span};
1414
use rustc_trait_selection::error_reporting::traits::report_object_safety_error;
1515
use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations};
16+
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
1617
use smallvec::{smallvec, SmallVec};
1718
use tracing::{debug, instrument};
1819

@@ -124,16 +125,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
124125
.into_iter()
125126
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
126127

127-
for (base_trait_ref, span) in regular_traits_refs_spans {
128+
for (base_trait_ref, original_span) in regular_traits_refs_spans {
128129
let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx);
129-
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
130+
for ClauseWithSupertraitSpan { pred, original_span, supertrait_span } in
131+
traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)])
132+
.filter_only_self()
133+
{
130134
debug!("observing object predicate `{pred:?}`");
131135

132136
let bound_predicate = pred.kind();
133137
match bound_predicate.skip_binder() {
134138
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
135139
let pred = bound_predicate.rebind(pred);
136-
associated_types.entry(span).or_default().extend(
140+
associated_types.entry(original_span).or_default().extend(
137141
tcx.associated_items(pred.def_id())
138142
.in_definition_order()
139143
.filter(|item| item.kind == ty::AssocKind::Type)
@@ -172,10 +176,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
172176
// the discussion in #56288 for alternatives.
173177
if !references_self {
174178
// Include projections defined on supertraits.
175-
projection_bounds.push((pred, span));
179+
projection_bounds.push((pred, original_span));
176180
}
177181

178-
self.check_elaborated_projection_mentions_input_lifetimes(pred, span);
182+
self.check_elaborated_projection_mentions_input_lifetimes(
183+
pred,
184+
original_span,
185+
supertrait_span,
186+
);
179187
}
180188
_ => (),
181189
}
@@ -369,6 +377,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
369377
&self,
370378
pred: ty::PolyProjectionPredicate<'tcx>,
371379
span: Span,
380+
supertrait_span: Span,
372381
) {
373382
let tcx = self.tcx();
374383

@@ -405,6 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
405414
item_name,
406415
br_name
407416
)
417+
.with_span_label(supertrait_span, "due to this supertrait")
408418
},
409419
);
410420
}

compiler/rustc_middle/src/ty/predicate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ pub struct Clause<'tcx>(
179179
);
180180

181181
impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
182+
fn as_predicate(self) -> Predicate<'tcx> {
183+
self.as_predicate()
184+
}
185+
182186
fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
183187
self.instantiate_supertrait(tcx, trait_ref)
184188
}

compiler/rustc_type_ir/src/elaborate.rs

+40
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,46 @@ pub trait Elaboratable<I: Interner> {
4343
) -> Self;
4444
}
4545

46+
pub struct ClauseWithSupertraitSpan<I: Interner> {
47+
pub pred: I::Predicate,
48+
// Span of the original elaborated predicate.
49+
pub original_span: I::Span,
50+
// Span of the supertrait predicatae that lead to this clause.
51+
pub supertrait_span: I::Span,
52+
}
53+
impl<I: Interner> ClauseWithSupertraitSpan<I> {
54+
pub fn new(pred: I::Predicate, span: I::Span) -> Self {
55+
ClauseWithSupertraitSpan { pred, original_span: span, supertrait_span: span }
56+
}
57+
}
58+
impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
59+
fn predicate(&self) -> <I as Interner>::Predicate {
60+
self.pred
61+
}
62+
63+
fn child(&self, clause: <I as Interner>::Clause) -> Self {
64+
ClauseWithSupertraitSpan {
65+
pred: clause.as_predicate(),
66+
original_span: self.original_span,
67+
supertrait_span: self.supertrait_span,
68+
}
69+
}
70+
71+
fn child_with_derived_cause(
72+
&self,
73+
clause: <I as Interner>::Clause,
74+
supertrait_span: <I as Interner>::Span,
75+
_parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
76+
_index: usize,
77+
) -> Self {
78+
ClauseWithSupertraitSpan {
79+
pred: clause.as_predicate(),
80+
original_span: self.original_span,
81+
supertrait_span: supertrait_span,
82+
}
83+
}
84+
}
85+
4686
pub fn elaborate<I: Interner, O: Elaboratable<I>>(
4787
cx: I,
4888
obligations: impl IntoIterator<Item = O>,

compiler/rustc_type_ir/src/inherent.rs

+2
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
460460
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
461461
+ Elaboratable<I>
462462
{
463+
fn as_predicate(self) -> I::Predicate;
464+
463465
fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
464466
self.kind()
465467
.map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })

tests/ui/traits/object/elaborated-predicates-unconstrained-late-bound.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0582]: binding for associated type `T` references lifetime `'a`, which does not appear in the trait input types
22
--> $DIR/elaborated-predicates-unconstrained-late-bound.rs:19:21
33
|
4+
LL | trait A<T>: B<T = T> {}
5+
| ----- due to this supertrait
6+
...
47
LL | Erase::<dyn for<'a> A<&'a _>>(x.as_str())
58
| ^^^^^^^^^^^^^^^^
69

0 commit comments

Comments
 (0)