Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ff8a8f7

Browse files
committed
Auto merge of rust-lang#141245 - compiler-errors:coroutine-obl, r=<try>
[PERF] Collect higher-ranked coroutines outlives assumptions Collect higher-ranked coroutines outlives, even if we don't use them, for perf.
2 parents 5f292ee + 2cd05fd commit ff8a8f7

File tree

13 files changed

+141
-42
lines changed

13 files changed

+141
-42
lines changed

compiler/rustc_macros/src/query.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl Parse for Query {
5151
let key = Pat::parse_single(&arg_content)?;
5252
arg_content.parse::<Token![:]>()?;
5353
let arg = arg_content.parse()?;
54+
let _ = arg_content.parse::<Option<Token![,]>>()?;
5455
let result = input.parse()?;
5556

5657
// Parse the query modifiers

compiler/rustc_middle/src/query/erase.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_span::ErrorGuaranteed;
66

77
use crate::query::CyclePlaceholder;
88
use crate::ty::adjustment::CoerceUnsizedInfo;
9-
use crate::ty::{self, Ty};
9+
use crate::ty::{self, Ty, TyCtxt};
1010
use crate::{mir, traits};
1111

1212
#[derive(Copy, Clone)]
@@ -207,6 +207,11 @@ impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
207207
type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
208208
}
209209

210+
impl EraseType for ty::Binder<'_, ty::CoroutineWitnessTypes<TyCtxt<'_>>> {
211+
type Result =
212+
[u8; size_of::<ty::Binder<'static, ty::CoroutineWitnessTypes<TyCtxt<'static>>>>()];
213+
}
214+
210215
impl EraseType for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
211216
type Result = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
212217
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,12 @@ rustc_queries! {
922922
separate_provide_extern
923923
}
924924

925+
query coroutine_hidden_types(
926+
def_id: DefId,
927+
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
928+
desc { "looking up the hidden types stored across await points in a coroutine" }
929+
}
930+
925931
/// Gets a map with the variances of every item in the local crate.
926932
///
927933
/// <div class="warning">

compiler/rustc_middle/src/ty/context.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
154154
type BoundRegion = ty::BoundRegion;
155155
type PlaceholderRegion = ty::PlaceholderRegion;
156156

157+
type RegionAssumptions = &'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>;
158+
157159
type ParamEnv = ty::ParamEnv<'tcx>;
158160
type Predicate = Predicate<'tcx>;
159161

@@ -340,7 +342,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
340342
fn coroutine_hidden_types(
341343
self,
342344
def_id: DefId,
343-
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> {
345+
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
344346
self.coroutine_hidden_types(def_id)
345347
}
346348

@@ -854,6 +856,7 @@ pub struct CtxtInterners<'tcx> {
854856
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
855857
valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>,
856858
patterns: InternedSet<'tcx, List<ty::Pattern<'tcx>>>,
859+
outlives: InternedSet<'tcx, List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>>,
857860
}
858861

859862
impl<'tcx> CtxtInterners<'tcx> {
@@ -891,6 +894,7 @@ impl<'tcx> CtxtInterners<'tcx> {
891894
offset_of: InternedSet::with_capacity(N),
892895
valtree: InternedSet::with_capacity(N),
893896
patterns: InternedSet::with_capacity(N),
897+
outlives: InternedSet::with_capacity(N),
894898
}
895899
}
896900

@@ -2685,6 +2689,7 @@ slice_interners!(
26852689
captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
26862690
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
26872691
patterns: pub mk_patterns(Pattern<'tcx>),
2692+
outlives: pub mk_outlives(ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>),
26882693
);
26892694

26902695
impl<'tcx> TyCtxt<'tcx> {
@@ -3100,6 +3105,17 @@ impl<'tcx> TyCtxt<'tcx> {
31003105
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
31013106
}
31023107

3108+
pub fn mk_outlives_from_iter<I, T>(self, iter: I) -> T::Output
3109+
where
3110+
I: Iterator<Item = T>,
3111+
T: CollectAndApply<
3112+
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
3113+
&'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
3114+
>,
3115+
{
3116+
T::collect_and_apply(iter, |xs| self.mk_outlives(xs))
3117+
}
3118+
31033119
/// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
31043120
/// typically generated by `#[derive(LintDiagnostic)]`).
31053121
#[track_caller]

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,4 +779,5 @@ list_fold! {
779779
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
780780
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
781781
&'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
782+
&'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> : mk_outlives,
782783
}

compiler/rustc_middle/src/ty/util.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::query::Providers;
2626
use crate::ty::layout::{FloatExt, IntegerExt};
2727
use crate::ty::{
2828
self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
29-
TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, fold_regions,
29+
TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast,
3030
};
3131

3232
#[derive(Copy, Clone, Debug)]
@@ -737,40 +737,6 @@ impl<'tcx> TyCtxt<'tcx> {
737737
}
738738
}
739739

740-
/// Return the set of types that should be taken into account when checking
741-
/// trait bounds on a coroutine's internal state. This properly replaces
742-
/// `ReErased` with new existential bound lifetimes.
743-
pub fn coroutine_hidden_types(
744-
self,
745-
def_id: DefId,
746-
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> {
747-
let coroutine_layout = self.mir_coroutine_witnesses(def_id);
748-
let mut vars = vec![];
749-
let bound_tys = self.mk_type_list_from_iter(
750-
coroutine_layout
751-
.as_ref()
752-
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
753-
.filter(|decl| !decl.ignore_for_traits)
754-
.map(|decl| {
755-
let ty = fold_regions(self, decl.ty, |re, debruijn| {
756-
assert_eq!(re, self.lifetimes.re_erased);
757-
let var = ty::BoundVar::from_usize(vars.len());
758-
vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
759-
ty::Region::new_bound(
760-
self,
761-
debruijn,
762-
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
763-
)
764-
});
765-
ty
766-
}),
767-
);
768-
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
769-
bound_tys,
770-
self.mk_bound_variable_kinds(&vars),
771-
))
772-
}
773-
774740
/// Expands the given impl trait type, stopping if the type is recursive.
775741
#[instrument(skip(self), level = "debug", ret)]
776742
pub fn try_expand_impl_trait_type(

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ where
8383
.cx()
8484
.coroutine_hidden_types(def_id)
8585
.instantiate(cx, args)
86-
.map_bound(|tys| tys.to_vec())),
86+
.map_bound(|bound| bound.types.to_vec())),
8787

