Skip to content

Commit 5eda136

Browse files
committed
Auto merge of #55305 - nikomatsakis:universes-refactor-3, r=scalexm
universes refactor 3 Some more refactorings from my universe branch. These are getting a bit more "invasive" -- they start to plumb the universe information through the canonicalization process. As of yet though I don't **believe** this branch changes our behavior in any notable way, though I'm marking the branch as `WIP` to give myself a chance to verify this. r? @scalexm
2 parents d06210f + c244fd7 commit 5eda136

27 files changed

+667
-557
lines changed

src/librustc/ich/impls_ty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
12291229

12301230
impl_stable_hash_for!(
12311231
impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
1232-
variables, value
1232+
max_universe, variables, value
12331233
}
12341234
);
12351235

@@ -1245,7 +1245,8 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
12451245

12461246
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
12471247
Ty(k),
1248-
Region
1248+
Region(ui),
1249+
PlaceholderRegion(placeholder),
12491250
});
12501251

12511252
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {

src/librustc/infer/canonical/canonicalizer.rs

+107-9
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
107107
)
108108
}
109109

110+
pub fn canonicalize_user_type_annotation<V>(&self, value: &V) -> Canonicalized<'gcx, V>
111+
where
112+
V: TypeFoldable<'tcx> + Lift<'gcx>,
113+
{
114+
let mut query_state = OriginalQueryValues::default();
115+
Canonicalizer::canonicalize(
116+
value,
117+
Some(self),
118+
self.tcx,
119+
&CanonicalizeUserTypeAnnotation,
120+
&mut query_state,
121+
)
122+
}
123+
110124
/// A hacky variant of `canonicalize_query` that does not
111125
/// canonicalize `'static`. Unfortunately, the existing leak
112126
/// check treaks `'static` differently in some cases (see also
@@ -162,11 +176,26 @@ struct CanonicalizeQueryResponse;
162176
impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
163177
fn canonicalize_free_region(
164178
&self,
165-
_canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
179+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
166180
r: ty::Region<'tcx>,
167181
) -> ty::Region<'tcx> {
168182
match r {
169183
ty::ReFree(_) | ty::ReEmpty | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
184+
ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
185+
CanonicalVarInfo {
186+
kind: CanonicalVarKind::PlaceholderRegion(*placeholder),
187+
},
188+
r,
189+
),
190+
ty::ReVar(vid) => {
191+
let universe = canonicalizer.region_var_universe(*vid);
192+
canonicalizer.canonical_var_for_region(
193+
CanonicalVarInfo {
194+
kind: CanonicalVarKind::Region(universe),
195+
},
196+
r,
197+
)
198+
}
170199
_ => {
171200
// Other than `'static` or `'empty`, the query
172201
// response should be executing in a fully
@@ -182,6 +211,29 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
182211
}
183212
}
184213

214+
struct CanonicalizeUserTypeAnnotation;
215+
216+
impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
217+
fn canonicalize_free_region(
218+
&self,
219+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
220+
r: ty::Region<'tcx>,
221+
) -> ty::Region<'tcx> {
222+
match r {
223+
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReEmpty | ty::ReStatic => r,
224+
ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
225+
_ => {
226+
// We only expect region names that the user can type.
227+
bug!("unexpected region in query response: `{:?}`", r)
228+
}
229+
}
230+
}
231+
232+
fn any(&self) -> bool {
233+
false
234+
}
235+
}
236+
185237
struct CanonicalizeAllFreeRegions;
186238

187239
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
@@ -190,7 +242,7 @@ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
190242
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
191243
r: ty::Region<'tcx>,
192244
) -> ty::Region<'tcx> {
193-
canonicalizer.canonical_var_for_region(r)
245+
canonicalizer.canonical_var_for_region_in_root_universe(r)
194246
}
195247

196248
fn any(&self) -> bool {
@@ -209,7 +261,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
209261
if let ty::ReStatic = r {
210262
r
211263
} else {
212-
canonicalizer.canonical_var_for_region(r)
264+
canonicalizer.canonical_var_for_region_in_root_universe(r)
213265
}
214266
}
215267

@@ -252,7 +304,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
252304
opportunistically resolved to {:?}",
253305
vid, r
254306
);
255-
self.canonical_var_for_region(r)
307+
self.canonicalize_region_mode
308+
.canonicalize_free_region(self, r)
256309
}
257310

258311
ty::ReStatic
@@ -261,7 +314,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
261314
| ty::ReScope(_)
262315
| ty::RePlaceholder(..)
263316
| ty::ReEmpty
264-
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
317+
| ty::ReErased => self.canonicalize_region_mode
318+
.canonicalize_free_region(self, r),
265319

266320
ty::ReClosureBound(..) | ty::ReCanonical(_) => {
267321
bug!("canonical region encountered during canonicalization")
@@ -353,6 +407,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
353407
if !value.has_type_flags(needs_canonical_flags) {
354408
let out_value = gcx.lift(value).unwrap();
355409
let canon_value = Canonical {
410+
max_universe: ty::UniverseIndex::ROOT,
356411
variables: List::empty(),
357412
value: out_value,
358413
};
@@ -383,7 +438,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
383438

384439
let canonical_variables = tcx.intern_canonical_var_infos(&canonicalizer.variables);
385440

441+
let max_universe = canonical_variables
442+
.iter()
443+
.map(|cvar| cvar.universe())
444+
.max()
445+
.unwrap_or(ty::UniverseIndex::ROOT);
446+
386447
Canonical {
448+
max_universe,
387449
variables: canonical_variables,
388450
value: out_value,
389451
}
@@ -450,10 +512,46 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
450512
}
451513
}
452514

453-
fn canonical_var_for_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
454-
let info = CanonicalVarInfo {
455-
kind: CanonicalVarKind::Region,
456-
};
515+
/// Shorthand helper that creates a canonical region variable for
516+
/// `r` (always in the root universe). The reason that we always
517+
/// put these variables into the root universe is because this
518+
/// method is used during **query construction:** in that case, we
519+
/// are taking all the regions and just putting them into the most
520+
/// generic context we can. This may generate solutions that don't
521+
/// fit (e.g., that equate some region variable with a placeholder
522+
/// it can't name) on the caller side, but that's ok, the caller
523+
/// can figure that out. In the meantime, it maximizes our
524+
/// caching.
525+
///
526+
/// (This works because unification never fails -- and hence trait
527+
/// selection is never affected -- due to a universe mismatch.)
528+
fn canonical_var_for_region_in_root_universe(
529+
&mut self,
530+
r: ty::Region<'tcx>,
531+
) -> ty::Region<'tcx> {
532+
self.canonical_var_for_region(
533+
CanonicalVarInfo {
534+
kind: CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
535+
},
536+
r,
537+
)
538+
}
539+
540+
/// Returns the universe in which `vid` is defined.
541+
fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
542+
self.infcx
543+
.unwrap()
544+
.borrow_region_constraints()
545+
.var_universe(vid)
546+
}
547+
548+
/// Create a canonical variable (with the given `info`)
549+
/// representing the region `r`; return a region referencing it.
550+
fn canonical_var_for_region(
551+
&mut self,
552+
info: CanonicalVarInfo,
553+
r: ty::Region<'tcx>,
554+
) -> ty::Region<'tcx> {
457555
let b = self.canonical_var(info, r.into());
458556
debug_assert_eq!(ty::INNERMOST, b.level);
459557
self.tcx().mk_region(ty::ReCanonical(b.var))

0 commit comments

Comments
 (0)