Skip to content

Commit c8c6c98

Browse files
committed
Auto merge of rust-lang#138845 - compiler-errors:stall-generators, r=<try>
Properly stall coroutine witnesses in new solver TODO: write description r? lcnr
2 parents 6bc57c6 + b153a5c commit c8c6c98

File tree

27 files changed

+399
-147
lines changed

27 files changed

+399
-147
lines changed

compiler/rustc_hir_typeck/src/closure.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163163
// Resume type defaults to `()` if the coroutine has no argument.
164164
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
165165

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

169177
// Coroutines that come from coroutine closures have not yet determined

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+29-24
Original file line numberDiff line numberDiff line change
@@ -635,34 +635,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
635635

636636
let mut obligations = vec![];
637637

638-
for &(coroutine_def_id, interior) in coroutines.iter() {
639-
debug!(?coroutine_def_id);
638+
if !self.next_trait_solver() {
639+
for &(coroutine_def_id, interior) in coroutines.iter() {
640+
debug!(?coroutine_def_id);
641+
642+
// Create the `CoroutineWitness` type that we will unify with `interior`.
643+
let args = ty::GenericArgs::identity_for_item(
644+
self.tcx,
645+
self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
646+
);
647+
let witness =
648+
Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
640649

641-
// Create the `CoroutineWitness` type that we will unify with `interior`.
642-
let args = ty::GenericArgs::identity_for_item(
643-
self.tcx,
644-
self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
645-
);
646-
let witness = Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
647-
648-
// Unify `interior` with `witness` and collect all the resulting obligations.
649-
let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
650-
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
651-
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
652-
};
653-
let ok = self
654-
.at(&self.misc(span), self.param_env)
655-
// Will never define opaque types, as all we do is instantiate a type variable.
656-
.eq(DefineOpaqueTypes::Yes, interior, witness)
657-
.expect("Failed to unify coroutine interior type");
658-
659-
obligations.extend(ok.obligations);
650+
// Unify `interior` with `witness` and collect all the resulting obligations.
651+
let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
652+
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
653+
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
654+
};
655+
let ok = self
656+
.at(&self.misc(span), self.param_env)
657+
// Will never define opaque types, as all we do is instantiate a type variable.
658+
.eq(DefineOpaqueTypes::Yes, interior, witness)
659+
.expect("Failed to unify coroutine interior type");
660+
661+
obligations.extend(ok.obligations);
662+
}
660663
}
661664

662-
// FIXME: Use a real visitor for unstalled obligations in the new solver.
663665
if !coroutines.is_empty() {
664-
obligations
665-
.extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
666+
obligations.extend(
667+
self.fulfillment_cx
668+
.borrow_mut()
669+
.drain_stalled_obligations_for_coroutines(&self.infcx),
670+
);
666671
}
667672

668673
self.typeck_results

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
8484
let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
8585

8686
let infcx =
87-
tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id));
87+
tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id));
8888
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
8989

9090
TypeckRootCtxt {

compiler/rustc_hir_typeck/src/writeback.rs

+46-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_data_structures::unord::ExtendUnord;
88
use rustc_errors::ErrorGuaranteed;
99
use rustc_hir::intravisit::{self, InferKind, Visitor};
1010
use rustc_hir::{self as hir, AmbigArg, HirId};
11+
use rustc_infer::traits::solve::Goal;
1112
use rustc_middle::span_bug;
1213
use rustc_middle::traits::ObligationCause;
1314
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@@ -763,7 +764,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
763764
T: TypeFoldable<TyCtxt<'tcx>>,
764765
{
765766
let value = self.fcx.resolve_vars_if_possible(value);
766-
let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true));
767+
768+
let mut goals = vec![];
769+
let value =
770+
value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true, &mut goals));
771+
772+
// Ensure that we resolve goals we get from normalizing coroutine interiors,
773+
// but we shouldn't expect those goals to need normalizing (or else we'd get
774+
// into a somewhat awkward fixpoint situation, and we don't need it anyways).
775+
let mut unexpected_goals = vec![];
776+
self.typeck_results.coroutine_stalled_predicates.extend(
777+
goals
778+
.into_iter()
779+
.map(|pred| {
780+
self.fcx.resolve_vars_if_possible(pred).fold_with(&mut Resolver::new(
781+
self.fcx,
782+
span,
783+
self.body,
784+
false,
785+
&mut unexpected_goals,
786+
))
787+
})
788+
// FIXME: throwing away the param-env :(
789+
.map(|goal| (goal.predicate, self.fcx.misc(span.to_span(self.fcx.tcx)))),
790+
);
791+
assert_eq!(unexpected_goals, vec![]);
792+
767793
assert!(!value.has_infer());
768794

