Skip to content

Commit 3e44c90

Browse files
committed
wf: ignore nested obligations with placeholders
1 parent 8d1ad7b commit 3e44c90

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

compiler/rustc_trait_selection/src/traits/wf.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,12 @@ pub fn predicate_obligations<'tcx>(
177177
/// `for<'a> where { T: 'a } fn(&'a T)`, at which point the `T: 'a` bound is
178178
/// trivially implied from the `param_env`.
179179
///
180-
/// This means that we WF bounds aren't always sufficiently checked for now.
180+
/// This means that we WF bounds aren't always sufficiently checked for now.
181181
fn emit_obligations_for<'tcx, T: TypeVisitable<'tcx>>(value: T) -> bool {
182-
!value.has_escaping_bound_vars()
182+
// We also don't emit obligations for placeholders. This will be incorrect
183+
// if we ever decide to also replace `ty::Param` with placeholders during
184+
// canonicalization or whatever. Hopefully we will have implications by then.
185+
!value.has_escaping_bound_vars() && !value.has_placeholders()
183186
}
184187

185188
struct WfPredicates<'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Checks that manual WF bounds are not use for implied bounds.
2+
//
3+
// With the current implementation for WF check, this can easily cause
4+
// unsoundness, as wf does not emit any obligations containing
5+
// placeholders or bound variables.
6+
struct MyStruct<T, U>(T, U);
7+
8+
trait Foo<'a, 'b> {}
9+
10+
// IF THIS TEST STOPS EMITTING ERRORS, PLEASE NOTIFY T-TYPES TO CHECK WHETHER THE CHANGE IS SOUND.
11+
impl<'a, 'b> Foo<'a, 'b> for () //~ ERROR cannot infer an appropriate lifetime
12+
where
13+
&'a &'b ():,
14+
//~^ ERROR in type `&'a &'b ()`, reference has a longer lifetime than the data it references
15+
{}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
2+
--> $DIR/on-impl-not-implied.rs:11:14
3+
|
4+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
5+
| ^^^^^^^^^^^
6+
|
7+
note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
8+
--> $DIR/on-impl-not-implied.rs:11:10
9+
|
10+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
11+
| ^^
12+
note: ...but the lifetime must also be valid for the lifetime `'a` as defined here...
13+
--> $DIR/on-impl-not-implied.rs:11:6
14+
|
15+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
16+
| ^^
17+
note: ...so that the types are compatible
18+
--> $DIR/on-impl-not-implied.rs:11:14
19+
|
20+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
21+
| ^^^^^^^^^^^
22+
= note: expected `Foo<'a, 'b>`
23+
found `Foo<'_, '_>`
24+
25+
error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references
26+
--> $DIR/on-impl-not-implied.rs:13:5
27+
|
28+
LL | &'a &'b ():,
29+
| ^^^^^^^^^^
30+
|
31+
note: the pointer is valid for the lifetime `'a` as defined here
32+
--> $DIR/on-impl-not-implied.rs:11:6
33+
|
34+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
35+
| ^^
36+
note: but the referenced data is only valid for the lifetime `'b` as defined here
37+
--> $DIR/on-impl-not-implied.rs:11:10
38+
|
39+
LL | impl<'a, 'b> Foo<'a, 'b> for ()
40+
| ^^
41+
42+
error: aborting due to 2 previous errors
43+
44+
Some errors have detailed explanations: E0491, E0495.
45+
For more information about an error, try `rustc --explain E0491`.
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
trait Foo<A> {}
3+
impl<'a, T: Foo<A>, A> Foo<A> for &'a mut T
4+
where
5+
// Needed to use `(A,)` because `A:` by itself doesn't emit a WF bound
6+
// as of writing this comment.
7+
//
8+
// This happens in `fn explicit_predicates_of`.
9+
(A,):,
10+
{}
11+
12+
fn tragic<T, F: for<'a> Foo<&'a T>>(_: F) {}
13+
fn oh_no<T, F: for<'a> Foo<&'a T>>(mut f: F) {
14+
// This results in a `for<'a> WF(&'a T)` bound where `'a` is replaced
15+
// with a placeholder before we compute the wf requirements.
16+
//
17+
// This bound would otherwise result in a `T: 'static` bound.
18+
tragic::<T, _>(&mut f);
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)