Skip to content

Commit 131ea2c

Browse files
committed
erase regions in cause code
1 parent f7f6199 commit 131ea2c

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14991499
};
15001500

15011501
if let ObligationCauseCode::ImplDerived(cause) = &*code {
1502-
try_borrowing(cause.derived.parent_trait_pred, &[])
1502+
// Parent trait predicate may contain regions that's already popped.
1503+
// We can erase them since evaluation later doesn't care about regions anyway.
1504+
let parent_trait_pred =
1505+
self.tcx.erase_and_anonymize_regions(cause.derived.parent_trait_pred);
1506+
try_borrowing(parent_trait_pred, &[])
15031507
} else if let ObligationCauseCode::WhereClause(..)
15041508
| ObligationCauseCode::WhereClauseInExpr(..) = code
15051509
{
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 already popped off when using parent predicate in cause code.
6+
7+
trait AsyncFn: Send + 'static {
8+
type Fut: Future<Output = ()> + Send;
9+
10+
fn call(&self) -> Self::Fut;
11+
}
12+
13+
async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
14+
filter.call().await;
15+
}
16+
17+
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
18+
todo!()
19+
}
20+
21+
async fn cursed_fut() {
22+
wrap_call(get_boxed_fn().as_ref()).await;
23+
}
24+
25+
fn observe_fut_not_send() {
26+
assert_send(cursed_fut());
27+
//~^ ERROR: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely [E0277]
28+
}
29+
30+
fn assert_send<T: Send>(t: T) -> T {
31+
t
32+
}
33+
34+
pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
35+
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
36+
37+
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/outdated-region-in-cause-code.rs:26: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/outdated-region-in-cause-code.rs:13: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/outdated-region-in-cause-code.rs:21: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/outdated-region-in-cause-code.rs:30: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`.

0 commit comments

Comments
 (0)