Skip to content

Commit 61f4528

Browse files
Stall coroutines based off of ty::Coroutine, not ty::CoroutineWitness
1 parent 5acaf41 commit 61f4528

File tree

15 files changed

+194
-186
lines changed

15 files changed

+194
-186
lines changed

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ where
229229
}
230230

231231
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
232-
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
232+
if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
233233
return cand;
234234
}
235235

@@ -294,7 +294,7 @@ where
294294
}
295295

296296
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
297-
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
297+
if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
298298
return cand;
299299
}
300300

@@ -1432,11 +1432,8 @@ where
14321432
self.merge_trait_candidates(candidates)
14331433
}
14341434

1435-
fn try_stall_coroutine_witness(
1436-
&mut self,
1437-
self_ty: I::Ty,
1438-
) -> Option<Result<Candidate<I>, NoSolution>> {
1439-
if let ty::CoroutineWitness(def_id, _) = self_ty.kind() {
1435+
fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1436+
if let ty::Coroutine(def_id, _) = self_ty.kind() {
14401437
match self.typing_mode() {
14411438
TypingMode::Analysis {
14421439
defining_opaque_types_and_generators: stalled_generators,

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
330330
return ControlFlow::Continue(());
331331
}
332332

333-
if let ty::CoroutineWitness(def_id, _) = *ty.kind()
333+
if let ty::Coroutine(def_id, _) = *ty.kind()
334334
&& def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id))
335335
{
336336
ControlFlow::Break(())

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -794,18 +794,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
794794
// The auto impl might apply; we don't know.
795795
candidates.ambiguous = true;
796796
}
797-
ty::Coroutine(coroutine_def_id, _)
798-
if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
799-
{
800-
match self.tcx().coroutine_movability(coroutine_def_id) {
801-
hir::Movability::Static => {
802-
// Immovable coroutines are never `Unpin`, so
803-
// suppress the normal auto-impl candidate for it.
797+
ty::Coroutine(coroutine_def_id, _) => {
798+
if self.tcx().is_lang_item(def_id, LangItem::Unpin) {
799+
match self.tcx().coroutine_movability(coroutine_def_id) {
800+
hir::Movability::Static => {
801+
// Immovable coroutines are never `Unpin`, so
802+
// suppress the normal auto-impl candidate for it.
803+
}
804+
hir::Movability::Movable => {
805+
// Movable coroutines are always `Unpin`, so add an
806+
// unconditional builtin candidate with no sub-obligations.
807+
candidates.vec.push(BuiltinCandidate);
808+
}
804809
}
805-
hir::Movability::Movable => {
806-
// Movable coroutines are always `Unpin`, so add an
807-
// unconditional builtin candidate.
808-
candidates.vec.push(BuiltinCandidate);
810+
} else {
811+
if self.should_stall_coroutine(coroutine_def_id) {
812+
candidates.ambiguous = true;
813+
} else {
814+
// Coroutines implement all other auto traits normally.
815+
candidates.vec.push(AutoImplCandidate);
809816
}
810817
}
811818
}
@@ -842,12 +849,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
842849
}
843850
}
844851

845-
ty::CoroutineWitness(def_id, _) => {
846-
if self.should_stall_coroutine_witness(def_id) {
847-
candidates.ambiguous = true;
848-
} else {
849-
candidates.vec.push(AutoImplCandidate);
850-
}
852+
ty::CoroutineWitness(..) => {
853+
candidates.vec.push(AutoImplCandidate);
851854
}
852855

853856
ty::Bool
@@ -866,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
866869
| ty::FnPtr(..)
867870
| ty::Closure(..)
868871
| ty::CoroutineClosure(..)
869-
| ty::Coroutine(..)
870872
| ty::Never
871873
| ty::Tuple(_)
872874
| ty::UnsafeBinder(_) => {
@@ -1153,6 +1155,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11531155
ty::Ref(_, _, hir::Mutability::Mut) => {}
11541156

11551157
ty::Coroutine(coroutine_def_id, args) => {
1158+
if self.should_stall_coroutine(coroutine_def_id) {
1159+
candidates.ambiguous = true;
1160+
return;
1161+
}
1162+
11561163
match self.tcx().coroutine_movability(coroutine_def_id) {
11571164
hir::Movability::Static => {}
11581165
hir::Movability::Movable => {
@@ -1194,12 +1201,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11941201
}
11951202
}
11961203

1197-
ty::CoroutineWitness(coroutine_def_id, _) => {
1198-
if self.should_stall_coroutine_witness(coroutine_def_id) {
1199-
candidates.ambiguous = true;
1200-
} else {
1201-
candidates.vec.push(SizedCandidate);
1202-
}
1204+
ty::CoroutineWitness(..) => {
1205+
candidates.vec.push(SizedCandidate);
12031206
}
12041207

12051208
// Fallback to whatever user-defined impls or param-env clauses exist in this case.
@@ -1238,7 +1241,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12381241
| ty::RawPtr(..)
12391242
| ty::Char
12401243
| ty::Ref(..)
1241-
| ty::Coroutine(..)
12421244
| ty::Array(..)
12431245
| ty::Closure(..)
12441246
| ty::CoroutineClosure(..)
@@ -1247,14 +1249,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12471249
candidates.vec.push(SizedCandidate);
12481250
}
12491251

1250-
ty::CoroutineWitness(coroutine_def_id, _) => {
1251-
if self.should_stall_coroutine_witness(coroutine_def_id) {
1252+
ty::Coroutine(coroutine_def_id, _) => {
1253+
if self.should_stall_coroutine(coroutine_def_id) {
12521254
candidates.ambiguous = true;
12531255
} else {
12541256
candidates.vec.push(SizedCandidate);
12551257
}
12561258
}
12571259

1260+
ty::CoroutineWitness(..) => {
1261+
candidates.vec.push(SizedCandidate);
1262+
}
1263+
12581264
// Conditionally `Sized`.
12591265
ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
12601266
candidates.vec.push(SizedCandidate);

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2844,7 +2844,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
28442844
obligations
28452845
}
28462846

2847-
fn should_stall_coroutine_witness(&self, def_id: DefId) -> bool {
2847+
fn should_stall_coroutine(&self, def_id: DefId) -> bool {
28482848
match self.infcx.typing_mode() {
28492849
TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => {
28502850
def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))

compiler/rustc_type_ir/src/flags.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,7 @@ bitflags::bitflags! {
131131
/// Does this have any binders with bound vars (e.g. that need to be anonymized)?
132132
const HAS_BINDER_VARS = 1 << 23;
133133

134-
/// Does this type have any coroutine witnesses in it?
135-
// FIXME: This should probably be changed to track whether the type has any
136-
// *coroutines* in it, though this will happen if we remove coroutine witnesses
137-
// altogether.
134+
/// Does this type have any coroutines in it?
138135
const HAS_TY_CORO = 1 << 24;
139136
}
140137
}
@@ -246,11 +243,13 @@ impl<I: Interner> FlagComputation<I> {
246243
self.add_flags(TypeFlags::HAS_TY_PARAM);
247244
}
248245

249-
ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) => {
246+
ty::Closure(_, args)
247+
| ty::CoroutineClosure(_, args)
248+
| ty::CoroutineWitness(_, args) => {
250249
self.add_args(args.as_slice());
251250
}
252251

253-
ty::CoroutineWitness(_, args) => {
252+
ty::Coroutine(_, args) => {
254253
self.add_flags(TypeFlags::HAS_TY_CORO);
255254
self.add_args(args.as_slice());
256255
}

tests/ui/async-await/issue-70818.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::future::Future;
44
fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
55
//~^ ERROR future cannot be sent between threads safely
66
async { (ty, ty1) }
7+
//~^ ERROR future cannot be sent between threads safely
78
}
89

910
fn main() {}

tests/ui/async-await/issue-70818.stderr

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
error: future cannot be sent between threads safely
2+
--> $DIR/issue-70818.rs:6:5
3+
|
4+
LL | async { (ty, ty1) }
5+
| ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
6+
|
7+
note: captured value is not `Send`
8+
--> $DIR/issue-70818.rs:6:18
9+
|
10+
LL | async { (ty, ty1) }
11+
| ^^^ has type `U` which is not `Send`
12+
note: required by a bound in an opaque type
13+
--> $DIR/issue-70818.rs:4:69
14+
|
15+
LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
16+
| ^^^^
17+
help: consider restricting type parameter `U` with trait `Send`
18+
|
19+
LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
20+
| +++++++++++++++++++
21+
122
error: future cannot be sent between threads safely
223
--> $DIR/issue-70818.rs:4:38
324
|
@@ -14,5 +35,5 @@ help: consider restricting type parameter `U` with trait `Send`
1435
LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
1536
| +++++++++++++++++++
1637

17-
error: aborting due to 1 previous error
38+
error: aborting due to 2 previous errors
1839

tests/ui/async-await/issue-86507.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
1313
|
1414
LL | let x = x;
1515
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
16-
= note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
16+
= note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<dyn Future<Output = ()> + Send>>`
1717
help: consider further restricting type parameter `T` with trait `Sync`
1818
|
1919
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)

tests/ui/coroutine/clone-impl-async.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::future::ready;
99

1010
struct NonClone;
1111

12-
fn main() {
12+
fn local() {
1313
let inner_non_clone = async {
1414
let non_clone = NonClone;
1515
let () = ready(()).await;
@@ -34,7 +34,9 @@ fn main() {
3434
//~^ ERROR : Copy` is not satisfied
3535
check_clone(&maybe_copy_clone);
3636
//~^ ERROR : Clone` is not satisfied
37+
}
3738

39+
fn non_local() {
3840
let inner_non_clone_fn = the_inner_non_clone_fn();
3941
check_copy(&inner_non_clone_fn);
4042
//~^ ERROR : Copy` is not satisfied
@@ -69,3 +71,5 @@ async fn the_maybe_copy_clone_fn() {}
6971

7072
fn check_copy<T: Copy>(_x: &T) {}
7173
fn check_clone<T: Clone>(_x: &T) {}
74+
75+
fn main() {}

0 commit comments

Comments
 (0)