Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ fn mir_borrowck(
let (input_body, _) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));

// We should eagerly check stalled coroutine obligations from HIR typeck.
// Not doing so leads to silent normalization failures later, which will
// fail to register opaque types in the next solver.
tcx.check_coroutine_obligations(def)?;

let input_body: &Body<'_> = &input_body.borrow();
if let Some(guar) = input_body.tainted_by_errors {
debug!("Skipping borrowck because of tainted body");
Expand Down
18 changes: 7 additions & 11 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
{
tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
}
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure_ok().mir_coroutine_witnesses(def_id);
let _ = tcx.ensure_ok().check_coroutine_obligations(
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
if tcx.is_coroutine(def_id.to_def_id())
&& (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
{
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) {
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
);
}
}
});
});
Expand Down
13 changes: 0 additions & 13 deletions tests/crashes/137916.rs

This file was deleted.

18 changes: 0 additions & 18 deletions tests/crashes/138274.rs

This file was deleted.

3 changes: 1 addition & 2 deletions tests/ui/async-await/issue-70818.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

use std::future::Future;
fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
//~^ ERROR future cannot be sent between threads safely
//~^ ERROR: future cannot be sent between threads safely
async { (ty, ty1) }
//~^ ERROR future cannot be sent between threads safely
}

fn main() {}
23 changes: 1 addition & 22 deletions tests/ui/async-await/issue-70818.stderr
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One less duplicate error.

Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
error: future cannot be sent between threads safely
--> $DIR/issue-70818.rs:6:5
|
LL | async { (ty, ty1) }
| ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: captured value is not `Send`
--> $DIR/issue-70818.rs:6:18
|
LL | async { (ty, ty1) }
| ^^^ has type `U` which is not `Send`
note: required by a bound in an opaque type
--> $DIR/issue-70818.rs:4:69
|
LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
| ^^^^
help: consider restricting type parameter `U` with trait `Send`
|
LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
| +++++++++++++++++++

error: future cannot be sent between threads safely
--> $DIR/issue-70818.rs:4:38
|
Expand All @@ -35,5 +14,5 @@ help: consider restricting type parameter `U` with trait `Send`
LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
| +++++++++++++++++++

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

