Skip to content

Commit 904b6fc

Browse files
authored
Unrolled build for #149299
Rollup merge of #149299 - adwinwhite:next-245-ice, r=lcnr Fudge infer vars in the cause code of `Obligation` intentionally Fixes the ICE variant in rust-lang/trait-system-refactor-initiative#245. Fixes #142866. The detailed cause is in the test comments. r? `@lcnr`
2 parents 2fb8053 + b111aed commit 904b6fc

File tree

6 files changed

+152
-0
lines changed

6 files changed

+152
-0
lines changed

compiler/rustc_infer/src/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ use crate::infer::InferCtxt;
3737
#[derive(Clone, TypeFoldable, TypeVisitable)]
3838
pub struct Obligation<'tcx, T> {
3939
/// The reason we have to prove this thing.
40+
/// FIXME: we shouldn't ignore the cause but instead change the affected visitors
41+
/// to only visit predicates manually.
4042
#[type_foldable(identity)]
4143
#[type_visitable(ignore)]
4244
pub cause: ObligationCause<'tcx>,

compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,11 @@ fn find_best_leaf_obligation<'tcx>(
177177
)
178178
.break_value()
179179
.ok_or(())
180+
// walk around the fact that the cause in `Obligation` is ignored by folders so that
181+
// we can properly fudge the infer vars in cause code.
182+
.map(|o| (o.cause.clone(), o))
180183
})
184+
.map(|(cause, o)| PredicateObligation { cause, ..o })
181185
.unwrap_or(obligation);
182186
deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
183187
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ edition: 2024
3+
//
4+
// A regression test for the ICE variant in trait-system-refactor-initiative#245.
5+
// We'll meet regions that're already popped off when using parent predicate in cause code.
6+
// `cause` in `Obligation` is ignored by folders/visitors.
7+
// In this case, `fudge_inference_if_ok` doesn't fudge a region var in cause code.
8+
//
9+
// The old solver doesn't trigger ICE because regions in the predicate are replaced with
10+
// placeholders when checking generator witness. Besides, the old solver doesn't eagerly
11+
// resolves vars before canonicalizing the predicate in `predicate_must_hold_modulo_regions`.
12+
13+
trait AsyncFn: Send + 'static {
14+
type Fut: Future<Output = ()> + Send;
15+
16+
fn call(&self) -> Self::Fut;
17+
}
18+
19+
async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
20+
filter.call().await;
21+
}
22+
23+
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
24+
todo!()
25+
}
26+
27+
async fn cursed_fut() {
28+
wrap_call(get_boxed_fn().as_ref()).await;
29+
}
30+
31+
fn observe_fut_not_send() {
32+
assert_send(cursed_fut());
33+
//~^ ERROR: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely [E0277]
34+
}
35+
36+
fn assert_send<T: Send>(t: T) -> T {
37+
t
38+
}
39+
40+
pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
41+
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
42+
43+
fn main() {}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0277]: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
2+
--> $DIR/leaking-vars-in-cause-code-1.rs:32:17
3+
|
4+
LL | assert_send(cursed_fut());
5+
| ----------- ^^^^^^^^^^^^ `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Sync` is not implemented for `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>`
10+
= note: required for `&dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` to implement `Send`
11+
note: required because it's used within this `async` fn body
12+
--> $DIR/leaking-vars-in-cause-code-1.rs:19:53
13+
|
14+
LL | async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
15+
| _____________________________________________________^
16+
LL | | filter.call().await;
17+
LL | | }
18+
| |_^
19+
note: required because it's used within this `async` fn body
20+
--> $DIR/leaking-vars-in-cause-code-1.rs:27:23
21+
|
22+
LL | async fn cursed_fut() {
23+
| _______________________^
24+
LL | | wrap_call(get_boxed_fn().as_ref()).await;
25+
LL | | }
26+
| |_^
27+
note: required by a bound in `assert_send`
28+
--> $DIR/leaking-vars-in-cause-code-1.rs:36:19
29+
|
30+
LL | fn assert_send<T: Send>(t: T) -> T {
31+
| ^^^^ required by this bound in `assert_send`
32+
33+
error: aborting due to 1 previous error
34+
35+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ compile-flags: -Znext-solver
2+
3+
// The `cause` in `Obligation` is ignored by type folders. So infer vars in cause code is not
4+
// fudged.
5+
// Check the comments of
6+
// `leaking-vars-in-cause-code-1.rs` for more details.
7+
trait Trait<T> {}
8+
struct A<T>(T);
9+
struct B<T>(T);
10+
11+
trait IncompleteGuidance {}
12+
13+
impl<T> Trait<()> for A<T>
14+
where
15+
T: IncompleteGuidance,
16+
{
17+
}
18+
19+
impl<T, U> Trait<()> for B<T>
20+
//~^ ERROR: the type parameter `U` is not constrained by the impl trait, self type, or predicates
21+
where
22+
A<T>: Trait<U>,
23+
{
24+
}
25+
26+
fn impls_trait<T: Trait<()>>() {}
27+
28+
fn main() {
29+
impls_trait::<B<()>>();
30+
//~^ ERROR: the trait bound `(): IncompleteGuidance` is not satisfied
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/leaking-vars-in-cause-code-2.rs:19:9
3+
|
4+
LL | impl<T, U> Trait<()> for B<T>
5+
| ^ unconstrained type parameter
6+
7+
error[E0277]: the trait bound `(): IncompleteGuidance` is not satisfied
8+
--> $DIR/leaking-vars-in-cause-code-2.rs:29:19
9+
|
10+
LL | impls_trait::<B<()>>();
11+
| ^^^^^ the trait `IncompleteGuidance` is not implemented for `()`
12+
|
13+
help: this trait has no implementations, consider adding one
14+
--> $DIR/leaking-vars-in-cause-code-2.rs:11:1
15+
|
16+
LL | trait IncompleteGuidance {}
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^
18+
note: required for `A<()>` to implement `Trait<()>`
19+
--> $DIR/leaking-vars-in-cause-code-2.rs:13:9
20+
|
21+
LL | impl<T> Trait<()> for A<T>
22+
| ^^^^^^^^^ ^^^^
23+
LL | where
24+
LL | T: IncompleteGuidance,
25+
| ------------------ unsatisfied trait bound introduced here
26+
= note: 1 redundant requirement hidden
27+
= note: required for `B<()>` to implement `Trait<()>`
28+
note: required by a bound in `impls_trait`
29+
--> $DIR/leaking-vars-in-cause-code-2.rs:26:19
30+
|
31+
LL | fn impls_trait<T: Trait<()>>() {}
32+
| ^^^^^^^^^ required by this bound in `impls_trait`
33+
34+
error: aborting due to 2 previous errors
35+
36+
Some errors have detailed explanations: E0207, E0277.
37+
For more information about an error, try `rustc --explain E0207`.

0 commit comments

Comments
 (0)