Skip to content

Commit b153a5c

Browse files
Review
1 parent 7c1661f commit b153a5c

File tree

10 files changed

+104
-133
lines changed

10 files changed

+104
-133
lines changed

Diff for: compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+28-28
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,9 @@ where
208208
}
209209
}
210210

211-
// TODO:
212-
if let ty::CoroutineWitness(def_id, _) = goal.predicate.self_ty().kind() {
213-
match ecx.typing_mode() {
214-
TypingMode::Analysis { stalled_generators, defining_opaque_types: _ } => {
215-
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
216-
{
217-
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
218-
}
219-
}
220-
TypingMode::Coherence
221-
| TypingMode::PostAnalysis
222-
| TypingMode::Borrowck { defining_opaque_types: _ }
223-
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
224-
}
211+
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
212+
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
213+
return cand;
225214
}
226215

227216
ecx.probe_and_evaluate_goal_for_constituent_tys(
@@ -275,20 +264,9 @@ where
275264
return Err(NoSolution);
276265
}
277266

278-
// TODO:
279-
if let ty::CoroutineWitness(def_id, _) = goal.predicate.self_ty().kind() {
280-
match ecx.typing_mode() {
281-
TypingMode::Analysis { stalled_generators, defining_opaque_types: _ } => {
282-
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
283-
{
284-
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
285-
}
286-
}
287-
TypingMode::Coherence
288-
| TypingMode::PostAnalysis
289-
| TypingMode::Borrowck { defining_opaque_types: _ }
290-
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
291-
}
267+
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
268+
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
269+
return cand;
292270
}
293271

294272
ecx.probe_and_evaluate_goal_for_constituent_tys(
@@ -1400,4 +1378,26 @@ where
14001378
let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
14011379
self.merge_trait_candidates(goal, candidates)
14021380
}
1381+
1382+
fn try_stall_coroutine_witness(
1383+
&mut self,
1384+
self_ty: I::Ty,
1385+
) -> Option<Result<Candidate<I>, NoSolution>> {
1386+
if let ty::CoroutineWitness(def_id, _) = self_ty.kind() {
1387+
match self.typing_mode() {
1388+
TypingMode::Analysis { stalled_generators, defining_opaque_types: _ } => {
1389+
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1390+
{
1391+
return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
1392+
}
1393+
}
1394+
TypingMode::Coherence
1395+
| TypingMode::PostAnalysis
1396+
| TypingMode::Borrowck { defining_opaque_types: _ }
1397+
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
1398+
}
1399+
}
1400+
1401+
None
1402+
}
14031403
}

Diff for: compiler/rustc_trait_selection/src/solve/fulfill.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_middle::ty::{
1414
};
1515
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
1616
use rustc_span::Span;
17+
use rustc_type_ir::data_structures::DelayedSet;
1718
use tracing::instrument;
1819

1920
use self::derive_errors::*;
@@ -236,7 +237,11 @@ where
236237
infcx
237238
.visit_proof_tree(
238239
obl.as_goal(),
239-
&mut StalledOnCoroutines { stalled_generators, span: obl.cause.span },
240+
&mut StalledOnCoroutines {
241+
stalled_generators,
242+
span: obl.cause.span,
243+
cache: Default::default(),
244+
},
240245
)
241246
.is_break()
242247
})
@@ -247,7 +252,7 @@ where
247252
struct StalledOnCoroutines<'tcx> {
248253
stalled_generators: &'tcx ty::List<LocalDefId>,
249254
span: Span,
250-
// TODO: Cache
255+
cache: DelayedSet<Ty<'tcx>>,
251256
}
252257

253258
impl<'tcx> inspect::ProofTreeVisitor<'tcx> for StalledOnCoroutines<'tcx> {
@@ -272,6 +277,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
272277
type Result = ControlFlow<()>;
273278

274279
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
280+
if !self.cache.insert(ty) {
281+
return ControlFlow::Continue(());
282+
}
283+
275284
if let ty::CoroutineWitness(def_id, _) = *ty.kind()
276285
&& def_id.as_local().is_some_and(|def_id| self.stalled_generators.contains(&def_id))
277286
{

Diff for: compiler/rustc_trait_selection/src/solve/normalize.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ where
6060
/// entered before passing `value` to the function. This is currently needed for
6161
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
6262
///
63-
/// TODO: doc
63+
/// This returns a set of stalled obligations if the typing mode of the underlying infcx
64+
/// has any stalled coroutine def ids.
6465
pub fn deeply_normalize_with_skipped_universes_and_ambiguous_goals<'tcx, T, E>(
6566
at: At<'_, 'tcx>,
6667
value: T,

Diff for: compiler/rustc_ty_utils/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod needs_drop;
3232
mod opaque_types;
3333
mod representability;
3434
pub mod sig_types;
35+
mod stalled_generators;
3536
mod structural_match;
3637
mod ty;
3738

@@ -50,4 +51,5 @@ pub fn provide(providers: &mut Providers) {
5051
ty::provide(providers);
5152
instance::provide(providers);
5253
structural_match::provide(providers);
54+
stalled_generators::provide(providers);
5355
}

Diff for: compiler/rustc_ty_utils/src/opaque_types.rs

+2-48
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use rustc_data_structures::fx::FxHashSet;
2-
use rustc_hir as hir;
32
use rustc_hir::def::DefKind;
4-
use rustc_hir::def_id::{DefId, LocalDefId};
3+
use rustc_hir::def_id::LocalDefId;
54
use rustc_hir::intravisit;
65
use rustc_hir::intravisit::Visitor;
76
use rustc_middle::query::Providers;
@@ -356,51 +355,6 @@ fn opaque_types_defined_by<'tcx>(
356355
tcx.mk_local_def_ids(&collector.opaques)
357356
}
358357