769795
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -781,7 +807,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
781807
T: TypeFoldable<TyCtxt<'tcx>>,
782808
{
783809
let value = self.fcx.resolve_vars_if_possible(value);
784-
let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false));
810+
811+
let mut goals = vec![];
812+
let value =
813+
value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false, &mut goals));
814+
assert_eq!(goals, vec![]);
815+
785816
assert!(!value.has_infer());
786817

787818
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -818,6 +849,7 @@ struct Resolver<'cx, 'tcx> {
818849
/// Whether we should normalize using the new solver, disabled
819850
/// both when using the old solver and when resolving predicates.
820851
should_normalize: bool,
852+
nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
821853
}
822854

823855
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -826,8 +858,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
826858
span: &'cx dyn Locatable,
827859
body: &'tcx hir::Body<'tcx>,
828860
should_normalize: bool,
861+
nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
829862
) -> Resolver<'cx, 'tcx> {
830-
Resolver { fcx, span, body, should_normalize }
863+
Resolver { fcx, span, body, nested_goals, should_normalize }
831864
}
832865

833866
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -864,12 +897,18 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
864897
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
865898
let at = self.fcx.at(&cause, self.fcx.param_env);
866899
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
867-
solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
868-
|errors| {
900+
match solve::deeply_normalize_with_skipped_universes_and_ambiguous_goals(
901+
at, value, universes,
902+
) {
903+
Ok((value, goals)) => {
904+
self.nested_goals.extend(goals);
905+
value
906+
}
907+
Err(errors) => {
869908
let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
870909
new_err(tcx, guar)
871-
},
872-
)
910+
}
911+
}
873912
} else {
874913
value
875914
};

