Skip to content

Commit d4b4738

Browse files
committed
Rollup merge of rust-lang#55921 - scalexm:placeholders, r=nikomatsakis
Add placeholder types Fixes rust-lang#48696 (handle universes in canonicalization of type inference vars), and fixes rust-lang#55098.
2 parents eef9507 + 1736391 commit d4b4738

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+413
-212
lines changed

src/librustc/ich/impls_ty.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,13 @@ for ty::TyKind<'gcx>
678678
Param(param_ty) => {
679679
param_ty.hash_stable(hcx, hasher);
680680
}
681-
Bound(bound_ty) => {
681+
Bound(debruijn, bound_ty) => {
682+
debruijn.hash_stable(hcx, hasher);
682683
bound_ty.hash_stable(hcx, hasher);
683684
}
685+
ty::Placeholder(placeholder_ty) => {
686+
placeholder_ty.hash_stable(hcx, hasher);
687+
}
684688
Foreign(def_id) => {
685689
def_id.hash_stable(hcx, hasher);
686690
}
@@ -1090,12 +1094,13 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
10901094

10911095
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
10921096
Ty(k),
1097+
PlaceholderTy(placeholder),
10931098
Region(ui),
10941099
PlaceholderRegion(placeholder),
10951100
});
10961101

10971102
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
1098-
General,
1103+
General(ui),
10991104
Int,
11001105
Float
11011106
});

src/librustc/infer/canonical/canonicalizer.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use infer::InferCtxt;
2323
use std::sync::atomic::Ordering;
2424
use ty::fold::{TypeFoldable, TypeFolder};
2525
use ty::subst::Kind;
26-
use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
26+
use ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
2727

2828
use rustc_data_structures::fx::FxHashMap;
2929
use rustc_data_structures::indexed_vec::Idx;
@@ -339,20 +339,51 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
339339

340340
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
341341
match t.sty {
342-
ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
342+
ty::Infer(ty::TyVar(vid)) => {
343+
match self.infcx.unwrap().probe_ty_var(vid) {
344+
// `t` could be a float / int variable: canonicalize that instead
345+
Ok(t) => self.fold_ty(t),
346+
347+
// `TyVar(vid)` is unresolved, track its universe index in the canonicalized
348+
// result
349+
Err(ui) => self.canonicalize_ty_var(
350+
CanonicalVarInfo {
351+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
352+
},
353+
t
354+
)
355+
}
356+
}
343357

344-
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
358+
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
359+
CanonicalVarInfo {
360+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
361+
},
362+
t
363+
),
345364

346-
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
365+
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
366+
CanonicalVarInfo {
367+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
368+
},
369+
t
370+
),
347371

348372
ty::Infer(ty::FreshTy(_))
349373
| ty::Infer(ty::FreshIntTy(_))
350374
| ty::Infer(ty::FreshFloatTy(_)) => {
351375
bug!("encountered a fresh type during canonicalization")
352376
}
353377

