Skip to content

Commit e466296

Browse files
committed
Auto merge of #141762 - compiler-errors:witnesser, r=lcnr
Unify `CoroutineWitness` sooner in typeck, and stall coroutine obligations based off of `TypingEnv` * Stall coroutine obligations based off of `TypingMode` in the old solver. * Eagerly assign `TyKind::CoroutineWitness` to the witness arg of coroutines during typeck, rather than deferring them to the end of typeck. r? lcnr This is part of #143017.
2 parents 9cd918b + 216cdb7 commit e466296

File tree

18 files changed

+200
-185
lines changed

18 files changed

+200
-185
lines changed

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
161161
// Resume type defaults to `()` if the coroutine has no argument.
162162
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
163163

164-
// In the new solver, we can just instantiate this eagerly
165-
// with the witness. This will ensure that goals that don't need
166-
// to stall on interior types will get processed eagerly.
167-
let interior = if self.next_trait_solver() {
168-
Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args)
169-
} else {
170-
self.next_ty_var(expr_span)
171-
};
172-
173-
self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior));
164+
let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args);
174165

175166
// Coroutines that come from coroutine closures have not yet determined
176167
// their kind ty, so make a fresh infer var which will be constrained

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -625,50 +625,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
625625
// trigger query cycle ICEs, as doing so requires MIR.
626626
self.select_obligations_where_possible(|_| {});
627627

628-
let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut());
629-
debug!(?coroutines);
630-
631-
let mut obligations = vec![];
632-
633-
if !self.next_trait_solver() {
634-
for &(coroutine_def_id, interior) in coroutines.iter() {
635-
debug!(?coroutine_def_id);
636-
637-
// Create the `CoroutineWitness` type that we will unify with `interior`.
638-
let args = ty::GenericArgs::identity_for_item(
639-
self.tcx,
640-
self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
641-
);
642-
let witness =
643-
Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
644-
645-
// Unify `interior` with `witness` and collect all the resulting obligations.
646-
let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
647-
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
648-
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
649-
};
650-
let ok = self
651-
.at(&self.misc(span), self.param_env)
652-
// Will never define opaque types, as all we do is instantiate a type variable.
653-
.eq(DefineOpaqueTypes::Yes, interior, witness)
654-
.expect("Failed to unify coroutine interior type");
655-
656-
obligations.extend(ok.obligations);
657-
}
658-
}
628+
let ty::TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
629+
else {
630+
bug!();
631+
};
659632

660-
if !coroutines.is_empty() {
661-
obligations.extend(
633+
if defining_opaque_types_and_generators
634+
.iter()
635+
.any(|def_id| self.tcx.is_coroutine(def_id.to_def_id()))
636+
{
637+
self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(
662638
self.fulfillment_cx
663639
.borrow_mut()
664-
.drain_stalled_obligations_for_coroutines(&self.infcx),
640+
.drain_stalled_obligations_for_coroutines(&self.infcx)
641+
.into_iter()
642+
.map(|o| (o.predicate, o.cause)),
665643
);
666644
}
667-
668-
self.typeck_results
669-
.borrow_mut()
670-
.coroutine_stalled_predicates
671-
.extend(obligations.into_iter().map(|o| (o.predicate, o.cause)));
672645
}
673646

674647
#[instrument(skip(self), level = "debug")]

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
6363

6464
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>,
6565

66-
pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, Ty<'tcx>)>>,
67-
6866
pub(super) deferred_repeat_expr_checks:
6967
RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>,
7068

@@ -103,7 +101,6 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
103101
deferred_cast_checks: RefCell::new(Vec::new()),
104102
deferred_transmute_checks: RefCell::new(Vec::new()),
105103
deferred_asm_checks: RefCell::new(Vec::new()),
106-
deferred_coroutine_interiors: RefCell::new(Vec::new()),
107104
deferred_repeat_expr_checks: RefCell::new(Vec::new()),
108105
diverging_type_vars: RefCell::new(Default::default()),
109106
infer_var_info: RefCell::new(Default::default()),

compiler/rustc_middle/src/ty/context.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -714,17 +714,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
714714
self,
715715
defining_anchor: Self::LocalDefId,
716716
) -> Self::LocalDefIds {
717-
if self.next_trait_solver_globally() {
718-
let coroutines_defined_by = self
719-
.nested_bodies_within(defining_anchor)
720-
.iter()
721-
.filter(|def_id| self.is_coroutine(def_id.to_def_id()));
722-
self.mk_local_def_ids_from_iter(
723-
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
724-
)
725-
} else {
726-
self.opaque_types_defined_by(defining_anchor)
727-
}
717+
let coroutines_defined_by = self
718+
.nested_bodies_within(defining_anchor)
719+
.iter()
720+
.filter(|def_id| self.is_coroutine(def_id.to_def_id()));
721+
self.mk_local_def_ids_from_iter(
722+
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
723+
)
728724
}
729725
}
730726

