Skip to content

Commit b608ebb

Browse files
Review
1 parent 7c1661f commit b608ebb

File tree

5 files changed

+45
-79
lines changed

5 files changed

+45
-79
lines changed

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
}

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
{

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,

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
}

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
}

0 commit comments

Comments
 (0)