1 change: 0 additions & 1 deletion tests/ui/async-await/issue-70935-complex-spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
fn foo(x: NotSync) -> impl Future + Send {
//~^ ERROR `*mut ()` cannot be shared between threads safely
async move {
//~^ ERROR `*mut ()` cannot be shared between threads safely
baz(|| async {
foo(x.clone());
}).await;
Expand Down
47 changes: 2 additions & 45 deletions tests/ui/async-await/issue-70935-complex-spans.stderr
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One less duplicate error.

Original file line number Diff line number Diff line change
@@ -1,46 +1,3 @@
error[E0277]: `*mut ()` cannot be shared between threads safely
--> $DIR/issue-70935-complex-spans.rs:17:5
|
LL | / async move {
LL | |
LL | | baz(|| async {
LL | | foo(x.clone());
LL | | }).await;
LL | | }
| |_____^ `*mut ()` cannot be shared between threads safely
|
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
note: required because it appears within the type `PhantomData<*mut ()>`
--> $SRC_DIR/core/src/marker.rs:LL:COL
note: required because it appears within the type `NotSync`
--> $DIR/issue-70935-complex-spans.rs:9:8
|
LL | struct NotSync(PhantomData<*mut ()>);
| ^^^^^^^
= note: required for `&NotSync` to implement `Send`
note: required because it's used within this closure
--> $DIR/issue-70935-complex-spans.rs:19:13
|
LL | baz(|| async {
| ^^
note: required because it's used within this `async` fn body
--> $DIR/issue-70935-complex-spans.rs:12:67
|
LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
| ___________________________________________________________________^
LL | | }
| |_^
note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:17:5
|
LL | async move {
| ^^^^^^^^^^
note: required by a bound in an opaque type
--> $DIR/issue-70935-complex-spans.rs:15:37
|
LL | fn foo(x: NotSync) -> impl Future + Send {
| ^^^^

error[E0277]: `*mut ()` cannot be shared between threads safely
--> $DIR/issue-70935-complex-spans.rs:15:23
|
Expand All @@ -57,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>);
| ^^^^^^^
= note: required for `&NotSync` to implement `Send`
note: required because it's used within this closure
--> $DIR/issue-70935-complex-spans.rs:19:13
--> $DIR/issue-70935-complex-spans.rs:18:13
|
LL | baz(|| async {
| ^^
Expand All @@ -74,6 +31,6 @@ note: required because it's used within this `async` block
LL | async move {
| ^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
1 change: 0 additions & 1 deletion tests/ui/coroutine/issue-105084.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ fn main() {
// one inside `g` and one inside `h`.
// Proceed and drop `t` in `g`.
Pin::new(&mut g).resume(());
//~^ ERROR borrow of moved value: `g`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we check stalled_coroutine_obligations before actual borrowck, we won't have borrowck diagnostics if those obligations fail.
I hope this is okay since HIR typeck failure also causes us skipping borrowck.
And stalled_coroutine_obligations should belong to HIR typeck if not for query cycle issue.


// Proceed and drop `t` in `h` -> double free!
Pin::new(&mut h).resume(());
Expand Down
29 changes: 2 additions & 27 deletions tests/ui/coroutine/issue-105084.stderr
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
error[E0382]: borrow of moved value: `g`
--> $DIR/issue-105084.rs:38:14
|
LL | let mut g = #[coroutine]
| ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait
...
LL | let mut h = copy(g);
| - value moved here
...
LL | Pin::new(&mut g).resume(());
| ^^^^^^ value borrowed here after move
|
note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary
--> $DIR/issue-105084.rs:10:21
|
LL | fn copy<T: Copy>(x: T) -> T {
| ---- ^ this parameter takes ownership of the value
| |
| in this function
help: consider cloning the value if the performance cost is acceptable
|
LL | let mut h = copy(g.clone());
| ++++++++

error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
--> $DIR/issue-105084.rs:32:17
|
Expand All @@ -45,7 +21,6 @@ note: required by a bound in `copy`
LL | fn copy<T: Copy>(x: T) -> T {
| ^^^^ required by this bound in `copy`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0277, E0382.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0277`.
32 changes: 32 additions & 0 deletions tests/ui/coroutine/stalled-coroutine-obligations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//@ edition: 2021

// Regression tests for #137916 and #138274
// We now check stalled coroutine obligations eagerly at the start of `mir_borrowck`.
// So these unsatisfied bounds are caught before causing ICEs.
use std::ptr::null;

async fn a() -> Box<dyn Send> {
Box::new(async {
//~^ ERROR: future cannot be sent between threads safely
let non_send = null::<()>();
&non_send;
async {}.await
})
}


trait Trait {}
fn foo() -> Box<dyn Trait> { todo!() }

fn fetch() {
async {
let fut = async {
let _x = foo();
async {}.await;
};
let _: Box<dyn Send> = Box::new(fut);
//~^ ERROR: future cannot be sent between threads safely
};
}

fn main() {}
40 changes: 40 additions & 0 deletions tests/ui/coroutine/stalled-coroutine-obligations.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
error: future cannot be sent between threads safely
--> $DIR/stalled-coroutine-obligations.rs:9:5
|
LL | / Box::new(async {
LL | |
LL | | let non_send = null::<()>();
LL | | &non_send;
LL | | async {}.await
LL | | })
| |______^ future created by async block is not `Send`
|
= help: within `{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}`, the trait `Send` is not implemented for `*const ()`
note: future is not `Send` as this value is used across an await
--> $DIR/stalled-coroutine-obligations.rs:13:18
|
LL | let non_send = null::<()>();
| -------- has type `*const ()` which is not `Send`
LL | &non_send;
LL | async {}.await
| ^^^^^ await occurs here, with `non_send` maybe used later
= note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}>` to `Box<dyn Send>`

error: future cannot be sent between threads safely
--> $DIR/stalled-coroutine-obligations.rs:27:32
|
LL | let _: Box<dyn Send> = Box::new(fut);
| ^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Send` is not implemented for `dyn Trait`
note: future is not `Send` as this value is used across an await
--> $DIR/stalled-coroutine-obligations.rs:25:22
|
LL | let _x = foo();
| -- has type `Box<dyn Trait>` which is not `Send`
LL | async {}.await;
| ^^^^^ await occurs here, with `_x` maybe used later
= note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:23:19: 23:24}>` to `Box<dyn Send>`

error: aborting due to 2 previous errors

50 changes: 50 additions & 0 deletions tests/ui/traits/next-solver/stalled-coroutine-obligations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//@ edition: 2024
//@ compile-flags: -Znext-solver --diagnostic-width=300

// Previously we check stalled coroutine obligations after borrowck pass.
// And we wrongly assume that these obligations hold in borrowck which leads to
// silent normalization failures.
// In the next solver, we register opaques types via `NormalizesTo` goals.
// So these failures also cause those opaques types not registered in storage.
//
// Regression test for #151322 and #151323.

#![feature(type_alias_impl_trait)]
#![feature(negative_impls)]
#![feature(auto_traits)]

fn stalled_copy_clone() {
type T = impl Copy;
let foo: T = async {};
//~^ ERROR: the trait bound

type U = impl Clone;
let bar: U = async {};
//~^ ERROR: the trait bound
}

auto trait Valid {}
struct False;
impl !Valid for False {}

fn stalled_auto_traits() {
type T = impl Valid;
let a = False;
let foo: T = async { a };
//~^ ERROR: the trait bound `False: Valid` is not satisfied
}


trait Trait {
fn stalled_send(&self, b: *mut ()) -> impl Future + Send {
//~^ ERROR: type mismatch resolving
//~| ERROR: type mismatch resolving
async move {
//~^ ERROR: type mismatch resolving
b
}
}
}


fn main() {}
Loading
Loading