Skip to content

Commit

Permalink
Elaborate supertrait span correctly to label the error better
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 14, 2024
1 parent 809121f commit f16d211
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 5 deletions.
20 changes: 15 additions & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_middle::ty::{
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::traits::report_object_safety_error;
use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations};
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
use smallvec::{smallvec, SmallVec};
use tracing::{debug, instrument};

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
);
}
_ => (),
}
Expand Down Expand Up @@ -369,6 +377,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
pred: ty::PolyProjectionPredicate<'tcx>,
span: Span,
supertrait_span: Span,
) {
let tcx = self.tcx();

Expand Down Expand Up @@ -405,6 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
item_name,
br_name
)
.with_span_label(supertrait_span, "due to this supertrait")
},
);
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ pub struct Clause<'tcx>(
);

impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> 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)
}
Expand Down
40 changes: 40 additions & 0 deletions compiler/rustc_type_ir/src/elaborate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,46 @@ pub trait Elaboratable<I: Interner> {
) -> Self;
}

pub struct ClauseWithSupertraitSpan<I: Interner> {
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<I: Interner> ClauseWithSupertraitSpan<I> {
pub fn new(pred: I::Predicate, span: I::Span) -> Self {
ClauseWithSupertraitSpan { pred, original_span: span, supertrait_span: span }
}
}
impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
fn predicate(&self) -> <I as Interner>::Predicate {
self.pred
}

fn child(&self, clause: <I as Interner>::Clause) -> Self {
ClauseWithSupertraitSpan {
pred: clause.as_predicate(),
original_span: self.original_span,
supertrait_span: self.supertrait_span,
}
}

fn child_with_derived_cause(
&self,
clause: <I as Interner>::Clause,
supertrait_span: <I as Interner>::Span,
_parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
_index: usize,
) -> Self {
ClauseWithSupertraitSpan {
pred: clause.as_predicate(),
original_span: self.original_span,
supertrait_span: supertrait_span,
}
}
}

pub fn elaborate<I: Interner, O: Elaboratable<I>>(
cx: I,
obligations: impl IntoIterator<Item = O>,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
+ Elaboratable<I>
{
fn as_predicate(self) -> I::Predicate;

fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
self.kind()
.map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T>: B<T = T> {}
| ----- due to this supertrait
...
LL | Erase::<dyn for<'a> A<&'a _>>(x.as_str())
| ^^^^^^^^^^^^^^^^

Expand Down

0 comments on commit f16d211

Please sign in to comment.