8888
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
8989

@@ -249,7 +249,7 @@ where
249249
.cx()
250250
.coroutine_hidden_types(def_id)
251251
.instantiate(ecx.cx(), args)
252-
.map_bound(|tys| tys.to_vec())),
252+
.map_bound(|bound| bound.types.to_vec())),
253253
}
254254
}
255255

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2866,7 +2866,7 @@ fn rebind_coroutine_witness_types<'tcx>(
28662866
let shifted_coroutine_types =
28672867
tcx.shift_bound_var_indices(bound_vars.len(), bound_coroutine_types.skip_binder());
28682868
ty::Binder::bind_with_vars(
2869-
ty::EarlyBinder::bind(shifted_coroutine_types.to_vec()).instantiate(tcx, args),
2869+
ty::EarlyBinder::bind(shifted_coroutine_types.types.to_vec()).instantiate(tcx, args),
28702870
tcx.mk_bound_variable_kinds_from_iter(
28712871
bound_vars.iter().chain(bound_coroutine_types.bound_vars()),
28722872
),
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use rustc_hir::def_id::DefId;
2+
use rustc_infer::infer::TyCtxtInferExt;
3+
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
4+
use rustc_infer::traits::{Obligation, ObligationCause};
5+
use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions};
6+
use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars};
7+
8+
/// Return the set of types that should be taken into account when checking
9+
/// trait bounds on a coroutine's internal state. This properly replaces
10+
/// `ReErased` with new existential bound lifetimes.
11+
pub(crate) fn coroutine_hidden_types<'tcx>(
12+
tcx: TyCtxt<'tcx>,
13+
def_id: DefId,
14+
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
15+
let coroutine_layout = tcx.mir_coroutine_witnesses(def_id);
16+
let mut vars = vec![];
17+
let bound_tys = tcx.mk_type_list_from_iter(
18+
coroutine_layout
19+
.as_ref()
20+
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
21+
.filter(|decl| !decl.ignore_for_traits)
22+
.map(|decl| {
23+
let ty = fold_regions(tcx, decl.ty, |re, debruijn| {
24+
assert_eq!(re, tcx.lifetimes.re_erased);
25+
let var = ty::BoundVar::from_usize(vars.len());
26+
vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
27+
ty::Region::new_bound(
28+
tcx,
29+
debruijn,
30+
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
31+
)
32+
});
33+
ty
34+
}),
35+
);
36+
37+
let assumptions = compute_assumptions(tcx, def_id, bound_tys);
38+
39+
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
40+
ty::CoroutineWitnessTypes { types: bound_tys, assumptions },
41+
tcx.mk_bound_variable_kinds(&vars),
42+
))
43+
}
44+
45+
fn compute_assumptions<'tcx>(
46+
tcx: TyCtxt<'tcx>,
47+
def_id: DefId,
48+
bound_tys: &'tcx ty::List<Ty<'tcx>>,
49+
) -> &'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> {
50+
let infcx = tcx.infer_ctxt().build(ty::TypingMode::Analysis {
51+
defining_opaque_types_and_generators: ty::List::empty(),
52+
});
53+
with_replaced_escaping_bound_vars(&infcx, &mut vec![None], bound_tys, |bound_tys| {
54+
let param_env = tcx.param_env(def_id);
55+
let ocx = ObligationCtxt::new(&infcx);
56+
57+
ocx.register_obligations(bound_tys.iter().map(|ty| {
58+
Obligation::new(
59+
tcx,
60+
ObligationCause::dummy(),
61+
param_env,
62+
ty::ClauseKind::WellFormed(ty.into()),
63+
)
64+
}));
65+
let _errors = ocx.select_all_or_error();
66+
67+
// Cannot use `take_registered_region_obligations` as we may compute the response
68+
// inside of a `probe` whenever we have multiple choices inside of the solver.
69+
let region_obligations = infcx.take_registered_region_obligations();
70+
let region_constraints = infcx.take_and_reset_region_constraints();
71+
tcx.mk_outlives_from_iter(
72+
make_query_region_constraints(
73+
tcx,
74+
region_obligations
75+
.iter()
76+
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
77+
&region_constraints,
78+
)
79+
.outlives
80+
.into_iter()
81+
.map(|(o, _)| o),
82+
)
83+
})
84+
}

compiler/rustc_traits/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// tidy-alphabetical-end
66

77
mod codegen;
8+
mod coroutine_witnesses;
89
mod dropck_outlives;
910
mod evaluate_obligation;
1011
mod implied_outlives_bounds;
@@ -24,4 +25,5 @@ pub fn provide(p: &mut Providers) {
2425
normalize_erasing_regions::provide(p);
2526
type_op::provide(p);
2627
p.codegen_select_candidate = codegen::codegen_select_candidate;
28+
p.coroutine_hidden_types = coroutine_witnesses::coroutine_hidden_types;
2729
}

0 commit comments

Comments
 (0)