Skip to content

Commit f28a368

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 0b4a81a + 6419a55 commit f28a368

File tree

21 files changed

+353
-90
lines changed

21 files changed

+353
-90
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};
@@ -731,7 +732,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
731732
T: TypeFoldable<TyCtxt<'tcx>>,
732733
{
733734
let value = self.fcx.resolve_vars_if_possible(value);
734-
let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true));
735+
736+
let mut goals = vec![];
737+
let value =
738+
value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true, &mut goals));
739+
740+
// Ensure that we resolve goals we get from normalizing coroutine interiors,
741+
// but we shouldn't expect those goals to need normalizing (or else we'd get
742+
// into a somewhat awkward fixpoint situation, and we don't need it anyways).
743+
let mut unexpected_goals = vec![];
744+
self.typeck_results.coroutine_stalled_predicates.extend(
745+
goals
746+
.into_iter()
747+
.map(|pred| {
748+
self.fcx.resolve_vars_if_possible(pred).fold_with(&mut Resolver::new(
749+
self.fcx,
750+
span,
751+
self.body,
752+
false,
753+
&mut unexpected_goals,
754+
))
755+
})
756+
// FIXME: throwing away the param-env :(
757+
.map(|goal| (goal.predicate, self.fcx.misc(span.to_span(self.fcx.tcx)))),
758+
);
759+
assert_eq!(unexpected_goals, vec![]);
760+
735761
assert!(!value.has_infer());
736762

737763
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -749,7 +775,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
749775
T: TypeFoldable<TyCtxt<'tcx>>,
750776
{
751777
let value = self.fcx.resolve_vars_if_possible(value);
752-
let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false));
778+
779+
let mut goals = vec![];
780+
let value =
781+
value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false, &mut goals));
782+
assert_eq!(goals, vec![]);
783+
753784
assert!(!value.has_infer());
754785

755786
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -786,6 +817,7 @@ struct Resolver<'cx, 'tcx> {
786817
/// Whether we should normalize using the new solver, disabled
787818
/// both when using the old solver and when resolving predicates.
788819
should_normalize: bool,
820+
nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
789821
}
790822

791823
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -794,8 +826,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
794826
span: &'cx dyn Locatable,
795827
body: &'tcx hir::Body<'tcx>,
796828
should_normalize: bool,
829+
nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
797830
) -> Resolver<'cx, 'tcx> {
798-
Resolver { fcx, span, body, should_normalize }
831+
Resolver { fcx, span, body, nested_goals, should_normalize }
799832
}
800833

801834
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -832,12 +865,18 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
832865
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
833866
let at = self.fcx.at(&cause, self.fcx.param_env);
834867
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
835-
solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
836-
|errors| {
868+
match solve::deeply_normalize_with_skipped_universes_and_ambiguous_goals(
869+
at, value, universes,
870+
) {
871+
Ok((value, goals)) => {
872+
self.nested_goals.extend(goals);
873+
value
874+
}
875+
Err(errors) => {
837876
let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
838877
new_err(tcx, guar)
839-
},
840-
)
878+
}
879+
}
841880
} else {
842881
value
843882
};

compiler/rustc_infer/src/infer/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -966,9 +966,10 @@ impl<'tcx> InferCtxt<'tcx> {
966966
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
967967
debug_assert!(!self.next_trait_solver());
968968
match self.typing_mode() {
969-
TypingMode::Analysis { defining_opaque_types } => {
970-
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
971-
}
969+
TypingMode::Analysis { defining_opaque_types_and_generators } => id
970+
.into()
971+
.as_local()
972+
.is_some_and(|def_id| defining_opaque_types_and_generators.contains(&def_id)),
972973
// FIXME(#132279): This function is quite weird in post-analysis
973974
// and post-borrowck analysis mode. We may need to modify its uses
974975
// to support PostBorrowckAnalysis in the old solver as well.
@@ -1260,7 +1261,7 @@ impl<'tcx> InferCtxt<'tcx> {
12601261
// to handle them without proper canonicalization. This means we may cause cycle
12611262
// errors and fail to reveal opaques while inside of bodies. We should rename this
12621263
// function and require explicit comments on all use-sites in the future.
1263-
ty::TypingMode::Analysis { defining_opaque_types: _ } => {
1264+
ty::TypingMode::Analysis { defining_opaque_types_and_generators: _ } => {
12641265
TypingMode::non_body_analysis()
12651266
}
12661267
mode @ (ty::TypingMode::Coherence

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
@@ -379,6 +379,15 @@ rustc_queries! {
379379
}
380380
}
381381

382+
query stalled_generators_within(
383+
key: LocalDefId
384+
) -> &'tcx ty::List<LocalDefId> {
385+
desc {
386+
|tcx| "computing the opaque types defined by `{}`",
387+
tcx.def_path_str(key.to_def_id())
388+
}
389+
}
390+
382391
/// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId`
383392
/// that must be proven true at definition site (and which can be assumed at usage sites).
384393
///

compiler/rustc_middle/src/query/plumbing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ 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 88 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 _: () = {

compiler/rustc_middle/src/ty/context.rs

+15-4
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)
@@ -663,9 +663,20 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
663663
self.anonymize_bound_vars(binder)
664664
}
665665

666-
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
666+
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds {
667667
self.opaque_types_defined_by(defining_anchor)
668668
}
669+
670+
fn opaque_types_and_generators_defined_by(
671+
self,
672+
defining_anchor: Self::LocalDefId,
673+
) -> Self::LocalDefIds {
674+
self.mk_local_def_ids_from_iter(
675+
self.opaque_types_defined_by(defining_anchor)
676+
.iter()
677+
.chain(self.stalled_generators_within(defining_anchor)),
678+
)
679+
}
669680
}
670681

671682
macro_rules! bidirectional_lang_item_map {
@@ -2871,11 +2882,11 @@ impl<'tcx> TyCtxt<'tcx> {
28712882
self.interners.intern_clauses(clauses)
28722883
}
28732884

2874-
pub fn mk_local_def_ids(self, clauses: &[LocalDefId]) -> &'tcx List<LocalDefId> {
2885+
pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
28752886
// FIXME consider asking the input slice to be sorted to avoid
28762887
// re-interning permutations, in which case that would be asserted
28772888
// here.
2878-
self.intern_local_def_ids(clauses)
2889+
self.intern_local_def_ids(def_ids)
28792890
}
28802891

28812892
pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output

compiler/rustc_next_trait_solver/src/solve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ 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 { defining_opaque_types_and_generators: non_rigid_opaques }
333333
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
334334
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
335335
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ 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_and_generators } => {
3737
let Some(def_id) = opaque_ty
3838
.def_id
3939
.as_local()
40-
.filter(|&def_id| defining_opaque_types.contains(&def_id))
40+
.filter(|&def_id| defining_opaque_types_and_generators.contains(&def_id))
4141
else {
4242
self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
4343
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+15
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ where
189189
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
190190
}
191191

192+
if let ty::CoroutineWitness(def_id, _) = goal.predicate.self_ty().kind() {
193+
match ecx.typing_mode() {
194+
TypingMode::Analysis { defining_opaque_types_and_generators } => {
195+
if def_id.as_local().is_some_and(|def_id| {
196+
defining_opaque_types_and_generators.contains(&def_id)
197+
}) {
198+
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
199+
}
200+
}
201+
TypingMode::Coherence
202+
| TypingMode::PostAnalysis
203+
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
204+
}
205+
}
206+
192207
ecx.probe_and_evaluate_goal_for_constituent_tys(
193208
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
194209
goal,

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)