359-
// TODO: Move this out of `opaque_types`
360-
fn stalled_generators_within<'tcx>(
361-
tcx: TyCtxt<'tcx>,
362-
item: LocalDefId,
363-
) -> &'tcx ty::List<LocalDefId> {
364-
if !tcx.next_trait_solver_globally() {
365-
return ty::List::empty();
366-
}
367-
368-
let body = tcx.hir_body_owned_by(item);
369-
let mut collector =
370-
StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
371-
collector.visit_body(body);
372-
tcx.mk_local_def_ids(&collector.stalled_coroutines)
373-
}
374-
375-
struct StalledGeneratorVisitor<'tcx> {
376-
tcx: TyCtxt<'tcx>,
377-
root_def_id: DefId,
378-
stalled_coroutines: Vec<LocalDefId>,
379-
}
380-
381-
impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
382-
fn visit_nested_body(&mut self, id: hir::BodyId) {
383-
if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
384-
== self.root_def_id
385-
{
386-
let body = self.tcx.hir_body(id);
387-
self.visit_body(body);
388-
}
389-
}
390-
391-
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
392-
if let hir::ExprKind::Closure(&hir::Closure {
393-
def_id,
394-
kind: hir::ClosureKind::Coroutine(_),
395-
..
396-
}) = ex.kind
397-
{
398-
self.stalled_coroutines.push(def_id);
399-
}
400-
intravisit::walk_expr(self, ex);
401-
}
402-
}
403-
404358
pub(super) fn provide(providers: &mut Providers) {
405-
*providers = Providers { opaque_types_defined_by, stalled_generators_within, ..*providers };
359+
*providers = Providers { opaque_types_defined_by, ..*providers };
406360
}

Diff for: compiler/rustc_ty_utils/src/stalled_generators.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use rustc_hir as hir;
2+
use rustc_hir::def_id::{DefId, LocalDefId};
3+
use rustc_hir::intravisit;
4+
use rustc_hir::intravisit::Visitor;
5+
use rustc_middle::query::Providers;
6+
use rustc_middle::ty::{self, TyCtxt};
7+
8+
fn stalled_generators_within<'tcx>(
9+
tcx: TyCtxt<'tcx>,
10+
item: LocalDefId,
11+
) -> &'tcx ty::List<LocalDefId> {
12+
if !tcx.next_trait_solver_globally() {
13+
return ty::List::empty();
14+
}
15+
16+
let body = tcx.hir_body_owned_by(item);
17+
let mut collector =
18+
StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
19+
collector.visit_body(body);
20+
tcx.mk_local_def_ids(&collector.stalled_coroutines)
21+
}
22+
23+
struct StalledGeneratorVisitor<'tcx> {
24+
tcx: TyCtxt<'tcx>,
25+
root_def_id: DefId,
26+
stalled_coroutines: Vec<LocalDefId>,
27+
}
28+
29+
impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
30+
fn visit_nested_body(&mut self, id: hir::BodyId) {
31+
if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
32+
== self.root_def_id
33+
{
34+
let body = self.tcx.hir_body(id);
35+
self.visit_body(body);
36+
}
37+
}
38+
39+
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
40+
if let hir::ExprKind::Closure(&hir::Closure {
41+
def_id,
42+
kind: hir::ClosureKind::Coroutine(_),
43+
..
44+
}) = ex.kind
45+
{
46+
self.stalled_coroutines.push(def_id);
47+
}
48+
intravisit::walk_expr(self, ex);
49+
}
50+
}
51+
52+
pub(super) fn provide(providers: &mut Providers) {
53+
*providers = Providers { stalled_generators_within, ..*providers };
54+
}

Diff for: tests/ui/async-await/async-closures/is-not-fn.next.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
error[E0271]: expected `{async [email protected]:8:14}` to return `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
1+
error[E0271]: type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
22
--> $DIR/is-not-fn.rs:8:14
33
|
44
LL | needs_fn(async || {});
5-
| -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
5+
| -------- ^^^^^^^^^^^ types differ
66
| |
77
| required by a bound introduced by this call
88
|
9-
= note: expected unit type `()`
10-
found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
119
note: required by a bound in `needs_fn`
1210
--> $DIR/is-not-fn.rs:7:25
1311
|

Diff for: tests/ui/async-await/async-closures/is-not-fn.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
fn main() {
77
fn needs_fn(x: impl FnOnce()) {}
88
needs_fn(async || {});
9-
//~^ ERROR expected `{async [email protected]:8:14}` to return `()`
9+
//[current]~^ ERROR expected `{async [email protected]:8:14}` to return `()`
10+
//[next]~^^ ERROR type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
1011
}

Diff for: tests/ui/coroutine/clone-rpit.next.stderr

-47
This file was deleted.

Diff for: tests/ui/coroutine/clone-rpit.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//@ revisions: current next
22
//@ ignore-compare-mode-next-solver (explicit revisions)
33
//@[next] compile-flags: -Znext-solver
4-
//@[current] check-pass
5-
//@[next] known-bug: trait-system-refactor-initiative#82
4+
//@ check-pass
65

76
#![feature(coroutines, coroutine_trait, coroutine_clone)]
87

0 commit comments

Comments
 (0)