compiler/rustc_trait_selection/src/infer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ impl<'tcx> InferCtxt<'tcx> {
3333
let ty = self.resolve_vars_if_possible(ty);
3434

3535
// FIXME(#132279): This should be removed as it causes us to incorrectly
36-
// handle opaques in their defining scope.
37-
if !self.next_trait_solver() && !(param_env, ty).has_infer() {
36+
// handle opaques in their defining scope, and stalled coroutines.
37+
if !self.next_trait_solver() && !(param_env, ty).has_infer() && !ty.has_coroutines() {
3838
return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty);
3939
}
4040

compiler/rustc_trait_selection/src/solve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod normalize;
77
mod select;
88

99
pub(crate) use delegate::SolverDelegate;
10-
pub use fulfill::{FulfillmentCtxt, NextSolverError};
10+
pub use fulfill::{FulfillmentCtxt, NextSolverError, StalledOnCoroutines};
1111
pub(crate) use normalize::deeply_normalize_for_diagnostics;
1212
pub use normalize::{
1313
deeply_normalize, deeply_normalize_with_skipped_universes,

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use rustc_infer::traits::{
1010
FromSolverError, PredicateObligation, PredicateObligations, TraitEngine,
1111
};
1212
use rustc_middle::ty::{
13-
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
13+
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
14+
TypingMode,
1415
};
1516
use rustc_next_trait_solver::delegate::SolverDelegate as _;
1617
use rustc_next_trait_solver::solve::{
@@ -254,7 +255,7 @@ where
254255
&mut self,
255256
infcx: &InferCtxt<'tcx>,
256257
) -> PredicateObligations<'tcx> {
257-
let stalled_generators = match infcx.typing_mode() {
258+
let stalled_coroutines = match infcx.typing_mode() {
258259
TypingMode::Analysis { defining_opaque_types_and_generators } => {
259260
defining_opaque_types_and_generators
260261
}
@@ -264,7 +265,7 @@ where
264265
| TypingMode::PostAnalysis => return Default::default(),
265266
};
266267

267-
if stalled_generators.is_empty() {
268+
if stalled_coroutines.is_empty() {
268269
return Default::default();
269270
}
270271

@@ -275,7 +276,7 @@ where
275276
.visit_proof_tree(
276277
obl.as_goal(),
277278
&mut StalledOnCoroutines {
278-
stalled_generators,
279+
stalled_coroutines,
279280
span: obl.cause.span,
280281
cache: Default::default(),
281282
},
@@ -297,10 +298,10 @@ where
297298
///
298299
/// This function can be also return false positives, which will lead to poor diagnostics
299300
/// so we want to keep this visitor *precise* too.
300-
struct StalledOnCoroutines<'tcx> {
301-
stalled_generators: &'tcx ty::List<LocalDefId>,
302-
span: Span,
303-
cache: DelayedSet<Ty<'tcx>>,
301+
pub struct StalledOnCoroutines<'tcx> {
302+
pub stalled_coroutines: &'tcx ty::List<LocalDefId>,
303+
pub span: Span,
304+
pub cache: DelayedSet<Ty<'tcx>>,
304305
}
305306

306307
impl<'tcx> inspect::ProofTreeVisitor<'tcx> for StalledOnCoroutines<'tcx> {
@@ -330,12 +331,14 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
330331
}
331332

332333
if let ty::CoroutineWitness(def_id, _) = *ty.kind()
333-
&& def_id.as_local().is_some_and(|def_id| self.stalled_generators.contains(&def_id))
334+
&& def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id))
334335
{
335-
return ControlFlow::Break(());
336+
ControlFlow::Break(())
337+
} else if ty.has_coroutines() {
338+
ty.super_visit_with(self)
339+
} else {
340+
ControlFlow::Continue(())
336341
}
337-
338-
ty.super_visit_with(self)
339342
}
340343
}
341344

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::marker::PhantomData;
33
use rustc_data_structures::obligation_forest::{
44
Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult,
55
};
6+
use rustc_hir::def_id::LocalDefId;
67
use rustc_infer::infer::DefineOpaqueTypes;
78
use rustc_infer::traits::{
89
FromSolverError, PolyTraitObligation, PredicateObligations, ProjectionCacheKey, SelectionError,
@@ -12,8 +13,10 @@ use rustc_middle::bug;
1213
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
1314
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1415
use rustc_middle::ty::{
15-
self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode, may_use_unstable_feature,
16+
self, Binder, Const, GenericArgsRef, TypeVisitable, TypeVisitableExt, TypingMode,
17+
may_use_unstable_feature,
1618
};
19+
use rustc_span::DUMMY_SP;
1720
use thin_vec::{ThinVec, thin_vec};
1821
use tracing::{debug, debug_span, instrument};
1922

@@ -26,6 +29,7 @@ use super::{
2629
};
2730
use crate::error_reporting::InferCtxtErrorExt;
2831
use crate::infer::{InferCtxt, TyOrConstInferVar};
32+
use crate::solve::StalledOnCoroutines;
2933
use crate::traits::normalize::normalize_with_depth_to;
3034
use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
3135
use crate::traits::query::evaluate_obligation::InferCtxtExt;
@@ -168,15 +172,33 @@ where
168172
&mut self,
169173
infcx: &InferCtxt<'tcx>,
170174
) -> PredicateObligations<'tcx> {
171-
let mut processor =
172-
DrainProcessor { removed_predicates: PredicateObligations::new(), infcx };
175+
let stalled_coroutines = match infcx.typing_mode() {
176+
TypingMode::Analysis { defining_opaque_types_and_generators } => {
177+
defining_opaque_types_and_generators
178+
}
179+
TypingMode::Coherence
180+
| TypingMode::Borrowck { defining_opaque_types: _ }
181+
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
182+
| TypingMode::PostAnalysis => return Default::default(),
183+
};
184+
185+
if stalled_coroutines.is_empty() {
186+
return Default::default();
187+
}
188+
189+
let mut processor = DrainProcessor {
190+
infcx,
191+
removed_predicates: PredicateObligations::new(),
192+
stalled_coroutines,
193+
};
173194
let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor);
174195
assert!(outcome.errors.is_empty());
175196
return processor.removed_predicates;
176197

