Auto merge of #55921 - scalexm:placeholders, r=nikomatsakis

Add placeholder types

Fixes #48696 (handle universes in canonicalization of type inference vars), and fixes #55098.
This commit is contained in:
bors 2018-11-25 06:48:21 +00:00
commit abe19a7305
52 changed files with 412 additions and 210 deletions

View file

@ -684,9 +684,13 @@ for ty::TyKind<'gcx>
Param(param_ty) => {
param_ty.hash_stable(hcx, hasher);
}
Bound(bound_ty) => {
Bound(debruijn, bound_ty) => {
debruijn.hash_stable(hcx, hasher);
bound_ty.hash_stable(hcx, hasher);
}
ty::Placeholder(placeholder_ty) => {
placeholder_ty.hash_stable(hcx, hasher);
}
Foreign(def_id) => {
def_id.hash_stable(hcx, hasher);
}
@ -1096,12 +1100,13 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
Ty(k),
PlaceholderTy(placeholder),
Region(ui),
PlaceholderRegion(placeholder),
});
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
General,
General(ui),
Int,
Float
});

View file

@ -23,7 +23,7 @@ use infer::InferCtxt;
use std::sync::atomic::Ordering;
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::Kind;
use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
use ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
@ -339,11 +339,35 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.sty {
ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
ty::Infer(ty::TyVar(vid)) => {
match self.infcx.unwrap().probe_ty_var(vid) {
// `t` could be a float / int variable: canonicalize that instead
Ok(t) => self.fold_ty(t),
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
// `TyVar(vid)` is unresolved, track its universe index in the canonicalized
// result
Err(ui) => self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
},
t
)
}
}
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
},
t
),
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
},
t
),
ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
@ -351,8 +375,15 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
bug!("encountered a fresh type during canonicalization")
}
ty::Bound(bound_ty) => {
if bound_ty.index >= self.binder_index {
ty::Placeholder(placeholder) => self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::PlaceholderTy(placeholder)
},
t
),
ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
t
@ -408,9 +439,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
V: TypeFoldable<'tcx> + Lift<'gcx>,
{
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
TypeFlags::KEEP_IN_LOCAL_TCX |
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
TypeFlags::HAS_TY_PLACEHOLDER
} else {
TypeFlags::KEEP_IN_LOCAL_TCX
TypeFlags::KEEP_IN_LOCAL_TCX |
TypeFlags::HAS_RE_PLACEHOLDER |
TypeFlags::HAS_TY_PLACEHOLDER
};
let gcx = tcx.global_tcx();
@ -574,17 +609,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
/// if `ty_var` is bound to anything; if so, canonicalize
/// *that*. Otherwise, create a new canonical variable for
/// `ty_var`.
fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
let infcx = self.infcx.expect("encountered ty-var without infcx");
let bound_to = infcx.shallow_resolve(ty_var);
if bound_to != ty_var {
self.fold_ty(bound_to)
} else {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Ty(ty_kind),
};
let var = self.canonical_var(info, ty_var.into());
self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
}
}
}

View file

