Skip to content

Commit b37feca

Browse files
committed
Give precendence to regions from member constaints when inferring concrete types.
1 parent b552965 commit b37feca

File tree

4 files changed

+45
-17
lines changed

4 files changed

+45
-17
lines changed

compiler/rustc_borrowck/src/member_constraints.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::ops::Index;
1111

1212
/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
1313
/// indexed by the region `R0`.
14+
#[derive(Debug)]
1415
pub(crate) struct MemberConstraintSet<'tcx, R>
1516
where
1617
R: Copy + Eq,
@@ -31,6 +32,7 @@ where
3132
}
3233

3334
/// Represents a `R0 member of [R1..Rn]` constraint
35+
#[derive(Debug)]
3436
pub(crate) struct NllMemberConstraint<'tcx> {
3537
next_constraint: Option<NllMemberConstraintIndex>,
3638

compiler/rustc_borrowck/src/region_infer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub struct RegionInferenceContext<'tcx> {
128128
/// adds a new lower bound to the SCC it is analyzing: so you wind up
129129
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
130130
/// minimal viable option.
131+
#[derive(Debug)]
131132
pub(crate) struct AppliedMemberConstraint {
132133
/// The SCC that was affected. (The "member region".)
133134
///

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::fx::FxHashMap;
1+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
22
use rustc_data_structures::vec_map::VecMap;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_hir::OpaqueTyOrigin;
@@ -63,17 +63,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
6363
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
6464
) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
6565
let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
66+
67+
let member_constraints: FxHashMap<_, _> = self
68+
.member_constraints
69+
.all_indices()
70+
.map(|ci| (self.member_constraints[ci].key, ci))
71+
.collect();
72+
debug!(?member_constraints);
73+
6674
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
6775
let substs = opaque_type_key.substs;
6876
debug!(?concrete_type, ?substs);
6977

7078
let mut subst_regions = vec![self.universal_regions.fr_static];
71-
let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
72-
if let ty::RePlaceholder(..) = region.kind() {
73-
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
74-
return region;
75-
}
76-
let vid = self.to_region_vid(region);
79+
80+
let to_universal_region = |vid, subst_regions: &mut Vec<_>| {
7781
trace!(?vid);
7882
let scc = self.constraint_sccs.scc(vid);
7983
trace!(?scc);
@@ -94,10 +98,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9498
infcx.tcx.lifetimes.re_static
9599
}
96100
}
101+
};
102+
103+
// Start by inserting universal regions from the member_constraint choice regions.
104+
// This will ensure they get precedence when folding the regions in the concrete type.
105+
if let Some(&ci) = member_constraints.get(&opaque_type_key) {
106+
for &vid in self.member_constraints.choice_regions(ci) {
107+
to_universal_region(vid, &mut subst_regions);
108+
}
109+
}
110+
debug!(?subst_regions);
111+
112+
// Next, insert universal regions from substs, so we can translate regions that appear
113+
// in them but are not subject to member constraints, for instance closure substs.
114+
let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
115+
if let ty::RePlaceholder(..) = region.kind() {
116+
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
117+
return region;
118+
}
119+
let vid = self.to_region_vid(region);
120+
to_universal_region(vid, &mut subst_regions)
97121
});
122+
debug!(?universal_substs);
123+
debug!(?subst_regions);
98124

99-
subst_regions.sort();
100-
subst_regions.dedup();
125+
// Deduplicate the set of regions while keeping the chosen order.
126+
let subst_regions = subst_regions.into_iter().collect::<FxIndexSet<_>>();
127+
debug!(?subst_regions);
101128

102129
let universal_concrete_type =
103130
infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
@@ -108,8 +135,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
108135
.unwrap_or(infcx.tcx.lifetimes.re_erased),
109136
_ => region,
110137
});
111-
112-
debug!(?universal_concrete_type, ?universal_substs);
138+
debug!(?universal_concrete_type);
113139

114140
let opaque_type_key =
115141
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };

compiler/rustc_middle/src/ty/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
12571257
}
12581258
}
12591259

1260-
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)]
1260+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
12611261
#[derive(TypeFoldable, TypeVisitable)]
12621262
pub struct OpaqueTypeKey<'tcx> {
12631263
pub def_id: LocalDefId,
@@ -1333,17 +1333,16 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
13331333
debug!(?id_substs);
13341334

13351335
// This zip may have several times the same lifetime in `substs` paired with a different
1336-
// lifetime from `id_substs`. In that case, we actually want to pick the last one, as it
1337-
// is the one we introduced in the impl-trait desugaring to be meaningful. The other ones
1338-
// are redundant.
1336+
// lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
1337+
// it will pick the last one, which is the one we introduced in the impl-trait desugaring.
13391338
let map = substs.iter().zip(id_substs);
13401339

13411340
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = match origin {
13421341
// HACK: The HIR lowering for async fn does not generate
13431342
// any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes
13441343
// would now fail to compile. We should probably just make hir lowering fill this in properly.
1345-
OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::AsyncFn(_) => map.collect(),
1346-
OpaqueTyOrigin::TyAlias => {
1344+
OpaqueTyOrigin::AsyncFn(_) => map.collect(),
1345+
OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::TyAlias => {
13471346
// Opaque types may only use regions that are bound. So for
13481347
// ```rust
13491348
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;

0 commit comments

Comments
 (0)