Skip to content

Commit

Permalink
Check elaborated projections from dyn don't mention unconstrained lat…
Browse files Browse the repository at this point in the history
…e bound lifetimes
  • Loading branch information
compiler-errors committed Oct 4, 2024
1 parent 14f303b commit ae5f58d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Include projections defined on supertraits.
projection_bounds.push((pred, span));
}

self.check_elaborated_projection_mentions_input_lifetimes(pred, span);
}
_ => (),
}
Expand Down Expand Up @@ -360,6 +362,54 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
}

/// Check that elaborating the principal of a trait ref doesn't lead to projections
/// that are unconstrained. This can happen because an otherwise unconstrained
/// *type variable* can be substituted with a type that has late-bound regions. See
/// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
fn check_elaborated_projection_mentions_input_lifetimes(
&self,
pred: ty::PolyProjectionPredicate<'tcx>,
span: Span,
) {
let tcx = self.tcx();

// Find any late-bound regions declared in `ty` that are not
// declared in the trait-ref or assoc_item. These are not well-formed.
//
// Example:
//
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
let late_bound_in_projection_term =
tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
let late_bound_in_term =
tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
debug!(?late_bound_in_projection_term);
debug!(?late_bound_in_term);

// FIXME: point at the type params that don't have appropriate lifetimes:
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
// ---- ---- ^^^^^^^
// NOTE(associated_const_equality): This error should be impossible to trigger
// with associated const equality constraints.
self.validate_late_bound_regions(
late_bound_in_projection_term,
late_bound_in_term,
|br_name| {
let item_name = tcx.item_name(pred.projection_def_id());
struct_span_code_err!(
self.dcx(),
span,
E0582,
"binding for associated type `{}` references {}, \
which does not appear in the trait input types",
item_name,
br_name
)
},
);
}
}

fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Make sure that when elaborating the principal of a dyn trait for projection predicates
// we don't end up in a situation where we have an unconstrained late-bound lifetime in
// the output of a projection.

// Fix for <https://github.com/rust-lang/rust/issues/130347>.

trait A<T>: B<T = T> {}

trait B {
type T;
}

struct Erase<T: ?Sized + B>(T::T);

fn main() {
let x = {
let x = String::from("hello");

Erase::<dyn for<'a> A<&'a _>>(x.as_str())
//~^ ERROR binding for associated type `T` references lifetime `'a`, which does not appear in the trait input types
};

dbg!(x.0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +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 | Erase::<dyn for<'a> A<&'a _>>(x.as_str())
| ^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0582`.
4 changes: 2 additions & 2 deletions tests/ui/traits/object/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ trait SuperGeneric<'a> {
}
trait AnyGeneric<'a>: SuperGeneric<'a> {}
trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {}
trait FixedGeneric2<'a>: Super<Assoc = &'a u8> {}
// trait FixedGeneric2<'a>: Super<Assoc = &'a u8> {} // Unsound!
trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {}
trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {}
trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {}
Expand All @@ -32,7 +32,7 @@ fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types
fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types
fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types
fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types
fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types
// fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } // Unsound!
fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types
fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types
fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types
Expand Down
13 changes: 1 addition & 12 deletions tests/ui/traits/object/pretty.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,6 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
= note: expected unit type `()`
found reference `&dyn for<'a> FixedGeneric1<'a>`

error[E0308]: mismatched types
--> $DIR/pretty.rs:35:60
|
LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x }
| - ^ expected `()`, found `&dyn FixedGeneric2<'a>`
| |
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>`
|
= note: expected unit type `()`
found reference `&dyn for<'a> FixedGeneric2<'a>`

error[E0308]: mismatched types
--> $DIR/pretty.rs:36:79
|
Expand Down Expand Up @@ -172,6 +161,6 @@ LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
= note: expected unit type `()`
found reference `&dyn HasGat<u8, Assoc<bool> = ()>`

error: aborting due to 15 previous errors; 1 warning emitted
error: aborting due to 14 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0308`.

0 comments on commit ae5f58d

Please sign in to comment.