@ -122,6 +122,7 @@ impl CanonicalVarInfo {
pub fn is_existential(&self) -> bool {
match self.kind {
CanonicalVarKind::Ty(_) => true,
CanonicalVarKind::PlaceholderTy(_) => false,
CanonicalVarKind::Region(_) => true,
CanonicalVarKind::PlaceholderRegion(..) => false,
}
@ -136,24 +137,27 @@ pub enum CanonicalVarKind {
/// Some kind of type inference variable.
Ty(CanonicalTyVarKind),
/// A "placeholder" that represents "any type".
PlaceholderTy(ty::PlaceholderType),
/// Region variable `'?R`.
Region(ty::UniverseIndex),
/// A "placeholder" that represents "any region". Created when you
/// are solving a goal like `for<'a> T: Foo<'a>` to represent the
/// bound region `'a`.
PlaceholderRegion(ty::Placeholder),
PlaceholderRegion(ty::PlaceholderRegion),
}
impl CanonicalVarKind {
pub fn universe(self) -> ty::UniverseIndex {
match self {
// At present, we don't support higher-ranked
// quantification over types, so all type variables are in
// the root universe.
CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
CanonicalVarKind::Ty(kind) => match kind {
CanonicalTyVarKind::General(ui) => ui,
CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
}
// Region variables can be created in sub-universes.
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
CanonicalVarKind::Region(ui) => ui,
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
}
@ -168,7 +172,7 @@ impl CanonicalVarKind {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
pub enum CanonicalTyVarKind {
/// General type variable `?T` that can be unified with arbitrary types.
General,
General(ty::UniverseIndex),
/// Integral type variable `?I` (that can only be unified with integral types).
Int,
@ -358,8 +362,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
match cv_info.kind {
CanonicalVarKind::Ty(ty_kind) => {
let ty = match ty_kind {
CanonicalTyVarKind::General => {
self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
CanonicalTyVarKind::General(ui) => {
self.next_ty_var_in_universe(
TypeVariableOrigin::MiscVariable(span),
universe_map(ui)
)
}
CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
@ -369,20 +376,27 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
ty.into()
}
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderType {
universe: universe_mapped,
name,
};
self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
}
CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
RegionVariableOrigin::MiscVariable(span),
universe_map(ui),
).into(),
CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe, name }) => {
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::Placeholder {
let placeholder_mapped = ty::PlaceholderRegion {
universe: universe_mapped,
name,
};
self.tcx
.mk_region(ty::RePlaceholder(placeholder_mapped))
.into()
self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
}
}
}

View file

@ -435,21 +435,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
match result_value.unpack() {
UnpackedKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above...
if let ty::Bound(b) = result_value.sty {
if let ty::Bound(debruijn, b) = result_value.sty {
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(b.index, ty::INNERMOST);
assert_eq!(debruijn, ty::INNERMOST);
opt_values[b.var] = Some(*original_value);
}
}
UnpackedKind::Lifetime(result_value) => {
// e.g., here `result_value` might be `'?1` in the example above...
if let &ty::RegionKind::ReLateBound(index, br) = result_value {
if let &ty::RegionKind::ReLateBound(debruijn, br) = result_value {
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(index, ty::INNERMOST);
assert_eq!(debruijn, ty::INNERMOST);
opt_values[br.assert_bound_var()] = Some(*original_value);
}
}

View file

@ -170,9 +170,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
t
}
ty::Bound(..) =>
bug!("encountered bound ty during freshening"),
ty::Generator(..) |
ty::Bool |
ty::Char |
@ -200,6 +197,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::Opaque(..) => {
t.super_fold_with(self)
}
ty::Placeholder(..) |
ty::Bound(..) => bug!("unexpected type {:?}", t),
}
}
}

View file

@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
// First, we instantiate each bound region in the supertype with a
// fresh placeholder region.
let (b_prime, placeholder_map) =
self.infcx.replace_late_bound_regions_with_placeholders(b);
self.infcx.replace_bound_vars_with_placeholders(b);
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
// First, we instantiate each bound region in the matcher
// with a placeholder region.
let ((a_match, a_value), placeholder_map) =
self.infcx.replace_late_bound_regions_with_placeholders(a_pair);
self.infcx.replace_bound_vars_with_placeholders(a_pair);
debug!("higher_ranked_match: a_match={:?}", a_match);
debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map);
@ -314,10 +314,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
region_vars
}
/// Replace all regions bound by `binder` with placeholder regions and
/// return a map indicating which bound-region was replaced with what
/// placeholder region. This is the first step of checking subtyping
/// when higher-ranked things are involved.
/// Replace all regions (resp. types) bound by `binder` with placeholder
/// regions (resp. types) and return a map indicating which bound-region
/// was replaced with what placeholder region. This is the first step of
/// checking subtyping when higher-ranked things are involved.
///
/// **Important:** you must call this function from within a snapshot.
/// Moreover, before committing the snapshot, you must eventually call
@ -330,26 +330,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// the [rustc guide].
///
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
pub fn replace_late_bound_regions_with_placeholders<T>(
pub fn replace_bound_vars_with_placeholders<T>(
&self,
binder: &ty::Binder<T>,
binder: &ty::Binder<T>
) -> (T, PlaceholderMap<'tcx>)
where
T : TypeFoldable<'tcx>,
T: TypeFoldable<'tcx>
{
let next_universe = self.create_next_universe();
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
let fld_r = |br| {
self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
universe: next_universe,
name: br,
}))
});
};
debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})",
binder,
result,
map);
let fld_t = |bound_ty: ty::BoundTy| {
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: next_universe,
name: bound_ty.var,
}))
};
let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t);
debug!(
"replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})",
binder,
result,
map
);
(result, map)
}
@ -530,7 +541,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// Pops the placeholder regions found in `placeholder_map` from the region
/// inference context. Whenever you create placeholder regions via
/// `replace_late_bound_regions_with_placeholders`, they must be popped before you
/// `replace_bound_vars_with_placeholders`, they must be popped before you
/// commit the enclosing snapshot (if you do not commit, e.g. within a
/// probe or as a result of an error, then this is not necessary, as
/// popping happens as part of the rollback).

View file

@ -227,7 +227,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
universe: Cell<ty::UniverseIndex>,
}
/// A map returned by `replace_late_bound_regions_with_placeholders()`
/// A map returned by `replace_bound_vars_with_placeholders()`
/// indicating the placeholder region that each late-bound region was
/// replaced with.
pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
@ -411,7 +411,7 @@ pub enum NLLRegionVariableOrigin {
/// "Universal" instantiation of a higher-ranked region (e.g.,
/// from a `for<'a> T` binder). Meant to represent "any region".
Placeholder(ty::Placeholder),
Placeholder(ty::PlaceholderRegion),
Existential,
}
@ -935,7 +935,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
b,
},
placeholder_map,
) = self.replace_late_bound_regions_with_placeholders(predicate);
) = self.replace_bound_vars_with_placeholders(predicate);
let cause_span = cause.span;
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@ -952,7 +952,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
) -> UnitResult<'tcx> {
self.commit_if_ok(|snapshot| {
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
self.replace_late_bound_regions_with_placeholders(predicate);
self.replace_bound_vars_with_placeholders(predicate);
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
});
@ -972,6 +972,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.tcx.mk_var(self.next_ty_var_id(false, origin))
}
pub fn next_ty_var_in_universe(
&self,
origin: TypeVariableOrigin,
universe: ty::UniverseIndex
) -> Ty<'tcx> {
let vid = self.type_variables
.borrow_mut()
.new_var(universe, false, origin);
self.tcx.mk_var(vid)
}
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(true, origin))
}
@ -1227,6 +1238,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the
/// universe index of `TyVar(vid)`.
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
use self::type_variable::TypeVariableValue;
match self.type_variables.borrow_mut().probe(vid) {
TypeVariableValue::Known { value } => Ok(value),
TypeVariableValue::Unknown { universe } => Err(universe),
}
}
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
self.inlined_shallow_resolve(typ)
}