177198
struct DrainProcessor<'a, 'tcx> {
178199
infcx: &'a InferCtxt<'tcx>,
179200
removed_predicates: PredicateObligations<'tcx>,
201+
stalled_coroutines: &'tcx ty::List<LocalDefId>,
180202
}
181203

182204
impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> {
@@ -185,10 +207,14 @@ where
185207
type OUT = Outcome<Self::Obligation, Self::Error>;
186208

187209
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
188-
pending_obligation
189-
.stalled_on
190-
.iter()
191-
.any(|&var| self.infcx.ty_or_const_infer_var_changed(var))
210+
self.infcx
211+
.resolve_vars_if_possible(pending_obligation.obligation.predicate)
212+
.visit_with(&mut StalledOnCoroutines {
213+
stalled_coroutines: self.stalled_coroutines,
214+
span: DUMMY_SP,
215+
cache: Default::default(),
216+
})
217+
.is_break()
192218
}
193219

194220
fn process_obligation(

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

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
842842
}
843843
}
844844

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+
}
851+
}
852+
845853
ty::Bool
846854
| ty::Char
847855
| ty::Int(_)
@@ -861,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
861869
| ty::Coroutine(..)
862870
| ty::Never
863871
| ty::Tuple(_)
864-
| ty::CoroutineWitness(..)
865872
| ty::UnsafeBinder(_) => {
866873
// Only consider auto impls of unsafe traits when there are
867874
// no unsafe fields.
@@ -1119,12 +1126,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11191126
match *self_ty.kind() {
11201127
// These impls are built-in because we cannot express sufficiently
11211128
// generic impls in libcore.
1122-
ty::FnDef(..)
1123-
| ty::FnPtr(..)
1124-
| ty::Error(_)
1125-
| ty::Tuple(..)
1126-
| ty::CoroutineWitness(..)
1127-
| ty::Pat(..) => {
1129+
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) | ty::Tuple(..) | ty::Pat(..) => {
11281130
candidates.vec.push(BuiltinCandidate);
11291131
}
11301132

@@ -1192,6 +1194,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11921194
}
11931195
}
11941196

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+
}
1203+
}
1204+
11951205
// Fallback to whatever user-defined impls or param-env clauses exist in this case.
11961206
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {}
11971207

@@ -1229,7 +1239,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12291239
| ty::Char
12301240
| ty::Ref(..)
12311241
| ty::Coroutine(..)
1232-
| ty::CoroutineWitness(..)
12331242
| ty::Array(..)
12341243
| ty::Closure(..)
12351244
| ty::CoroutineClosure(..)
@@ -1238,6 +1247,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12381247
candidates.vec.push(SizedCandidate);
12391248
}
12401249

1250+
ty::CoroutineWitness(coroutine_def_id, _) => {
1251+
if self.should_stall_coroutine_witness(coroutine_def_id) {
1252+
candidates.ambiguous = true;
1253+
} else {
1254+
candidates.vec.push(SizedCandidate);
1255+
}
1256+
}
1257+
12411258
// Conditionally `Sized`.
12421259
ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
12431260
candidates.vec.push(SizedCandidate);

0 commit comments

Comments
 (0)