compiler/rustc_infer/src/infer/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ impl<'tcx> InferCtxt<'tcx> {
967967
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
968968
debug_assert!(!self.next_trait_solver());
969969
match self.typing_mode() {
970-
TypingMode::Analysis { defining_opaque_types }
970+
TypingMode::Analysis { defining_opaque_types, stalled_generators: _ }
971971
| TypingMode::Borrowck { defining_opaque_types } => {
972972
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
973973
}
@@ -1262,7 +1262,7 @@ impl<'tcx> InferCtxt<'tcx> {
12621262
// to handle them without proper canonicalization. This means we may cause cycle
12631263
// errors and fail to reveal opaques while inside of bodies. We should rename this
12641264
// function and require explicit comments on all use-sites in the future.
1265-
ty::TypingMode::Analysis { defining_opaque_types: _ }
1265+
ty::TypingMode::Analysis { defining_opaque_types: _, stalled_generators: _ }
12661266
| ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
12671267
TypingMode::non_body_analysis()
12681268
}

compiler/rustc_infer/src/traits/engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
9494
/// Among all pending obligations, collect those are stalled on a inference variable which has
9595
/// changed since the last call to `select_where_possible`. Those obligations are marked as
9696
/// successful and returned.
97-
fn drain_unstalled_obligations(
97+
fn drain_stalled_obligations_for_coroutines(
9898
&mut self,
9999
infcx: &InferCtxt<'tcx>,
100100
) -> PredicateObligations<'tcx>;

compiler/rustc_middle/src/query/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,15 @@ rustc_queries! {
387387
}
388388
}
389389

390+
query stalled_generators_within(
391+
key: LocalDefId
392+
) -> &'tcx ty::List<LocalDefId> {
393+
desc {
394+
|tcx| "computing the opaque types defined by `{}`",
395+
tcx.def_path_str(key.to_def_id())
396+
}
397+
}
398+
390399
/// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId`
391400
/// that must be proven true at definition site (and which can be assumed at usage sites).
392401
///

compiler/rustc_middle/src/query/plumbing.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,11 @@ macro_rules! define_callbacks {
366366

367367
pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
368368

369-
// Ensure that keys grow no larger than 80 bytes by accident.
369+
// Ensure that keys grow no larger than 96 bytes by accident.
370370
// Increase this limit if necessary, but do try to keep the size low if possible
371371
#[cfg(target_pointer_width = "64")]
372372
const _: () = {
373-
if size_of::<Key<'static>>() > 88 {
373+
if size_of::<Key<'static>>() > 96 {
374374
panic!("{}", concat!(
375375
"the query `",
376376
stringify!($name),

compiler/rustc_middle/src/ty/context.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
106106
) -> Self::PredefinedOpaques {
107107
self.mk_predefined_opaques_in_body(data)
108108
}
109-
type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
109+
type LocalDefIds = &'tcx ty::List<LocalDefId>;
110110
type CanonicalVars = CanonicalVarInfos<'tcx>;
111111
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
112112
self.mk_canonical_var_infos(infos)
@@ -674,9 +674,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
674674
self.anonymize_bound_vars(binder)
675675
}
676676

677-
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
677+
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds {
678678
self.opaque_types_defined_by(defining_anchor)
679679
}
680+
681+
fn stalled_generators_within(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds {
682+
if self.next_trait_solver_globally() {
683+
self.stalled_generators_within(defining_anchor)
684+
} else {
685+
ty::List::empty()
686+
}
687+
}
680688
}
681689

682690
macro_rules! bidirectional_lang_item_map {

compiler/rustc_next_trait_solver/src/solve/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,10 @@ where
329329
TypingMode::Coherence | TypingMode::PostAnalysis => false,
330330
// During analysis, opaques are rigid unless they may be defined by
331331
// the current body.
332-
TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
332+
TypingMode::Analysis {
333+
defining_opaque_types: non_rigid_opaques,
334+
stalled_generators: _,
335+
}
333336
| TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques }
334337
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
335338
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))

compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ where
3333
);
3434
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
3535
}
36-
TypingMode::Analysis { defining_opaque_types } => {
36+
TypingMode::Analysis { defining_opaque_types, stalled_generators: _ } => {
3737
let Some(def_id) = opaque_ty
3838
.def_id
3939
.as_local()

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+32
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ where
208208
}
209209
}
210210

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;
214+
}
215+
211216
ecx.probe_and_evaluate_goal_for_constituent_tys(
212217
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
213218
goal,
@@ -259,6 +264,11 @@ where
259264
return Err(NoSolution);
260265
}
261266

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;
270+
}
271+
262272
ecx.probe_and_evaluate_goal_for_constituent_tys(
263273
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
264274
goal,
@@ -1368,4 +1378,26 @@ where
13681378
let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
13691379
self.merge_trait_candidates(goal, candidates)
13701380
}
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+
}
13711403
}

compiler/rustc_trait_selection/src/infer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl<'tcx> InferCtxt<'tcx> {
3434

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

compiler/rustc_trait_selection/src/solve.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ mod select;
99
pub(crate) use delegate::SolverDelegate;
1010
pub use fulfill::{FulfillmentCtxt, NextSolverError};
1111
pub(crate) use normalize::deeply_normalize_for_diagnostics;
12-
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
12+
pub use normalize::{
13+
deeply_normalize, deeply_normalize_with_skipped_universes,
14+
deeply_normalize_with_skipped_universes_and_ambiguous_goals,
15+
};
1316
pub use select::InferCtxtSelectExt;

0 commit comments

Comments
 (0)