View file

@ -95,7 +95,7 @@ pub trait TypeRelatingDelegate<'tcx> {
/// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
/// we will invoke this method to instantiate `'b` with a
/// placeholder region.
fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx>;
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>;
/// Creates a new existential region in the given universe. This
/// is used when handling subtyping and type variables -- if we
@ -176,7 +176,7 @@ where
universe
});
let placeholder = ty::Placeholder { universe, name: br };
let placeholder = ty::PlaceholderRegion { universe, name: br };
delegate.next_placeholder_region(placeholder)
} else {
delegate.next_existential_region_var()

View file

@ -72,7 +72,7 @@ pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
struct TypeVariableData {
origin: TypeVariableOrigin,
diverging: bool
diverging: bool,
}
#[derive(Copy, Clone, Debug)]

View file

@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
false
}
ty::Bound(..) | ty::Infer(..) => match in_crate {
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
InCrate::Local => false,
// The inference variable might be unified with a local
// type in that remote crate.

View file

@ -281,7 +281,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::Generator(..) => Some(18),
ty::Foreign(..) => Some(19),
ty::GeneratorWitness(..) => Some(20),
ty::Bound(..) | ty::Infer(..) | ty::Error => None,
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
}
}

View file

@ -204,7 +204,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
let infcx = selcx.infcx();
infcx.commit_if_ok(|snapshot| {
let (placeholder_predicate, placeholder_map) =
infcx.replace_late_bound_regions_with_placeholders(&obligation.predicate);
infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
let skol_obligation = obligation.with(placeholder_predicate);
let r = match project_and_unify_type(selcx, &skol_obligation) {
@ -424,7 +424,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.selcx.tcx().global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_skol() {
if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = Substs::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
if let Some(instance) = instance {
@ -1656,7 +1656,7 @@ impl<'tcx> ProjectionCache<'tcx> {
}
pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol());
self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders());
}
pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) {

View file

@ -251,6 +251,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
| ty::Projection(..)
| ty::Param(_)
| ty::Opaque(..)
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Bound(..)
| ty::Generator(..) => false,

View file

@ -202,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.infcx.tcx.global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_skol() {
if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = Substs::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
if let Some(instance) = instance {

View file

@ -1726,7 +1726,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let poly_trait_predicate = self.infcx()
.resolve_type_vars_if_possible(&obligation.predicate);
let (skol_trait_predicate, placeholder_map) = self.infcx()
.replace_late_bound_regions_with_placeholders(&poly_trait_predicate);
.replace_bound_vars_with_placeholders(&poly_trait_predicate);
debug!(
"match_projection_obligation_against_definition_bounds: \
skol_trait_predicate={:?} placeholder_map={:?}",
@ -2470,7 +2470,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::Infer(ty::TyVar(_)) => Ambiguous,
ty::UnnormalizedProjection(..)
| ty::Bound(_)
| ty::Placeholder(..)
| ty::Bound(..)
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
@ -2555,7 +2556,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
ty::UnnormalizedProjection(..)
| ty::Bound(_)
| ty::Placeholder(..)
| ty::Bound(..)
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
@ -2594,11 +2596,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
| ty::Char => Vec::new(),
ty::UnnormalizedProjection(..)
| ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
| ty::Projection(..)
| ty::Bound(_)
| ty::Bound(..)
| ty::Infer(ty::TyVar(_))
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
@ -2682,7 +2685,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
self.in_snapshot(|this, snapshot| {
let (skol_ty, placeholder_map) = this.infcx()
.replace_late_bound_regions_with_placeholders(&ty);
.replace_bound_vars_with_placeholders(&ty);
let Normalized {
value: normalized_ty,
mut obligations,
@ -2916,7 +2919,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let trait_obligations: Vec<PredicateObligation<'_>> = self.in_snapshot(|this, snapshot| {
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
let (trait_ref, placeholder_map) = this.infcx()
.replace_late_bound_regions_with_placeholders(&poly_trait_ref);
.replace_bound_vars_with_placeholders(&poly_trait_ref);
let cause = obligation.derived_cause(ImplDerivedObligation);
this.impl_or_trait_obligations(
cause,
@ -3119,7 +3122,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
self.in_snapshot(|this, snapshot| {
let (predicate, placeholder_map) = this.infcx()
.replace_late_bound_regions_with_placeholders(&obligation.predicate);
.replace_bound_vars_with_placeholders(&obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
let substs = trait_ref.substs;
@ -3582,7 +3585,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
let (skol_obligation, placeholder_map) = self.infcx()
.replace_late_bound_regions_with_placeholders(&obligation.predicate);
.replace_bound_vars_with_placeholders(&obligation.predicate);
let skol_obligation_trait_ref = skol_obligation.trait_ref;
let impl_substs = self.infcx

View file

@ -324,7 +324,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
use syntax::symbol::Symbol;
match t.sty {
ty::Bound(bound_ty) if bound_ty.index == self.binder_index => {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
self.types.insert(
bound_ty.var.as_u32(),
match bound_ty.kind {

View file

@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
pub fn print_debug_stats(self) {
sty_debug_print!(
self,
Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Placeholder,
Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);

View file

@ -212,7 +212,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
ty::Infer(ty::IntVar(_)) => "integral variable".into(),
ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
ty::Bound(_) |
ty::Placeholder(..) => "placeholder type".into(),
ty::Bound(..) => "bound type".into(),
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),

View file

@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::Foreign(def_id) => {
Some(ForeignSimplifiedType(def_id))
}
ty::Bound(..) | ty::Infer(_) | ty::Error => None,
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error => None,
}
}

View file

@ -115,8 +115,12 @@ impl FlagComputation {
self.add_substs(&substs.substs);
}
&ty::Bound(bound_ty) => {
self.add_binder(bound_ty.index);
&ty::Bound(debruijn, _) => {
self.add_binder(debruijn);
}
&ty::Placeholder(..) => {
self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
}
&ty::Infer(infer) => {

View file

@ -102,14 +102,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn needs_infer(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
}
fn has_skol(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_SKOL)
fn has_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER | TypeFlags::HAS_TY_PLACEHOLDER)
}
fn needs_subst(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST)
}
fn has_re_skol(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_SKOL)
fn has_re_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER)
}
fn has_closure_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
@ -460,8 +460,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx>
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.sty {
ty::Bound(bound_ty) => {
if bound_ty.index == self.current_index {
ty::Bound(debruijn, bound_ty) => {
if debruijn == self.current_index {
let fld_t = &mut self.fld_t;
let ty = fld_t(bound_ty);
ty::fold::shift_vars(
@ -526,7 +526,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
T: TypeFoldable<'tcx>
{
// identity for bound types
let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty));
self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
}
@ -722,16 +722,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
match ty.sty {
ty::Bound(bound_ty) => {
if self.amount == 0 || bound_ty.index < self.current_index {
ty::Bound(debruijn, bound_ty) => {
if self.amount == 0 || debruijn < self.current_index {
ty
} else {
let shifted = ty::BoundTy {
index: bound_ty.index.shifted_in(self.amount),
var: bound_ty.var,
kind: bound_ty.kind,
};
self.tcx.mk_ty(ty::Bound(shifted))
self.tcx.mk_ty(
ty::Bound(debruijn.shifted_in(self.amount), bound_ty)
)
}
}

View file

@ -515,6 +515,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
ty::Str |
ty::FnPtr(_) |
ty::Projection(_) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::Param(_) |
ty::Opaque(..) |

View file

@ -1159,6 +1159,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}
ty::Bound(..) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::GeneratorWitness(..) |
ty::Infer(_) => {
@ -1743,7 +1744,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
}
ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) |
ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
ty::Placeholder(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) |
ty::Error => {
bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
}
})

View file

@ -432,7 +432,7 @@ bitflags! {
const HAS_SELF = 1 << 1;
const HAS_TY_INFER = 1 << 2;
const HAS_RE_INFER = 1 << 3;
const HAS_RE_SKOL = 1 << 4;
const HAS_RE_PLACEHOLDER = 1 << 4;
/// Does this have any `ReEarlyBound` regions? Used to
/// determine whether substitition is required, since those
@ -467,6 +467,8 @@ bitflags! {
/// if a global bound is safe to evaluate.
const HAS_RE_LATE_BOUND = 1 << 13;
const HAS_TY_PLACEHOLDER = 1 << 14;
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits;
@ -478,7 +480,7 @@ bitflags! {
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_TY_INFER.bits |
TypeFlags::HAS_RE_INFER.bits |
TypeFlags::HAS_RE_SKOL.bits |
TypeFlags::HAS_RE_PLACEHOLDER.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits |
TypeFlags::HAS_FREE_REGIONS.bits |
TypeFlags::HAS_TY_ERR.bits |
@ -486,7 +488,8 @@ bitflags! {
TypeFlags::HAS_TY_CLOSURE.bits |
TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
TypeFlags::KEEP_IN_LOCAL_TCX.bits |
TypeFlags::HAS_RE_LATE_BOUND.bits;
TypeFlags::HAS_RE_LATE_BOUND.bits |
TypeFlags::HAS_TY_PLACEHOLDER.bits;
}
}
@ -1587,12 +1590,27 @@ impl UniverseIndex {
/// universe are just two regions with an unknown relationship to one
/// another.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub struct Placeholder {
pub struct Placeholder<T> {
pub universe: UniverseIndex,
pub name: BoundRegion,
pub name: T,
}
impl_stable_hash_for!(struct Placeholder { universe, name });
impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for Placeholder<T>
where T: HashStable<StableHashingContext<'a>>
{
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>
) {
self.universe.hash_stable(hcx, hasher);
self.name.hash_stable(hcx, hasher);
}
}
pub type PlaceholderRegion = Placeholder<BoundRegion>;
pub type PlaceholderType = Placeholder<BoundVar>;
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
@ -1674,7 +1692,7 @@ impl<'tcx> ParamEnv<'tcx> {
}
Reveal::All => {
if value.has_skol()
if value.has_placeholders()
|| value.needs_infer()
|| value.has_param_types()
|| value.has_self_ty()
@ -2430,6 +2448,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}
}
Placeholder(..) |
Bound(..) |
Infer(..) => {
bug!("unexpected type `{:?}` in sized_constraint_for_ty",

View file

@ -155,6 +155,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ty::FnDef(..) | // OutlivesFunction (*)
ty::FnPtr(_) | // OutlivesFunction (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::Placeholder(..) |
ty::Bound(..) |
ty::Error => {
// (*) Bare functions and traits are both binders. In the

View file

@ -746,6 +746,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::Infer(_) |
ty::Param(..) |
ty::Bound(..) |
ty::Placeholder(..) |
ty::Never |
ty::Foreign(..) => return self
};
@ -792,6 +793,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::Error |
ty::Infer(_) |
ty::Bound(..) |
ty::Placeholder(..) |
ty::Param(..) |
ty::Never |
ty::Foreign(..) => false,

View file

@ -201,7 +201,10 @@ pub enum TyKind<'tcx> {
Param(ParamTy),
/// Bound type variable, used only when preparing a trait query.
Bound(BoundTy),
Bound(ty::DebruijnIndex, BoundTy),
/// A placeholder type - universally quantified higher-ranked type.
Placeholder(ty::PlaceholderType),
/// A type variable used during type checking.
Infer(InferTy),
@ -1165,7 +1168,7 @@ pub enum RegionKind {
/// A placeholder region - basically the higher-ranked version of ReFree.
/// Should not exist after typeck.
RePlaceholder(ty::Placeholder),
RePlaceholder(ty::PlaceholderRegion),
/// Empty lifetime is for data that is never accessed.
/// Bottom in the region lattice. We treat ReEmpty somewhat
@ -1242,7 +1245,6 @@ newtype_index! {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct BoundTy {
pub index: DebruijnIndex,
pub var: BoundVar,
pub kind: BoundTyKind,
}
@ -1253,13 +1255,12 @@ pub enum BoundTyKind {
Param(InternedString),
}
impl_stable_hash_for!(struct BoundTy { index, var, kind });
impl_stable_hash_for!(struct BoundTy { var, kind });
impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
impl BoundTy {
pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
impl From<BoundVar> for BoundTy {
fn from(var: BoundVar) -> Self {
BoundTy {
index,
var,
kind: BoundTyKind::Anon,
}
@ -1462,7 +1463,7 @@ impl RegionKind {
}
ty::RePlaceholder(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_RE_SKOL;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
}
ty::ReLateBound(..) => {
flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
@ -1890,6 +1891,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
Foreign(..) |
Param(_) |
Bound(..) |
Placeholder(..) |
Infer(_) |
Error => {}
}
@ -1953,7 +1955,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
ty::Infer(ty::TyVar(_)) => false,
ty::Bound(_) |
ty::Bound(..) |
ty::Placeholder(..) |
ty::Infer(ty::FreshTy(_)) |
ty::Infer(ty::FreshIntTy(_)) |
ty::Infer(ty::FreshFloatTy(_)) =>

View file

@ -190,11 +190,12 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
Substs::for_item(tcx, def_id, |param, _| {
match param.kind {
ty::GenericParamDefKind::Type { .. } => {
tcx.mk_ty(ty::Bound(ty::BoundTy {
index: ty::INNERMOST,
var: ty::BoundVar::from(param.index),
kind: ty::BoundTyKind::Param(param.name),
})).into()
tcx.mk_ty(
ty::Bound(ty::INNERMOST, ty::BoundTy {
var: ty::BoundVar::from(param.index),
kind: ty::BoundTyKind::Param(param.name),
})
).into()
}
ty::GenericParamDefKind::Lifetime => {
@ -584,18 +585,18 @@ impl CanonicalUserSubsts<'tcx> {
self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
match kind.unpack() {
UnpackedKind::Type(ty) => match ty.sty {
ty::Bound(b) => {
ty::Bound(debruijn, b) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(b.index, ty::INNERMOST);
assert_eq!(debruijn, ty::INNERMOST);
cvar == b.var
}
_ => false,
},
UnpackedKind::Lifetime(r) => match r {
ty::ReLateBound(index, br) => {
ty::ReLateBound(debruijn, br) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(*index, ty::INNERMOST);
assert_eq!(*debruijn, ty::INNERMOST);
cvar == br.assert_bound_var()
}
_ => false,

View file

@ -952,7 +952,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Can refer to a type which may drop.
// FIXME(eddyb) check this against a ParamEnv.
ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
ty::Placeholder(..) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),

View file

@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
match parent_ty.sty {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error |
ty::Bound(..) | ty::Foreign(..) => {
ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
}
ty::Array(ty, len) => {
push_const(stack, len);

View file

@ -259,6 +259,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
ty::Never |
ty::Param(_) |
ty::Bound(..) |
ty::Placeholder(..) |
ty::Foreign(..) => {
// WfScalar, WfParameter, etc
}

View file

@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt};
use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
use ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
use util::nodemap::FxHashSet;
@ -792,7 +792,7 @@ define_print! {
}
ty::ReLateBound(_, br) |
ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
write!(f, "{}", br)
}
ty::ReScope(scope) if cx.identify_regions => {
@ -1110,13 +1110,13 @@ define_print! {
Infer(infer_ty) => write!(f, "{}", infer_ty),
Error => write!(f, "[type error]"),
Param(ref param_ty) => write!(f, "{}", param_ty),
Bound(bound_ty) => {
Bound(debruijn, bound_ty) => {
match bound_ty.kind {
ty::BoundTyKind::Anon => {
if bound_ty.index == ty::INNERMOST {
if debruijn == ty::INNERMOST {
write!(f, "^{}", bound_ty.var.index())
} else {
write!(f, "^{}_{}", bound_ty.index.index(), bound_ty.var.index())
write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index())
}
}
@ -1144,6 +1144,9 @@ define_print! {
data.print(f, cx)?;
write!(f, ")")
}
Placeholder(placeholder) => {
write!(f, "Placeholder({:?})", placeholder)
}
Opaque(def_id, substs) => {
if cx.is_verbose {
return write!(f, "Opaque({:?}, {:?})", def_id, substs);

View file

@ -172,6 +172,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
}
ty::Error |
ty::Infer(_) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::Projection(..) |
ty::Bound(..) |

View file

@ -727,6 +727,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::Closure(..) |
ty::Generator(..) |
ty::GeneratorWitness(..) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::Projection(..) |
ty::Opaque(..) |

View file

@ -2193,7 +2193,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
match ty.sty {
ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
| ty::TyKind::Ref(
ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }),
ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
_,
_,
) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()),
@ -2207,7 +2207,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
match ty.sty {
ty::TyKind::Ref(region, _, _) => match region {
ty::RegionKind::ReLateBound(_, br)
| ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => {
| ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
with_highlight_region_for_bound_region(*br, counter, || region.to_string())
}
_ => region.to_string(),

View file

@ -1230,7 +1230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
mir: &Mir<'tcx>,
_mir_def_id: DefId,
longer_fr: RegionVid,
placeholder: ty::Placeholder,
placeholder: ty::PlaceholderRegion,
) {
debug!(
"check_bound_universal_region(fr={:?}, placeholder={:?})",

View file

@ -150,7 +150,7 @@ crate enum RegionElement {
/// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
/// type).
PlaceholderRegion(ty::Placeholder),
PlaceholderRegion(ty::PlaceholderRegion),
}
/// When we initially compute liveness, we use a bit matrix storing
@ -219,17 +219,17 @@ impl<N: Idx> LivenessValues<N> {
}
}
/// Maps from `ty::Placeholder` values that are used in the rest of
/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
/// rustc to the internal `PlaceholderIndex` values that are used in
/// NLL.
#[derive(Default)]
crate struct PlaceholderIndices {
to_index: FxHashMap<ty::Placeholder, PlaceholderIndex>,
from_index: IndexVec<PlaceholderIndex, ty::Placeholder>,
to_index: FxHashMap<ty::PlaceholderRegion, PlaceholderIndex>,
from_index: IndexVec<PlaceholderIndex, ty::PlaceholderRegion>,
}
impl PlaceholderIndices {
crate fn insert(&mut self, placeholder: ty::Placeholder) -> PlaceholderIndex {
crate fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
let PlaceholderIndices {
to_index,
from_index,
@ -239,11 +239,11 @@ impl PlaceholderIndices {
.or_insert_with(|| from_index.push(placeholder))
}
crate fn lookup_index(&self, placeholder: ty::Placeholder) -> PlaceholderIndex {
crate fn lookup_index(&self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
self.to_index[&placeholder]
}
crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::Placeholder {
crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::PlaceholderRegion {
self.from_index[placeholder]
}
@ -375,7 +375,7 @@ impl<N: Idx> RegionValues<N> {
crate fn placeholders_contained_in<'a>(
&'a self,
r: N,
) -> impl Iterator<Item = ty::Placeholder> + 'a {
) -> impl Iterator<Item = ty::PlaceholderRegion> + 'a {
self.placeholders
.row(r)
.into_iter()
@ -432,7 +432,7 @@ impl ToElementIndex for RegionVid {
}
}
impl ToElementIndex for ty::Placeholder {
impl ToElementIndex for ty::PlaceholderRegion {
fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
let index = values.placeholder_indices.lookup_index(self);
values.placeholders.insert(row, index)

View file

@ -777,7 +777,7 @@ impl MirTypeckRegionConstraints<'tcx> {
fn placeholder_region(
&mut self,
infcx: &InferCtxt<'_, '_, 'tcx>,
placeholder: ty::Placeholder,
placeholder: ty::PlaceholderRegion,
) -> ty::Region<'tcx> {
let placeholder_index = self.placeholder_indices.insert(placeholder);
match self.placeholder_index_to_region.get(placeholder_index) {

View file

@ -84,7 +84,10 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
}
}
fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> {
fn next_placeholder_region(
&mut self,
placeholder: ty::PlaceholderRegion
) -> ty::Region<'tcx> {
if let Some(borrowck_context) = &mut self.borrowck_context {
borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
} else {

View file

@ -378,6 +378,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
ty::Error |
ty::Bound(..) |
ty::Infer(_) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::Projection(..) |
ty::Param(_) |

View file

@ -11,7 +11,7 @@
mod program_clauses;
use chalk_engine::fallible::Fallible as ChalkEngineFallible;
use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
use chalk_engine::{context, hh::HhGoal, DelayedLiteral, Literal, ExClause};
use rustc::infer::canonical::{
Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
};
@ -28,7 +28,7 @@ use rustc::traits::{
InEnvironment,
};
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::subst::Kind;
use rustc::ty::subst::{Kind, UnpackedKind};
use rustc::ty::{self, TyCtxt};
use std::fmt::{self, Debug};
@ -44,7 +44,7 @@ crate struct ChalkArenas<'gcx> {
#[derive(Copy, Clone)]
crate struct ChalkContext<'cx, 'gcx: 'cx> {
_arenas: ChalkArenas<'gcx>,
_tcx: TyCtxt<'cx, 'gcx, 'gcx>,
tcx: TyCtxt<'cx, 'gcx, 'gcx>,
}
#[derive(Copy, Clone)]
@ -68,7 +68,7 @@ BraceStructTypeFoldableImpl! {
}
impl context::Context for ChalkArenas<'tcx> {
type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>;
type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
@ -147,19 +147,29 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
/// - the environment and goal found by substitution `S` into `arg`
fn instantiate_ucanonical_goal<R>(
&self,
_arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
_op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
) -> R {
unimplemented!()
self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| {
let chalk_infcx = &mut ChalkInferenceContext {
infcx,
};
op.with(chalk_infcx, subst, arg.environment, arg.goal)
})
}
fn instantiate_ex_clause<R>(
&self,
_num_universes: usize,
_canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
_op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
arg: &Canonical<'gcx, ChalkExClause<'gcx>>,
op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
) -> R {
unimplemented!()
self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| {
let chalk_infcx = &mut ChalkInferenceContext {
infcx,
};
op.with(chalk_infcx,arg)
})
}
/// True if this solution has no region constraints.
@ -186,14 +196,33 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
}
fn is_trivial_substitution(
_u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
_canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
) -> bool {
unimplemented!()
let subst = &canonical_subst.value.subst;
assert_eq!(u_canon.variables.len(), subst.var_values.len());
subst.var_values
.iter_enumerated()
.all(|(cvar, kind)| match kind.unpack() {
UnpackedKind::Lifetime(r) => match r {
&ty::ReLateBound(debruijn, br) => {
debug_assert_eq!(debruijn, ty::INNERMOST);
cvar == br.assert_bound_var()
}
_ => false,
},
UnpackedKind::Type(ty) => match ty.sty {
ty::Bound(debruijn, bound_ty) => {
debug_assert_eq!(debruijn, ty::INNERMOST);
cvar == bound_ty.var
}
_ => false,
},
})
}
fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
0 // FIXME
fn num_universes(canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
canon.max_universe.index() + 1
}
/// Convert a goal G *from* the canonical universes *into* our
@ -214,39 +243,6 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
}
}
//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
// for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
//{
// fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
// self
// }
//
// fn is_trivial_substitution(
// &self,
// canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
// ) -> bool {
// let subst = &canonical_subst.value.subst;
// assert_eq!(self.canonical.variables.len(), subst.var_values.len());
// subst
// .var_values
// .iter_enumerated()
// .all(|(cvar, kind)| match kind.unpack() {
// Kind::Lifetime(r) => match r {
// ty::ReCanonical(cvar1) => cvar == cvar1,
// _ => false,
// },
// Kind::Type(ty) => match ty.sty {
// ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
// _ => false,
// },
// })
// }
//
// fn num_universes(&self) -> usize {
// 0 // FIXME
// }
//}
impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
for ChalkInferenceContext<'cx, 'gcx, 'tcx>
{
@ -260,7 +256,10 @@ impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
match *goal {
GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
GoalKind::Implies(hypotheses, goal) => HhGoal::Implies(
hypotheses.iter().cloned().collect(),
goal
),
GoalKind::And(left, right) => HhGoal::And(left, right),
GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
@ -338,9 +337,9 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
fn instantiate_binders_universally(
&mut self,
_arg: &ty::Binder<Goal<'tcx>>,
arg: &ty::Binder<Goal<'tcx>>,
) -> Goal<'tcx> {
panic!("FIXME -- universal instantiation needs sgrif's branch")
self.infcx.replace_bound_vars_with_placeholders(arg).0
}
fn instantiate_binders_existentially(
@ -491,3 +490,68 @@ BraceStructLiftImpl! {
subst, constraints
}
}
trait Upcast<'tcx, 'gcx: 'tcx>: 'gcx {
type Upcasted: 'tcx;
fn upcast(&self) -> Self::Upcasted;
}
impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for DelayedLiteral<ChalkArenas<'gcx>> {
type Upcasted = DelayedLiteral<ChalkArenas<'tcx>>;
fn upcast(&self) -> Self::Upcasted {
match self {
&DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()),
&DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index),
DelayedLiteral::Positive(index, subst) => DelayedLiteral::Positive(
*index,
subst.clone()
),
}
}
}
impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for Literal<ChalkArenas<'gcx>> {
type Upcasted = Literal<ChalkArenas<'tcx>>;
fn upcast(&self) -> Self::Upcasted {
match self {
&Literal::Negative(goal) => Literal::Negative(goal),
&Literal::Positive(goal) => Literal::Positive(goal),
}
}
}
impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for ExClause<ChalkArenas<'gcx>> {
type Upcasted = ExClause<ChalkArenas<'tcx>>;
fn upcast(&self) -> Self::Upcasted {
ExClause {
subst: self.subst.clone(),
delayed_literals: self.delayed_literals
.iter()
.map(|l| l.upcast())
.collect(),
constraints: self.constraints.clone(),
subgoals: self.subgoals
.iter()
.map(|g| g.upcast())
.collect(),
}
}
}
impl<'tcx, 'gcx: 'tcx, T> Upcast<'tcx, 'gcx> for Canonical<'gcx, T>
where T: Upcast<'tcx, 'gcx>
{
type Upcasted = Canonical<'tcx, T::Upcasted>;
fn upcast(&self) -> Self::Upcasted {
Canonical {
max_universe: self.max_universe,
value: self.value.upcast(),
variables: self.variables,
}
}
}

View file

@ -59,7 +59,8 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
let ty = ty::Bound(
ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
@ -88,9 +89,9 @@ fn program_clauses_for_fn_ptr<'tcx>(
) -> Clauses<'tcx> {
let inputs_and_output = tcx.mk_type_list(
(0..arity_and_output).into_iter()
.map(|i| ty::BoundVar::from(i))
// DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
.map(|i| ty::BoundTy::new(ty::DebruijnIndex::from(1usize), ty::BoundVar::from(i)))
.map(|t| tcx.mk_ty(ty::Bound(t)))
.map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into())))
);
let fn_sig = ty::Binder::bind(ty::FnSig {
@ -115,7 +116,8 @@ fn program_clauses_for_fn_ptr<'tcx>(
fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
let ty = ty::Bound(
ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
@ -151,7 +153,8 @@ fn program_clauses_for_array<'tcx>(
length: &'tcx ty::Const<'tcx>
) -> Clauses<'tcx> {
let ty = ty::Bound(
ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
ty::INNERMOST,
ty::BoundVar::from_u32(0).into()
);
let ty = tcx.mk_ty(ty);
@ -188,8 +191,8 @@ fn program_clauses_for_tuple<'tcx>(
) -> Clauses<'tcx> {
let type_list = tcx.mk_type_list(
(0..arity).into_iter()
.map(|i| ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from(i)))
.map(|t| tcx.mk_ty(ty::Bound(t)))
.map(|i| ty::BoundVar::from(i))
.map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
);
let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
@ -233,7 +236,7 @@ fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx>
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
);
let ty = tcx.mk_ty(
ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
);
let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
@ -418,6 +421,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
}
ty::GeneratorWitness(..) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::Infer(..) |
ty::Bound(..) |

View file

@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
ty::Bound(..) | ty::Infer(..) | ty::Error => {
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => {
// By the time this code runs, all type variables ought to
// be fully resolved.
Err(NoSolution)

View file

@ -55,7 +55,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
);
let ty = self.tcx.mk_ty(
ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
);
let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
@ -114,6 +114,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
ty::Tuple(..) |
ty::Never |
ty::Infer(..) |
ty::Placeholder(..) |
ty::Bound(..) => (),
ty::GeneratorWitness(..) |

View file

@ -515,7 +515,8 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
.unwrap_or(0);
// Add a new type param after the existing ones (`U` in the comment above).
let ty_var = ty::Bound(
ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(offset + 1))
ty::INNERMOST,
ty::BoundVar::from_u32(offset + 1).into()
);
// `ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U)`

View file

@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
ty::Param(ref p) => Some(PointerKind::OfParam(p)),
// Insufficient type information.
ty::Bound(..) | ty::Infer(_) => None,
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |

View file

@ -1494,7 +1494,7 @@ impl<'tcx> Candidate<'tcx> {
// `WhereClausePick`.
assert!(
!trait_ref.skip_binder().substs.needs_infer()
&& !trait_ref.skip_binder().substs.has_skol()
&& !trait_ref.skip_binder().substs.has_placeholders()
);
WhereClausePick(trait_ref.clone())

View file

@ -115,7 +115,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
assert!(!ty.needs_infer() && !ty.has_skol());
assert!(!ty.needs_infer() && !ty.has_placeholders());
self.tables.node_types_mut().insert(hir_id, ty);
}
@ -580,7 +580,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
let substs = self.resolve(&substs, &span);
debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
assert!(!substs.needs_infer() && !substs.has_skol());
assert!(!substs.needs_infer() && !substs.has_placeholders());
self.tables.node_substs_mut().insert(hir_id, substs);
}

View file

@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// types, where we use Error as the Self type
}
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
ty::GeneratorWitness(..) |
ty::Bound(..) |

View file

@ -2744,6 +2744,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
ty::Bound(..) => panic!("Bound"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
ty::Infer(..) => panic!("Infer"),

View file

@ -16,6 +16,7 @@
//
// dont-check-compiler-stdout
// dont-check-compiler-stderr
// compile-flags: --error-format human
// rustc-env:RUST_LOG=debug

View file

@ -4,7 +4,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
LL | let x = foo::<u32>; //~ ERROR [u32]
| ^^^^^^^^^^
error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
--> $DIR/dump-fn-method.rs:42:13
|
LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
@ -16,7 +16,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
error: user substs: Canonical { max_universe: U1, variables: [CanonicalVarInfo { kind: Ty(General(U1)) }, CanonicalVarInfo { kind: Ty(General(U1)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
--> $DIR/dump-fn-method.rs:54:5
|
LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]