354-
ty::Bound(bound_ty) => {
355-
if bound_ty.index >= self.binder_index {
378+
ty::Placeholder(placeholder) => self.canonicalize_ty_var(
379+
CanonicalVarInfo {
380+
kind: CanonicalVarKind::PlaceholderTy(placeholder)
381+
},
382+
t
383+
),
384+
385+
ty::Bound(debruijn, _) => {
386+
if debruijn >= self.binder_index {
356387
bug!("escaping bound type during canonicalization")
357388
} else {
358389
t
@@ -408,9 +439,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
408439
V: TypeFoldable<'tcx> + Lift<'gcx>,
409440
{
410441
let needs_canonical_flags = if canonicalize_region_mode.any() {
411-
TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
442+
TypeFlags::KEEP_IN_LOCAL_TCX |
443+
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
444+
TypeFlags::HAS_TY_PLACEHOLDER
412445
} else {
413-
TypeFlags::KEEP_IN_LOCAL_TCX
446+
TypeFlags::KEEP_IN_LOCAL_TCX |
447+
TypeFlags::HAS_RE_PLACEHOLDER |
448+
TypeFlags::HAS_TY_PLACEHOLDER
414449
};
415450

416451
let gcx = tcx.global_tcx();
@@ -574,17 +609,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
574609
/// if `ty_var` is bound to anything; if so, canonicalize
575610
/// *that*. Otherwise, create a new canonical variable for
576611
/// `ty_var`.
577-
fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
612+
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
578613
let infcx = self.infcx.expect("encountered ty-var without infcx");
579614
let bound_to = infcx.shallow_resolve(ty_var);
580615
if bound_to != ty_var {
581616
self.fold_ty(bound_to)
582617
} else {
583-
let info = CanonicalVarInfo {
584-
kind: CanonicalVarKind::Ty(ty_kind),
585-
};
586618
let var = self.canonical_var(info, ty_var.into());
587-
self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
619+
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
588620
}
589621
}
590622
}

src/librustc/infer/canonical/mod.rs

+28-14
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ impl CanonicalVarInfo {
122122
pub fn is_existential(&self) -> bool {
123123
match self.kind {
124124
CanonicalVarKind::Ty(_) => true,
125+
CanonicalVarKind::PlaceholderTy(_) => false,
125126
CanonicalVarKind::Region(_) => true,
126127
CanonicalVarKind::PlaceholderRegion(..) => false,
127128
}
@@ -136,24 +137,27 @@ pub enum CanonicalVarKind {
136137
/// Some kind of type inference variable.
137138
Ty(CanonicalTyVarKind),
138139

140+
/// A "placeholder" that represents "any type".
141+
PlaceholderTy(ty::PlaceholderType),
142+
139143
/// Region variable `'?R`.
140144
Region(ty::UniverseIndex),
141145

142146
/// A "placeholder" that represents "any region". Created when you
143147
/// are solving a goal like `for<'a> T: Foo<'a>` to represent the
144148
/// bound region `'a`.
145-
PlaceholderRegion(ty::Placeholder),
149+
PlaceholderRegion(ty::PlaceholderRegion),
146150
}
147151

148152
impl CanonicalVarKind {
149153
pub fn universe(self) -> ty::UniverseIndex {
150154
match self {
151-
// At present, we don't support higher-ranked
152-
// quantification over types, so all type variables are in
153-
// the root universe.
154-
CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
155+
CanonicalVarKind::Ty(kind) => match kind {
156+
CanonicalTyVarKind::General(ui) => ui,
157+
CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
158+
}
155159

156-
// Region variables can be created in sub-universes.
160+
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
157161
CanonicalVarKind::Region(ui) => ui,
158162
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
159163
}
@@ -168,7 +172,7 @@ impl CanonicalVarKind {
168172
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
169173
pub enum CanonicalTyVarKind {
170174
/// General type variable `?T` that can be unified with arbitrary types.
171-
General,
175+
General(ty::UniverseIndex),
172176

173177
/// Integral type variable `?I` (that can only be unified with integral types).
174178
Int,
@@ -358,8 +362,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
358362
match cv_info.kind {
359363
CanonicalVarKind::Ty(ty_kind) => {
360364
let ty = match ty_kind {
361-
CanonicalTyVarKind::General => {
362-
self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
365+
CanonicalTyVarKind::General(ui) => {
366+
self.next_ty_var_in_universe(
367+
TypeVariableOrigin::MiscVariable(span),
368+
universe_map(ui)
369+
)
363370
}
364371

365372
CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
@@ -369,20 +376,27 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
369376
ty.into()
370377
}
371378

379+
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
380+
let universe_mapped = universe_map(universe);
381+
let placeholder_mapped = ty::PlaceholderType {
382+
universe: universe_mapped,
383+
name,
384+
};
385+
self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
386+
}
387+
372388
CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
373389
RegionVariableOrigin::MiscVariable(span),
374390
universe_map(ui),
375391
).into(),
376392

377-
CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe, name }) => {
393+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
378394
let universe_mapped = universe_map(universe);
379-
let placeholder_mapped = ty::Placeholder {
395+
let placeholder_mapped = ty::PlaceholderRegion {
380396
universe: universe_mapped,
381397
name,
382398
};
383-
self.tcx
384-
.mk_region(ty::RePlaceholder(placeholder_mapped))
385-
.into()
399+
self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
386400
}
387401
}
388402
}

src/librustc/infer/canonical/query_response.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -435,21 +435,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
435435
match result_value.unpack() {
436436
UnpackedKind::Type(result_value) => {
437437
// e.g., here `result_value` might be `?0` in the example above...
438-
if let ty::Bound(b) = result_value.sty {
438+
if let ty::Bound(debruijn, b) = result_value.sty {
439439
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
440440

441441
// We only allow a `ty::INNERMOST` index in substitutions.
442-
assert_eq!(b.index, ty::INNERMOST);
442+
assert_eq!(debruijn, ty::INNERMOST);
443443
opt_values[b.var] = Some(*original_value);
444444
}
445445
}
446446
UnpackedKind::Lifetime(result_value) => {
447447
// e.g., here `result_value` might be `'?1` in the example above...
448-
if let &ty::RegionKind::ReLateBound(index, br) = result_value {
448+
if let &ty::RegionKind::ReLateBound(debruijn, br) = result_value {
449449
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
450450

451451
// We only allow a `ty::INNERMOST` index in substitutions.
452-
assert_eq!(index, ty::INNERMOST);
452+
assert_eq!(debruijn, ty::INNERMOST);
453453
opt_values[br.assert_bound_var()] = Some(*original_value);
454454
}
455455
}

src/librustc/infer/freshen.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
170170
t
171171
}
172172

173-
ty::Bound(..) =>
174-
bug!("encountered bound ty during freshening"),
175-
176173
ty::Generator(..) |
177174
ty::Bool |
178175
ty::Char |
@@ -200,6 +197,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
200197
ty::Opaque(..) => {
201198
t.super_fold_with(self)
202199
}
200+
201+
ty::Placeholder(..) |
202+
ty::Bound(..) => bug!("unexpected type {:?}", t),
203203
}
204204
}
205205
}

src/librustc/infer/higher_ranked/mod.rs

+28-17
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
5353
// First, we instantiate each bound region in the supertype with a
5454
// fresh placeholder region.
5555
let (b_prime, placeholder_map) =
56-
self.infcx.replace_late_bound_regions_with_placeholders(b);
56+
self.infcx.replace_bound_vars_with_placeholders(b);
5757

5858
// Next, we instantiate each bound region in the subtype
5959
// with a fresh region variable. These region variables --
@@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
115115
// First, we instantiate each bound region in the matcher
116116
// with a placeholder region.
117117
let ((a_match, a_value), placeholder_map) =
118-
self.infcx.replace_late_bound_regions_with_placeholders(a_pair);
118+
self.infcx.replace_bound_vars_with_placeholders(a_pair);
119119

120120
debug!("higher_ranked_match: a_match={:?}", a_match);
121121
debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map);
@@ -314,10 +314,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
314314
region_vars
315315
}
316316

317-
/// Replace all regions bound by `binder` with placeholder regions and
318-
/// return a map indicating which bound-region was replaced with what
319-
/// placeholder region. This is the first step of checking subtyping
320-
/// when higher-ranked things are involved.
317+
/// Replace all regions (resp. types) bound by `binder` with placeholder
318+
/// regions (resp. types) and return a map indicating which bound-region
319+
/// was replaced with what placeholder region. This is the first step of
320+
/// checking subtyping when higher-ranked things are involved.
321321
///
322322
/// **Important:** you must call this function from within a snapshot.
323323
/// Moreover, before committing the snapshot, you must eventually call
@@ -330,26 +330,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
330330
/// the [rustc guide].
331331
///
332332
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
333-
pub fn replace_late_bound_regions_with_placeholders<T>(
333+
pub fn replace_bound_vars_with_placeholders<T>(
334334
&self,
335-
binder: &ty::Binder<T>,
335+
binder: &ty::Binder<T>
336336
) -> (T, PlaceholderMap<'tcx>)
337337
where
338-
T : TypeFoldable<'tcx>,
338+
T: TypeFoldable<'tcx>
339339
{
340340
let next_universe = self.create_next_universe();
341341

342-
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
343-
self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
342+
let fld_r = |br| {
343+
self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
344344
universe: next_universe,
345345
name: br,
346346
}))
347-
});
347+
};
348+
349+
let fld_t = |bound_ty: ty::BoundTy| {
350+
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
351+
universe: next_universe,
352+
name: bound_ty.var,
353+
}))
354+
};
355+
356+
let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t);
348357

349-
debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})",
350-
binder,
351-
result,
352-
map);
358+
debug!(
359+
"replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})",
360+
binder,
361+
result,
362+
map
363+
);
353364

354365
(result, map)
355366
}
@@ -530,7 +541,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
530541

531542
/// Pops the placeholder regions found in `placeholder_map` from the region
532543
/// inference context. Whenever you create placeholder regions via
533-
/// `replace_late_bound_regions_with_placeholders`, they must be popped before you
544+
/// `replace_bound_vars_with_placeholders`, they must be popped before you
534545
/// commit the enclosing snapshot (if you do not commit, e.g. within a
535546
/// probe or as a result of an error, then this is not necessary, as
536547
/// popping happens as part of the rollback).

0 commit comments

Comments
 (0)