Skip to content

Commit fa58ce3

Browse files
committed
Auto merge of #138845 - compiler-errors:stall-generators, r=lcnr
Properly stall coroutine witnesses in new solver TODO: write description r? lcnr
2 parents df35ff6 + f943f73 commit fa58ce3

File tree

27 files changed

+436
-153
lines changed

27 files changed

+436
-153
lines changed

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 9 additions & 1 deletion
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

Lines changed: 29 additions & 24 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
8383
let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
8484

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

8989
TypeckRootCtxt {

compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 46 additions & 7 deletions
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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,9 @@ 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 {
971+
defining_opaque_types_and_generators: defining_opaque_types,
972+
}
971973
| TypingMode::Borrowck { defining_opaque_types } => {
972974
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
973975
}
@@ -1262,7 +1264,7 @@ impl<'tcx> InferCtxt<'tcx> {
12621264
// to handle them without proper canonicalization. This means we may cause cycle
12631265
// errors and fail to reveal opaques while inside of bodies. We should rename this
12641266
// function and require explicit comments on all use-sites in the future.
1265-
ty::TypingMode::Analysis { defining_opaque_types: _ }
1267+
ty::TypingMode::Analysis { defining_opaque_types_and_generators: _ }
12661268
| ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
12671269
TypingMode::non_body_analysis()
12681270
}

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 9 additions & 0 deletions
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 coroutines defined within `{}`",
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 19 additions & 4 deletions
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,24 @@ 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 opaque_types_and_generators_defined_by(
682+
self,
683+
defining_anchor: Self::LocalDefId,
684+
) -> Self::LocalDefIds {
685+
if self.next_trait_solver_globally() {
686+
self.mk_local_def_ids_from_iter(
687+
self.opaque_types_defined_by(defining_anchor)
688+
.iter()
689+
.chain(self.stalled_generators_within(defining_anchor)),
690+
)
691+
} else {
692+
self.opaque_types_defined_by(defining_anchor)
693+
}
694+
}
680695
}
681696

682697
macro_rules! bidirectional_lang_item_map {
@@ -2906,11 +2921,11 @@ impl<'tcx> TyCtxt<'tcx> {
29062921
self.interners.intern_clauses(clauses)
29072922
}
29082923

2909-
pub fn mk_local_def_ids(self, clauses: &[LocalDefId]) -> &'tcx List<LocalDefId> {
2924+
pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
29102925
// FIXME consider asking the input slice to be sorted to avoid
29112926
// re-interning permutations, in which case that would be asserted
29122927
// here.
2913-
self.intern_local_def_ids(clauses)
2928+
self.intern_local_def_ids(def_ids)
29142929
}
29152930

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

compiler/rustc_next_trait_solver/src/solve/mod.rs

Lines changed: 1 addition & 1 deletion
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::Borrowck { defining_opaque_types: non_rigid_opaques }
334334
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
335335
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy