Auto merge of #55330 - scalexm:bound-ty, r=nikomatsakis
Add support for bound types This PR may have some slight performance impacts, I don't know how hot is the code I touched. Also, this breaks clippy and miri. r? @nikomatsakis
This commit is contained in:
commit
2ad8c7b350
72 changed files with 557 additions and 392 deletions
|
@ -100,9 +100,6 @@ for ty::RegionKind {
|
|||
ty::ReEmpty => {
|
||||
// No variant fields to hash for these ...
|
||||
}
|
||||
ty::ReCanonical(c) => {
|
||||
c.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::ReLateBound(db, ty::BrAnon(i)) => {
|
||||
db.hash_stable(hcx, hasher);
|
||||
i.hash_stable(hcx, hasher);
|
||||
|
@ -147,7 +144,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundTyIndex {
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'gcx>,
|
||||
|
@ -852,6 +849,9 @@ for ty::TyKind<'gcx>
|
|||
Param(param_ty) => {
|
||||
param_ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
Bound(bound_ty) => {
|
||||
bound_ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
Foreign(def_id) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
@ -869,7 +869,6 @@ impl_stable_hash_for!(enum ty::InferTy {
|
|||
FreshTy(a),
|
||||
FreshIntTy(a),
|
||||
FreshFloatTy(a),
|
||||
BoundTy(a),
|
||||
});
|
||||
|
||||
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
|
||||
|
|
|
@ -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, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags};
|
||||
use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
@ -277,9 +277,11 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
|||
query_state: &'cx mut OriginalQueryValues<'tcx>,
|
||||
// Note that indices is only used once `var_values` is big enough to be
|
||||
// heap-allocated.
|
||||
indices: FxHashMap<Kind<'tcx>, BoundTyIndex>,
|
||||
indices: FxHashMap<Kind<'tcx>, BoundVar>,
|
||||
canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
|
||||
needs_canonical_flags: TypeFlags,
|
||||
|
||||
binder_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> {
|
||||
|
@ -287,11 +289,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
|
|||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
self.binder_index.shift_in(1);
|
||||
let t = t.super_fold_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReLateBound(..) => {
|
||||
// leave bound regions alone
|
||||
r
|
||||
ty::ReLateBound(index, ..) => {
|
||||
if index >= self.binder_index {
|
||||
bug!("escaping late bound region during canonicalization")
|
||||
} else {
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
ty::ReVar(vid) => {
|
||||
|
@ -317,8 +331,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
|
|||
| ty::ReErased => self.canonicalize_region_mode
|
||||
.canonicalize_free_region(self, r),
|
||||
|
||||
ty::ReClosureBound(..) | ty::ReCanonical(_) => {
|
||||
bug!("canonical region encountered during canonicalization")
|
||||
ty::ReClosureBound(..) => {
|
||||
bug!("closure bound region encountered during canonicalization")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,8 +351,12 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
|
|||
bug!("encountered a fresh type during canonicalization")
|
||||
}
|
||||
|
||||
ty::Infer(ty::BoundTy(_)) => {
|
||||
bug!("encountered a canonical type during canonicalization")
|
||||
ty::Bound(bound_ty) => {
|
||||
if bound_ty.index >= self.binder_index {
|
||||
bug!("escaping bound type during canonicalization")
|
||||
} else {
|
||||
t
|
||||
}
|
||||
}
|
||||
|
||||
ty::Closure(..)
|
||||
|
@ -389,12 +407,6 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'gcx>,
|
||||
{
|
||||
debug_assert!(
|
||||
!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS),
|
||||
"canonicalizing a canonical value: {:?}",
|
||||
value,
|
||||
);
|
||||
|
||||
let needs_canonical_flags = if canonicalize_region_mode.any() {
|
||||
TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
|
||||
} else {
|
||||
|
@ -422,6 +434,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
variables: SmallVec::new(),
|
||||
query_state,
|
||||
indices: FxHashMap::default(),
|
||||
binder_index: ty::INNERMOST,
|
||||
};
|
||||
let out_value = value.fold_with(&mut canonicalizer);
|
||||
|
||||
|
@ -455,7 +468,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
/// or returns an existing variable if `kind` has already been
|
||||
/// seen. `kind` is expected to be an unbound variable (or
|
||||
/// potentially a free region).
|
||||
fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy {
|
||||
fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundVar {
|
||||
let Canonicalizer {
|
||||
variables,
|
||||
query_state,
|
||||
|
@ -475,7 +488,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
// direct linear search of `var_values`.
|
||||
if let Some(idx) = var_values.iter().position(|&k| k == kind) {
|
||||
// `kind` is already present in `var_values`.
|
||||
BoundTyIndex::new(idx)
|
||||
BoundVar::new(idx)
|
||||
} else {
|
||||
// `kind` isn't present in `var_values`. Append it. Likewise
|
||||
// for `info` and `variables`.
|
||||
|
@ -490,11 +503,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
*indices = var_values
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &kind)| (kind, BoundTyIndex::new(i)))
|
||||
.map(|(i, &kind)| (kind, BoundVar::new(i)))
|
||||
.collect();
|
||||
}
|
||||
// The cv is the index of the appended element.
|
||||
BoundTyIndex::new(var_values.len() - 1)
|
||||
BoundVar::new(var_values.len() - 1)
|
||||
}
|
||||
} else {
|
||||
// `var_values` is large. Do a hashmap search via `indices`.
|
||||
|
@ -502,14 +515,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
variables.push(info);
|
||||
var_values.push(kind);
|
||||
assert_eq!(variables.len(), var_values.len());
|
||||
BoundTyIndex::new(variables.len() - 1)
|
||||
BoundVar::new(variables.len() - 1)
|
||||
})
|
||||
};
|
||||
|
||||
BoundTy {
|
||||
level: ty::INNERMOST,
|
||||
var,
|
||||
}
|
||||
var
|
||||
}
|
||||
|
||||
/// Shorthand helper that creates a canonical region variable for
|
||||
|
@ -552,9 +562,12 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
info: CanonicalVarInfo,
|
||||
r: ty::Region<'tcx>,
|
||||
) -> ty::Region<'tcx> {
|
||||
let b = self.canonical_var(info, r.into());
|
||||
debug_assert_eq!(ty::INNERMOST, b.level);
|
||||
self.tcx().mk_region(ty::ReCanonical(b.var))
|
||||
let var = self.canonical_var(info, r.into());
|
||||
let region = ty::ReLateBound(
|
||||
self.binder_index,
|
||||
ty::BoundRegion::BrAnon(var.as_u32())
|
||||
);
|
||||
self.tcx().mk_region(region)
|
||||
}
|
||||
|
||||
/// Given a type variable `ty_var` of the given kind, first check
|
||||
|
@ -570,9 +583,8 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
|
|||
let info = CanonicalVarInfo {
|
||||
kind: CanonicalVarKind::Ty(ty_kind),
|
||||
};
|
||||
let b = self.canonical_var(info, ty_var.into());
|
||||
debug_assert_eq!(ty::INNERMOST, b.level);
|
||||
self.tcx().mk_infer(ty::InferTy::BoundTy(b))
|
||||
let var = self.canonical_var(info, ty_var.into());
|
||||
self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
//! - a map M (of type `CanonicalVarValues`) from those canonical
|
||||
//! variables back to the original.
|
||||
//!
|
||||
//! We can then do queries using T2. These will give back constriants
|
||||
//! We can then do queries using T2. These will give back constraints
|
||||
//! on the canonical variables which can be translated, using the map
|
||||
//! M, into constraints in our source context. This process of
|
||||
//! translating the results back is done by the
|
||||
|
@ -40,7 +40,7 @@ use std::ops::Index;
|
|||
use syntax::source_map::Span;
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::subst::Kind;
|
||||
use ty::{self, BoundTyIndex, Lift, List, Region, TyCtxt};
|
||||
use ty::{self, BoundVar, Lift, List, Region, TyCtxt};
|
||||
|
||||
mod canonicalizer;
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
|
|||
/// canonicalized query response.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub struct CanonicalVarValues<'tcx> {
|
||||
pub var_values: IndexVec<BoundTyIndex, Kind<'tcx>>,
|
||||
pub var_values: IndexVec<BoundVar, Kind<'tcx>>,
|
||||
}
|
||||
|
||||
/// When we canonicalize a value to form a query, we wind up replacing
|
||||
|
@ -337,7 +337,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
variables: &List<CanonicalVarInfo>,
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> CanonicalVarValues<'tcx> {
|
||||
let var_values: IndexVec<BoundTyIndex, Kind<'tcx>> = variables
|
||||
let var_values: IndexVec<BoundVar, Kind<'tcx>> = variables
|
||||
.iter()
|
||||
.map(|info| self.instantiate_canonical_var(span, *info, &universe_map))
|
||||
.collect();
|
||||
|
@ -456,10 +456,10 @@ BraceStructLiftImpl! {
|
|||
} where R: Lift<'tcx>
|
||||
}
|
||||
|
||||
impl<'tcx> Index<BoundTyIndex> for CanonicalVarValues<'tcx> {
|
||||
impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
|
||||
type Output = Kind<'tcx>;
|
||||
|
||||
fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> {
|
||||
fn index(&self, value: BoundVar) -> &Kind<'tcx> {
|
||||
&self.var_values[value]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ use traits::{FulfillmentContext, TraitEngine};
|
|||
use traits::{Obligation, ObligationCause, PredicateObligation};
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::subst::{Kind, UnpackedKind};
|
||||
use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt};
|
||||
use ty::{self, BoundVar, Lift, Ty, TyCtxt};
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
|
||||
/// The "main method" for a canonicalized trait query. Given the
|
||||
|
@ -273,7 +273,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
for (index, original_value) in original_values.var_values.iter().enumerate() {
|
||||
// ...with the value `v_r` of that variable from the query.
|
||||
let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
|
||||
&v.var_values[BoundTyIndex::new(index)]
|
||||
&v.var_values[BoundVar::new(index)]
|
||||
});
|
||||
match (original_value.unpack(), result_value.unpack()) {
|
||||
(UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
|
||||
|
@ -308,11 +308,14 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
// ...also include the other query region constraints from the query.
|
||||
output_query_region_constraints.extend(
|
||||
query_response.value.region_constraints.iter().filter_map(|r_c| {
|
||||
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
|
||||
let k1 = substitute_value(self.tcx, &result_subst, &k1);
|
||||
let r2 = substitute_value(self.tcx, &result_subst, &r2);
|
||||
let r_c = substitute_value(self.tcx, &result_subst, r_c);
|
||||
|
||||
// Screen out `'a: 'a` cases -- we skip the binder here but
|
||||
// only care the inner values to one another, so they are still at
|
||||
// consistent binding levels.
|
||||
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
|
||||
if k1 != r2.into() {
|
||||
Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)))
|
||||
Some(r_c)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -423,7 +426,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
// is directly equal to one of the canonical variables in the
|
||||
// result, then we can type the corresponding value from the
|
||||
// input. See the example above.
|
||||
let mut opt_values: IndexVec<BoundTyIndex, Option<Kind<'tcx>>> =
|
||||
let mut opt_values: IndexVec<BoundVar, Option<Kind<'tcx>>> =
|
||||
IndexVec::from_elem_n(None, query_response.variables.len());
|
||||
|
||||
// In terms of our example above, we are iterating over pairs like:
|
||||
|
@ -432,16 +435,22 @@ 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::Infer(ty::InferTy::BoundTy(b)) = result_value.sty {
|
||||
// in which case we would set `canonical_vars[0]` to `Some(?U)`.
|
||||
if let ty::Bound(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);
|
||||
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::ReCanonical(index) = result_value {
|
||||
// in which case we would set `canonical_vars[0]` to `Some('static)`.
|
||||
opt_values[index] = Some(*original_value);
|
||||
if let &ty::RegionKind::ReLateBound(index, 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);
|
||||
opt_values[br.assert_bound_var()] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -457,7 +466,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
.enumerate()
|
||||
.map(|(index, info)| {
|
||||
if info.is_existential() {
|
||||
match opt_values[BoundTyIndex::new(index)] {
|
||||
match opt_values[BoundVar::new(index)] {
|
||||
Some(k) => k,
|
||||
None => self.instantiate_canonical_var(cause.span, *info, |u| {
|
||||
universe_map[u.as_usize()]
|
||||
|
@ -496,7 +505,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
// canonical variable; this is taken from
|
||||
// `query_response.var_values` after applying the substitution
|
||||
// `result_subst`.
|
||||
let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> {
|
||||
let substituted_query_response = |index: BoundVar| -> Kind<'tcx> {
|
||||
query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
|
||||
};
|
||||
|
||||
|
@ -523,22 +532,23 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
unsubstituted_region_constraints
|
||||
.iter()
|
||||
.map(move |constraint| {
|
||||
let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
|
||||
let k1 = substitute_value(self.tcx, result_subst, k1);
|
||||
let r2 = substitute_value(self.tcx, result_subst, r2);
|
||||
let constraint = substitute_value(self.tcx, result_subst, constraint);
|
||||
let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
|
||||
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
match k1.unpack() {
|
||||
UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
|
||||
ty::Binder::dummy(
|
||||
ty::Binder::bind(
|
||||
ty::OutlivesPredicate(r1, r2)
|
||||
)),
|
||||
)
|
||||
),
|
||||
UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(
|
||||
t1, r2
|
||||
)))
|
||||
ty::Binder::bind(
|
||||
ty::OutlivesPredicate(t1, r2)
|
||||
)
|
||||
),
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -552,12 +562,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
variables1: &OriginalQueryValues<'tcx>,
|
||||
variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>,
|
||||
variables2: impl Fn(BoundVar) -> Kind<'tcx>,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
self.commit_if_ok(|_| {
|
||||
let mut obligations = vec![];
|
||||
for (index, value1) in variables1.var_values.iter().enumerate() {
|
||||
let value2 = variables2(BoundTyIndex::new(index));
|
||||
let value2 = variables2(BoundVar::new(index));
|
||||
|
||||
match (value1.unpack(), value2.unpack()) {
|
||||
(UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
|
||||
|
@ -620,11 +630,11 @@ pub fn make_query_outlives<'tcx>(
|
|||
}
|
||||
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
|
||||
})
|
||||
.map(ty::Binder::dummy) // no bound regions in the code above
|
||||
.map(ty::Binder::dummy) // no bound vars in the code above
|
||||
.chain(
|
||||
outlives_obligations
|
||||
.map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
|
||||
.map(ty::Binder::dummy), // no bound regions in the code above
|
||||
.map(ty::Binder::dummy) // no bound vars in the code above
|
||||
)
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
|
||||
|
||||
use infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use ty::fold::{TypeFoldable, TypeFolder};
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::subst::UnpackedKind;
|
||||
use ty::{self, Ty, TyCtxt, TypeFlags};
|
||||
use ty::{self, TyCtxt};
|
||||
|
||||
impl<'tcx, V> Canonical<'tcx, V> {
|
||||
/// Instantiate the wrapped value, replacing each canonical value
|
||||
|
@ -64,51 +64,22 @@ where
|
|||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
if var_values.var_values.is_empty() {
|
||||
debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS));
|
||||
value.clone()
|
||||
} else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
|
||||
value.clone()
|
||||
} else {
|
||||
value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values })
|
||||
}
|
||||
}
|
||||
|
||||
struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
var_values: &'cx CanonicalVarValues<'tcx>,
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match t.sty {
|
||||
ty::Infer(ty::InferTy::BoundTy(b)) => {
|
||||
debug_assert_eq!(ty::INNERMOST, b.level);
|
||||
match self.var_values.var_values[b.var].unpack() {
|
||||
UnpackedKind::Type(ty) => ty,
|
||||
r => bug!("{:?} is a type but value is {:?}", b, r),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
|
||||
t
|
||||
} else {
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match r {
|
||||
ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() {
|
||||
let fld_r = |br: ty::BoundRegion| {
|
||||
match var_values.var_values[br.assert_bound_var()].unpack() {
|
||||
UnpackedKind::Lifetime(l) => l,
|
||||
r => bug!("{:?} is a region but value is {:?}", c, r),
|
||||
},
|
||||
_ => r.super_fold_with(self),
|
||||
}
|
||||
r => bug!("{:?} is a region but value is {:?}", br, r),
|
||||
}
|
||||
};
|
||||
|
||||
let fld_t = |bound_ty: ty::BoundTy| {
|
||||
match var_values.var_values[bound_ty.var].unpack() {
|
||||
UnpackedKind::Type(ty) => ty,
|
||||
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
|
||||
}
|
||||
};
|
||||
|
||||
tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -485,7 +485,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
|
|||
}
|
||||
}
|
||||
|
||||
ty::ReCanonical(..) |
|
||||
ty::ReClosureBound(..) => {
|
||||
span_bug!(
|
||||
self.span,
|
||||
|
|
|
@ -152,7 +152,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
// We shouldn't encounter an error message with ReClosureBound.
|
||||
ty::ReCanonical(..) | ty::ReClosureBound(..) => {
|
||||
ty::ReClosureBound(..) => {
|
||||
bug!("encountered unexpected ReClosureBound: {:?}", region,);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -114,7 +114,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
|||
self.tcx().types.re_erased
|
||||
}
|
||||
|
||||
ty::ReCanonical(..) |
|
||||
ty::ReClosureBound(..) => {
|
||||
bug!(
|
||||
"encountered unexpected region: {:?}",
|
||||
|
@ -171,8 +170,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
|||
t
|
||||
}
|
||||
|
||||
ty::Infer(ty::BoundTy(..)) =>
|
||||
bug!("encountered canonical ty during freshening"),
|
||||
ty::Bound(..) =>
|
||||
bug!("encountered bound ty during freshening"),
|
||||
|
||||
ty::Generator(..) |
|
||||
ty::Bool |
|
||||
|
|
|
@ -260,9 +260,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
|
|||
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
match (a, b) {
|
||||
(&ty::ReCanonical(..), _)
|
||||
| (_, &ty::ReCanonical(..))
|
||||
| (&ty::ReClosureBound(..), _)
|
||||
(&ty::ReClosureBound(..), _)
|
||||
| (_, &ty::ReClosureBound(..))
|
||||
| (&ReLateBound(..), _)
|
||||
| (_, &ReLateBound(..))
|
||||
|
|
|
@ -305,7 +305,7 @@ where
|
|||
ty, region, origin
|
||||
);
|
||||
|
||||
assert!(!ty.has_escaping_regions());
|
||||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
let components = self.tcx.outlives_components(ty);
|
||||
self.components_must_outlive(origin, components, region);
|
||||
|
|
|
@ -323,7 +323,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
|
|||
predicates
|
||||
.into_iter()
|
||||
.filter_map(|p| p.as_ref().to_opt_type_outlives())
|
||||
.filter_map(|p| p.no_late_bound_regions())
|
||||
.filter_map(|p| p.no_bound_vars())
|
||||
.filter(move |p| compare_ty(p.0))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -833,10 +833,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
|||
ty::RePlaceholder(placeholder) => placeholder.universe,
|
||||
ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
|
||||
ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
|
||||
ty::ReCanonical(..) => bug!(
|
||||
"region_universe(): encountered canonical region {:?}",
|
||||
region
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||
// Shouldn't have any LBR here, so we can safely put
|
||||
// this under a binder below without fear of accidental
|
||||
// capture.
|
||||
assert!(!a.has_escaping_regions());
|
||||
assert!(!b.has_escaping_regions());
|
||||
assert!(!a.has_escaping_bound_vars());
|
||||
assert!(!b.has_escaping_bound_vars());
|
||||
|
||||
// can't make progress on `A <: B` if both A and B are
|
||||
// type variables, so record an obligation. We also
|
||||
|
|
|
@ -683,8 +683,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
|||
}
|
||||
&ty::Predicate::TypeOutlives(ref binder) => {
|
||||
match (
|
||||
binder.no_late_bound_regions(),
|
||||
binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(),
|
||||
binder.no_bound_vars(),
|
||||
binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
|
||||
) {
|
||||
(None, Some(t_a)) => {
|
||||
select.infcx().register_region_obligation_with_cause(
|
||||
|
|
|
@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
ty::Infer(..) => match in_crate {
|
||||
ty::Bound(..) | ty::Infer(..) => match in_crate {
|
||||
InCrate::Local => false,
|
||||
// The inference variable might be unified with a local
|
||||
// type in that remote crate.
|
||||
|
|
|
@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
ty::Generator(..) => Some(18),
|
||||
ty::Foreign(..) => Some(19),
|
||||
ty::GeneratorWitness(..) => Some(20),
|
||||
ty::Infer(..) | ty::Error => None,
|
||||
ty::Bound(..) | ty::Infer(..) | ty::Error => None,
|
||||
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
debug!("normalize_projection_type(projection_ty={:?})",
|
||||
projection_ty);
|
||||
|
||||
debug_assert!(!projection_ty.has_escaping_regions());
|
||||
debug_assert!(!projection_ty.has_escaping_bound_vars());
|
||||
|
||||
// FIXME(#20304) -- cache
|
||||
|
||||
|
@ -349,15 +349,15 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
|
|||
}
|
||||
|
||||
ty::Predicate::TypeOutlives(ref binder) => {
|
||||
// Check if there are higher-ranked regions.
|
||||
match binder.no_late_bound_regions() {
|
||||
// Check if there are higher-ranked vars.
|
||||
match binder.no_bound_vars() {
|
||||
// If there are, inspect the underlying type further.
|
||||
None => {
|
||||
// Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
|
||||
let binder = binder.map_bound_ref(|pred| pred.0);
|
||||
|
||||
// Check if the type has any bound regions.
|
||||
match binder.no_late_bound_regions() {
|
||||
// Check if the type has any bound vars.
|
||||
match binder.no_bound_vars() {
|
||||
// If so, this obligation is an error (for now). Eventually we should be
|
||||
// able to support additional cases here, like `for<'a> &'a str: 'a`.
|
||||
// NOTE: this is duplicate-implemented between here and fulfillment.
|
||||
|
|
|
@ -352,7 +352,7 @@ impl<'tcx> GoalKind<'tcx> {
|
|||
domain_goal: PolyDomainGoal<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
) -> GoalKind<'tcx> {
|
||||
match domain_goal.no_late_bound_regions() {
|
||||
match domain_goal.no_bound_vars() {
|
||||
Some(p) => p.into_goal(),
|
||||
None => GoalKind::Quantified(
|
||||
QuantifierKind::Universal,
|
||||
|
|
|
@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
|||
|
||||
let ty = ty.super_fold_with(self);
|
||||
match ty.sty {
|
||||
ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
|
||||
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*)
|
||||
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
||||
match self.param_env.reveal {
|
||||
Reveal::UserFacing => ty,
|
||||
|
@ -393,7 +393,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
|||
}
|
||||
}
|
||||
|
||||
ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
|
||||
ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*)
|
||||
|
||||
// (*) This is kind of hacky -- we need to be able to
|
||||
// handle normalization within binders because
|
||||
|
@ -1619,7 +1619,7 @@ impl<'cx, 'gcx, 'tcx> ProjectionCacheKey<'tcx> {
|
|||
let infcx = selcx.infcx();
|
||||
// We don't do cross-snapshot caching of obligations with escaping regions,
|
||||
// so there's no cache key to use
|
||||
predicate.no_late_bound_regions()
|
||||
predicate.no_bound_vars()
|
||||
.map(|predicate| ProjectionCacheKey {
|
||||
// We don't attempt to match up with a specific type-variable state
|
||||
// from a specific call to `opt_normalize_projection_type` - if
|
||||
|
|
|
@ -252,6 +252,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
|
|||
| ty::Param(_)
|
||||
| ty::Opaque(..)
|
||||
| ty::Infer(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Generator(..) => false,
|
||||
|
||||
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
|
|
|
@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
|||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = ty.super_fold_with(self);
|
||||
match ty.sty {
|
||||
ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => {
|
||||
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
|
||||
// (*)
|
||||
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
||||
match self.param_env.reveal {
|
||||
|
@ -138,7 +138,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
|||
}
|
||||
}
|
||||
|
||||
ty::Projection(ref data) if !data.has_escaping_regions() => {
|
||||
ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
|
||||
// (*)
|
||||
// (*) This is kind of hacky -- we need to be able to
|
||||
// handle normalization within binders because
|
||||
|
|
|
@ -164,7 +164,7 @@ pub fn explicit_outlives_bounds<'tcx>(
|
|||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => None,
|
||||
ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map(
|
||||
ty::Predicate::RegionOutlives(ref data) => data.no_bound_vars().map(
|
||||
|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a),
|
||||
),
|
||||
})
|
||||
|
|
|
@ -587,7 +587,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
obligation: &TraitObligation<'tcx>,
|
||||
) -> SelectionResult<'tcx, Selection<'tcx>> {
|
||||
debug!("select({:?})", obligation);
|
||||
debug_assert!(!obligation.predicate.has_escaping_regions());
|
||||
debug_assert!(!obligation.predicate.has_escaping_bound_vars());
|
||||
|
||||
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
|
||||
|
||||
|
@ -690,7 +690,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(ref t) => {
|
||||
debug_assert!(!t.has_escaping_regions());
|
||||
debug_assert!(!t.has_escaping_bound_vars());
|
||||
let obligation = obligation.with(t.clone());
|
||||
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
|
||||
}
|
||||
|
@ -722,9 +722,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
},
|
||||
|
||||
ty::Predicate::TypeOutlives(ref binder) => {
|
||||
assert!(!binder.has_escaping_regions());
|
||||
// Check if the type has higher-ranked regions.
|
||||
if binder.skip_binder().0.has_escaping_regions() {
|
||||
assert!(!binder.has_escaping_bound_vars());
|
||||
// Check if the type has higher-ranked vars.
|
||||
if binder.skip_binder().0.has_escaping_bound_vars() {
|
||||
// If so, this obligation is an error (for now). Eventually we should be
|
||||
// able to support additional cases here, like `for<'a> &'a str: 'a`.
|
||||
|
||||
|
@ -740,7 +740,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
Ok(EvaluatedToErr)
|
||||
}
|
||||
} else {
|
||||
// If the type has no late bound regions, then if we assign all
|
||||
// If the type has no late bound vars, then if we assign all
|
||||
// the inference variables in it to be 'static, then the type
|
||||
// will be 'static itself.
|
||||
//
|
||||
|
@ -1199,7 +1199,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
"candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
|
||||
cache_fresh_trait_pred, stack
|
||||
);
|
||||
debug_assert!(!stack.obligation.predicate.has_escaping_regions());
|
||||
debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
|
||||
|
||||
if let Some(c) =
|
||||
self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
|
||||
|
@ -1801,7 +1801,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
placeholder_map: &infer::PlaceholderMap<'tcx>,
|
||||
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
|
||||
) -> bool {
|
||||
debug_assert!(!skol_trait_ref.has_escaping_regions());
|
||||
debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
|
||||
if self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
|
||||
|
@ -2168,7 +2168,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
// T: Trait
|
||||
// so it seems ok if we (conservatively) fail to accept that `Unsize`
|
||||
// obligation above. Should be possible to extend this in the future.
|
||||
let source = match obligation.self_ty().no_late_bound_regions() {
|
||||
let source = match obligation.self_ty().no_bound_vars() {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
// Don't add any candidates if there are bound regions.
|
||||
|
@ -2445,7 +2445,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
ty::Infer(ty::TyVar(_)) => Ambiguous,
|
||||
|
||||
ty::UnnormalizedProjection(..)
|
||||
| ty::Infer(ty::BoundTy(_))
|
||||
| ty::Bound(_)
|
||||
| ty::Infer(ty::FreshTy(_))
|
||||
| ty::Infer(ty::FreshIntTy(_))
|
||||
| ty::Infer(ty::FreshFloatTy(_)) => {
|
||||
|
@ -2530,7 +2530,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
ty::UnnormalizedProjection(..)
|
||||
| ty::Infer(ty::BoundTy(_))
|
||||
| ty::Bound(_)
|
||||
| ty::Infer(ty::FreshTy(_))
|
||||
| ty::Infer(ty::FreshIntTy(_))
|
||||
| ty::Infer(ty::FreshFloatTy(_)) => {
|
||||
|
@ -2573,7 +2573,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Projection(..)
|
||||
| ty::Infer(ty::BoundTy(_))
|
||||
| ty::Bound(_)
|
||||
| ty::Infer(ty::TyVar(_))
|
||||
| ty::Infer(ty::FreshTy(_))
|
||||
| ty::Infer(ty::FreshIntTy(_))
|
||||
|
@ -3235,7 +3235,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
// assemble_candidates_for_unsizing should ensure there are no late bound
|
||||
// regions here. See the comment there for more details.
|
||||
let source = self.infcx
|
||||
.shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap());
|
||||
.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
|
||||
let target = obligation
|
||||
.predicate
|
||||
.skip_binder()
|
||||
|
|
|
@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
|||
sty_debug_print!(
|
||||
self,
|
||||
Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
|
||||
Generator, GeneratorWitness, Dynamic, Closure, Tuple,
|
||||
Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
|
||||
Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
|
||||
|
||||
println!("Substs interner: #{}", self.interners.substs.borrow().len());
|
||||
|
|
|
@ -212,7 +212,7 @@ 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::Infer(ty::BoundTy(_)) |
|
||||
ty::Bound(_) |
|
||||
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
|
||||
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
|
||||
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
|
||||
|
|
|
@ -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::Infer(_) | ty::Error => None,
|
||||
ty::Bound(..) | ty::Infer(_) | ty::Error => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,15 +115,17 @@ impl FlagComputation {
|
|||
self.add_substs(&substs.substs);
|
||||
}
|
||||
|
||||
&ty::Bound(bound_ty) => {
|
||||
self.add_binder(bound_ty.index);
|
||||
}
|
||||
|
||||
&ty::Infer(infer) => {
|
||||
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
|
||||
self.add_flags(TypeFlags::HAS_TY_INFER);
|
||||
match infer {
|
||||
ty::FreshTy(_) |
|
||||
ty::FreshIntTy(_) |
|
||||
ty::FreshFloatTy(_) |
|
||||
ty::BoundTy(_) => {
|
||||
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
|
||||
ty::FreshFloatTy(_) => {
|
||||
}
|
||||
|
||||
ty::TyVar(_) |
|
||||
|
@ -141,7 +143,7 @@ impl FlagComputation {
|
|||
&ty::Projection(ref data) => {
|
||||
// currently we can't normalize projections that
|
||||
// include bound regions, so track those separately.
|
||||
if !data.has_escaping_regions() {
|
||||
if !data.has_escaping_bound_vars() {
|
||||
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
|
||||
}
|
||||
self.add_flags(TypeFlags::HAS_PROJECTION);
|
||||
|
|
|
@ -67,18 +67,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
|||
/// bound by `binder` or bound by some binder outside of `binder`.
|
||||
/// If `binder` is `ty::INNERMOST`, this indicates whether
|
||||
/// there are any late-bound regions that appear free.
|
||||
fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
|
||||
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
|
||||
}
|
||||
|
||||
/// True if this `self` has any regions that escape `binder` (and
|
||||
/// hence are not bound by it).
|
||||
fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.has_regions_bound_at_or_above(binder.shifted_in(1))
|
||||
fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.has_vars_bound_at_or_above(binder.shifted_in(1))
|
||||
}
|
||||
|
||||
fn has_escaping_regions(&self) -> bool {
|
||||
self.has_regions_bound_at_or_above(ty::INNERMOST)
|
||||
fn has_escaping_bound_vars(&self) -> bool {
|
||||
self.has_vars_bound_at_or_above(ty::INNERMOST)
|
||||
}
|
||||
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
|
@ -416,11 +416,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Late-bound region replacer
|
||||
// Bound vars replacer
|
||||
|
||||
// Replaces the escaping regions in a type.
|
||||
|
||||
struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
/// Replaces the escaping bound vars (late bound regions or bound types) in a type.
|
||||
struct BoundVarReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
/// As with `RegionFolder`, represents the index of a binder *just outside*
|
||||
|
@ -428,7 +427,82 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
current_index: ty::DebruijnIndex,
|
||||
|
||||
fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
|
||||
map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
|
||||
fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a),
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> {
|
||||
fn new<F, G>(
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
fld_r: &'a mut F,
|
||||
fld_t: &'a mut G
|
||||
) -> Self
|
||||
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>
|
||||
{
|
||||
BoundVarReplacer {
|
||||
tcx,
|
||||
current_index: ty::INNERMOST,
|
||||
fld_r,
|
||||
fld_t,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
|
||||
|
||||
fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
|
||||
self.current_index.shift_in(1);
|
||||
let t = t.super_fold_with(self);
|
||||
self.current_index.shift_out(1);
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match t.sty {
|
||||
ty::Bound(bound_ty) => {
|
||||
if bound_ty.index == self.current_index {
|
||||
let fld_t = &mut self.fld_t;
|
||||
let ty = fld_t(bound_ty);
|
||||
ty::fold::shift_vars(
|
||||
self.tcx,
|
||||
&ty,
|
||||
self.current_index.as_u32()
|
||||
)
|
||||
} else {
|
||||
t
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if !t.has_vars_bound_at_or_above(self.current_index) {
|
||||
// Nothing more to substitute.
|
||||
t
|
||||
} else {
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
|
||||
let fld_r = &mut self.fld_r;
|
||||
let region = fld_r(br);
|
||||
if let ty::ReLateBound(debruijn1, br) = *region {
|
||||
// If the callback returns a late-bound region,
|
||||
// that region should always use the INNERMOST
|
||||
// debruijn index. Then we adjust it to the
|
||||
// correct depth.
|
||||
assert_eq!(debruijn1, ty::INNERMOST);
|
||||
self.tcx.mk_region(ty::ReLateBound(debruijn, br))
|
||||
} else {
|
||||
region
|
||||
}
|
||||
}
|
||||
_ => r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
/// same `BoundRegion` will reuse the previous result. A map is
|
||||
/// returned at the end with each bound region and the free region
|
||||
/// that replaced it.
|
||||
pub fn replace_late_bound_regions<T,F>(self,
|
||||
///
|
||||
/// This method only replaces late bound regions and the result may still
|
||||
/// contain escaping bound types.
|
||||
pub fn replace_late_bound_regions<T, F>(
|
||||
self,
|
||||
value: &Binder<T>,
|
||||
mut f: F)
|
||||
-> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
|
||||
where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
T : TypeFoldable<'tcx>,
|
||||
mut fld_r: F
|
||||
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
|
||||
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
T: TypeFoldable<'tcx>
|
||||
{
|
||||
let mut replacer = RegionReplacer::new(self, &mut f);
|
||||
let mut map = BTreeMap::new();
|
||||
let mut real_fldr = |br| {
|
||||
*map.entry(br).or_insert_with(|| fld_r(br))
|
||||
};
|
||||
|
||||
// identity for bound types
|
||||
let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
|
||||
|
||||
let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
|
||||
let result = value.skip_binder().fold_with(&mut replacer);
|
||||
(result, replacer.map)
|
||||
(result, map)
|
||||
}
|
||||
|
||||
/// Replace all escaping bound vars. The `fld_r` closure replaces escaping
|
||||
/// bound regions while the `fld_t` closure replaces escaping bound types.
|
||||
pub fn replace_escaping_bound_vars<T, F, G>(
|
||||
self,
|
||||
value: &T,
|
||||
mut fld_r: F,
|
||||
mut fld_t: G
|
||||
) -> T
|
||||
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
|
||||
T: TypeFoldable<'tcx>
|
||||
{
|
||||
if !value.has_escaping_bound_vars() {
|
||||
value.clone()
|
||||
} else {
|
||||
let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
|
||||
let result = value.fold_with(&mut replacer);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace all types or regions bound by the given `Binder`. The `fld_r`
|
||||
/// closure replaces bound regions while the `fld_t` closure replaces bound
|
||||
/// types.
|
||||
pub fn replace_bound_vars<T, F, G>(
|
||||
self,
|
||||
value: &Binder<T>,
|
||||
fld_r: F,
|
||||
fld_t: G
|
||||
) -> T
|
||||
where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
|
||||
T: TypeFoldable<'tcx>
|
||||
{
|
||||
self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
|
||||
}
|
||||
|
||||
/// Replace any late-bound regions bound in `value` with
|
||||
|
@ -549,21 +672,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
|
||||
fn new<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F)
|
||||
-> RegionReplacer<'a, 'gcx, 'tcx>
|
||||
where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>
|
||||
{
|
||||
RegionReplacer {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Shifter
|
||||
//
|
||||
// Shifts the De Bruijn indices on all escaping bound vars by a
|
||||
// fixed amount. Useful in substitution or when otherwise introducing
|
||||
// a binding level that is not intended to capture the existing bound
|
||||
// vars. See comment on `shift_vars_through_binders` method in
|
||||
// `subst.rs` for more details.
|
||||
|
||||
struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
current_index: ty::DebruijnIndex,
|
||||
amount: u32,
|
||||
}
|
||||
|
||||
impl Shifter<'a, 'gcx, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self {
|
||||
Shifter {
|
||||
tcx,
|
||||
current_index: ty::INNERMOST,
|
||||
fld_r,
|
||||
map: BTreeMap::default()
|
||||
amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
|
||||
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
|
||||
|
||||
fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
|
||||
|
@ -573,64 +708,48 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
|
|||
t
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !t.has_regions_bound_at_or_above(self.current_index) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
|
||||
let fld_r = &mut self.fld_r;
|
||||
let region = *self.map.entry(br).or_insert_with(|| fld_r(br));
|
||||
if let ty::ReLateBound(debruijn1, br) = *region {
|
||||
// If the callback returns a late-bound region,
|
||||
// that region should always use the INNERMOST
|
||||
// debruijn index. Then we adjust it to the
|
||||
// correct depth.
|
||||
assert_eq!(debruijn1, ty::INNERMOST);
|
||||
self.tcx.mk_region(ty::ReLateBound(debruijn, br))
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
if self.amount == 0 || debruijn < self.current_index {
|
||||
r
|
||||
} else {
|
||||
region
|
||||
let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br);
|
||||
self.tcx.mk_region(shifted)
|
||||
}
|
||||
}
|
||||
_ => r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Region shifter
|
||||
//
|
||||
// Shifts the De Bruijn indices on all escaping bound regions by a
|
||||
// fixed amount. Useful in substitution or when otherwise introducing
|
||||
// a binding level that is not intended to capture the existing bound
|
||||
// regions. See comment on `shift_regions_through_binders` method in
|
||||
// `subst.rs` for more details.
|
||||
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
|
||||
} 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))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
|
||||
match region {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
ty::ReLateBound(debruijn.shifted_in(amount), br)
|
||||
}
|
||||
_ => {
|
||||
region
|
||||
_ => ty.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shift_region_ref<'a, 'gcx, 'tcx>(
|
||||
pub fn shift_region<'a, 'gcx, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
amount: u32)
|
||||
-> ty::Region<'tcx>
|
||||
{
|
||||
amount: u32
|
||||
) -> ty::Region<'tcx> {
|
||||
match region {
|
||||
&ty::ReLateBound(debruijn, br) if amount > 0 => {
|
||||
tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
|
||||
ty::ReLateBound(debruijn, br) if amount > 0 => {
|
||||
tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br))
|
||||
}
|
||||
_ => {
|
||||
region
|
||||
|
@ -638,20 +757,19 @@ pub fn shift_region_ref<'a, 'gcx, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
amount: u32,
|
||||
value: &T) -> T
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("shift_regions(value={:?}, amount={})",
|
||||
pub fn shift_vars<'a, 'gcx, 'tcx, T>(
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
value: &T,
|
||||
amount: u32
|
||||
) -> T where T: TypeFoldable<'tcx> {
|
||||
debug!("shift_vars(value={:?}, amount={})",
|
||||
value, amount);
|
||||
|
||||
value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
|
||||
shift_region_ref(tcx, region, amount)
|
||||
}))
|
||||
value.fold_with(&mut Shifter::new(tcx, amount))
|
||||
}
|
||||
|
||||
/// An "escaping region" is a bound region whose binder is not part of `t`.
|
||||
/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
|
||||
/// bound region or a bound type.
|
||||
///
|
||||
/// So, for example, consider a type like the following, which has two binders:
|
||||
///
|
||||
|
@ -663,24 +781,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
|
||||
/// fn type*, that type has an escaping region: `'a`.
|
||||
///
|
||||
/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
|
||||
/// we already use the term "free region". It refers to the regions that we use to represent bound
|
||||
/// regions on a fn definition while we are typechecking its body.
|
||||
/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
|
||||
/// we already use the term "free var". It refers to the regions or types that we use to represent
|
||||
/// bound regions or type params on a fn definition while we are typechecking its body.
|
||||
///
|
||||
/// To clarify, conceptually there is no particular difference between
|
||||
/// an "escaping" region and a "free" region. However, there is a big
|
||||
/// an "escaping" var and a "free" var. However, there is a big
|
||||
/// difference in practice. Basically, when "entering" a binding
|
||||
/// level, one is generally required to do some sort of processing to
|
||||
/// a bound region, such as replacing it with a fresh/placeholder
|
||||
/// region, or making an entry in the environment to represent the
|
||||
/// scope to which it is attached, etc. An escaping region represents
|
||||
/// a bound region for which this processing has not yet been done.
|
||||
struct HasEscapingRegionsVisitor {
|
||||
/// a bound var, such as replacing it with a fresh/placeholder
|
||||
/// var, or making an entry in the environment to represent the
|
||||
/// scope to which it is attached, etc. An escaping var represents
|
||||
/// a bound var for which this processing has not yet been done.
|
||||
struct HasEscapingVarsVisitor {
|
||||
/// Anything bound by `outer_index` or "above" is escaping
|
||||
outer_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
|
@ -693,7 +811,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
|
|||
// `outer_index`, that means that `t` contains some content
|
||||
// bound at `outer_index` or above (because
|
||||
// `outer_exclusive_binder` is always 1 higher than the
|
||||
// content in `t`). Therefore, `t` has some escaping regions.
|
||||
// content in `t`). Therefore, `t` has some escaping vars.
|
||||
t.outer_exclusive_binder > self.outer_index
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
|
|||
impl<'a, 'b, 'tcx> Instance<'tcx> {
|
||||
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
|
||||
-> Instance<'tcx> {
|
||||
assert!(!substs.has_escaping_regions(),
|
||||
assert!(!substs.has_escaping_bound_vars(),
|
||||
"substs of instance {:?} not normalized for codegen: {:?}",
|
||||
def_id, substs);
|
||||
Instance { def: InstanceDef::Item(def_id), substs: substs }
|
||||
|
|
|
@ -519,6 +519,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
|
|||
ty::Param(_) |
|
||||
ty::Opaque(..) |
|
||||
ty::Infer(_) |
|
||||
ty::Bound(..) |
|
||||
ty::Error |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Never |
|
||||
|
|
|
@ -1124,9 +1124,14 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||
}
|
||||
tcx.layout_raw(param_env.and(normalized))?
|
||||
}
|
||||
ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
|
||||
|
||||
ty::Bound(..) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Infer(_) => {
|
||||
bug!("LayoutDetails::compute: unexpected type `{}`", ty)
|
||||
}
|
||||
|
||||
ty::Param(_) | ty::Error => {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
}
|
||||
|
@ -1703,7 +1708,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
ty::Projection(_) | ty::UnnormalizedProjection(..) |
|
||||
ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) |
|
||||
ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
|
||||
bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
|
|||
|
||||
use hir;
|
||||
|
||||
pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
|
||||
pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
|
||||
pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
|
||||
pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
|
||||
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
|
||||
|
@ -463,13 +463,9 @@ bitflags! {
|
|||
// Currently we can't normalize projections w/ bound regions.
|
||||
const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
|
||||
|
||||
// Set if this includes a "canonical" type or region var --
|
||||
// ought to be true only for the results of canonicalization.
|
||||
const HAS_CANONICAL_VARS = 1 << 13;
|
||||
|
||||
/// Does this have any `ReLateBound` regions? Used to check
|
||||
/// if a global bound is safe to evaluate.
|
||||
const HAS_RE_LATE_BOUND = 1 << 14;
|
||||
const HAS_RE_LATE_BOUND = 1 << 13;
|
||||
|
||||
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
|
||||
TypeFlags::HAS_SELF.bits |
|
||||
|
@ -490,7 +486,6 @@ bitflags! {
|
|||
TypeFlags::HAS_TY_CLOSURE.bits |
|
||||
TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
|
||||
TypeFlags::KEEP_IN_LOCAL_TCX.bits |
|
||||
TypeFlags::HAS_CANONICAL_VARS.bits |
|
||||
TypeFlags::HAS_RE_LATE_BOUND.bits;
|
||||
}
|
||||
}
|
||||
|
@ -2378,6 +2373,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
}
|
||||
}
|
||||
|
||||
Bound(..) |
|
||||
Infer(..) => {
|
||||
bug!("unexpected type `{:?}` in sized_constraint_for_ty",
|
||||
ty)
|
||||
|
|
|
@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// we simply fallback to the most restrictive rule, which
|
||||
// requires that `Pi: 'a` for all `i`.
|
||||
ty::Projection(ref data) => {
|
||||
if !data.has_escaping_regions() {
|
||||
if !data.has_escaping_bound_vars() {
|
||||
// best case: no escaping regions, so push the
|
||||
// projection and skip the subtree (thus generating no
|
||||
// constraints for Pi). This defers the choice between
|
||||
|
@ -156,6 +156,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
ty::FnDef(..) | // OutlivesFunction (*)
|
||||
ty::FnPtr(_) | // OutlivesFunction (*)
|
||||
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
|
||||
ty::Bound(..) |
|
||||
ty::Error => {
|
||||
// (*) Bare functions and traits are both binders. In the
|
||||
// RFC, this means we would add the bound regions to the
|
||||
|
|
|
@ -734,9 +734,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
|||
ty::UnnormalizedProjection(data.fold_with(folder))
|
||||
}
|
||||
ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
|
||||
ty::Bool | ty::Char | ty::Str | ty::Int(_) |
|
||||
ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
|
||||
ty::Param(..) | ty::Never | ty::Foreign(..) => return self
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Str |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) |
|
||||
ty::Error |
|
||||
ty::Infer(_) |
|
||||
ty::Param(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Never |
|
||||
ty::Foreign(..) => return self
|
||||
};
|
||||
|
||||
if self.sty == sty {
|
||||
|
@ -771,9 +781,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
|||
data.visit_with(visitor)
|
||||
}
|
||||
ty::Opaque(_, ref substs) => substs.visit_with(visitor),
|
||||
ty::Bool | ty::Char | ty::Str | ty::Int(_) |
|
||||
ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
|
||||
ty::Param(..) | ty::Never | ty::Foreign(..) => false,
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Str |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) |
|
||||
ty::Error |
|
||||
ty::Infer(_) |
|
||||
ty::Bound(..) |
|
||||
ty::Param(..) |
|
||||
ty::Never |
|
||||
ty::Foreign(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,17 @@ impl BoundRegion {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// When canonicalizing, we replace unbound inference variables and free
|
||||
/// regions with anonymous late bound regions. This method asserts that
|
||||
/// we have an anonymous late bound region, which hence may refer to
|
||||
/// a canonical variable.
|
||||
pub fn assert_bound_var(&self) -> BoundVar {
|
||||
match *self {
|
||||
BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
|
||||
_ => bug!("bound region is not anonymous"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// N.B., If you change this, you'll probably want to change the corresponding
|
||||
|
@ -188,6 +199,9 @@ pub enum TyKind<'tcx> {
|
|||
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
||||
Param(ParamTy),
|
||||
|
||||
/// Bound type variable, used only when preparing a trait query.
|
||||
Bound(BoundTy),
|
||||
|
||||
/// A type variable used during type checking.
|
||||
Infer(InferTy),
|
||||
|
||||
|
@ -727,8 +741,8 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
|
|||
/// or some placeholder type.
|
||||
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
|
||||
-> ty::TraitRef<'tcx> {
|
||||
// otherwise the escaping regions would be captured by the binder
|
||||
// debug_assert!(!self_ty.has_escaping_regions());
|
||||
// otherwise the escaping vars would be captured by the binder
|
||||
// debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
ty::TraitRef {
|
||||
def_id: self.def_id,
|
||||
|
@ -755,11 +769,11 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Binder is a binder for higher-ranked lifetimes. It is part of the
|
||||
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
|
||||
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
|
||||
/// (which would be represented by the type `PolyTraitRef ==
|
||||
/// Binder<TraitRef>`). Note that when we instantiate,
|
||||
/// erase, or otherwise "discharge" these bound regions, we change the
|
||||
/// erase, or otherwise "discharge" these bound vars, we change the
|
||||
/// type from `Binder<T>` to just `T` (see
|
||||
/// e.g. `liberate_late_bound_regions`).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
|
@ -767,29 +781,28 @@ pub struct Binder<T>(T);
|
|||
|
||||
impl<T> Binder<T> {
|
||||
/// Wraps `value` in a binder, asserting that `value` does not
|
||||
/// contain any bound regions that would be bound by the
|
||||
/// contain any bound vars that would be bound by the
|
||||
/// binder. This is commonly used to 'inject' a value T into a
|
||||
/// different binding level.
|
||||
pub fn dummy<'tcx>(value: T) -> Binder<T>
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
debug_assert!(!value.has_escaping_regions());
|
||||
debug_assert!(!value.has_escaping_bound_vars());
|
||||
Binder(value)
|
||||
}
|
||||
|
||||
/// Wraps `value` in a binder, binding late-bound regions (if any).
|
||||
pub fn bind<'tcx>(value: T) -> Binder<T>
|
||||
{
|
||||
/// Wraps `value` in a binder, binding higher-ranked vars (if any).
|
||||
pub fn bind<'tcx>(value: T) -> Binder<T> {
|
||||
Binder(value)
|
||||
}
|
||||
|
||||
/// Skips the binder and returns the "bound" value. This is a
|
||||
/// risky thing to do because it's easy to get confused about
|
||||
/// debruijn indices and the like. It is usually better to
|
||||
/// discharge the binder using `no_late_bound_regions` or
|
||||
/// discharge the binder using `no_bound_vars` or
|
||||
/// `replace_late_bound_regions` or something like
|
||||
/// that. `skip_binder` is only valid when you are either
|
||||
/// extracting data that has nothing to do with bound regions, you
|
||||
/// extracting data that has nothing to do with bound vars, you
|
||||
/// are doing some sort of test that does not involve bound
|
||||
/// regions, or you are being very careful about your depth
|
||||
/// accounting.
|
||||
|
@ -798,7 +811,7 @@ impl<T> Binder<T> {
|
|||
///
|
||||
/// - extracting the def-id from a PolyTraitRef;
|
||||
/// - comparing the self type of a PolyTraitRef to see if it is equal to
|
||||
/// a type parameter `X`, since the type `X` does not reference any regions
|
||||
/// a type parameter `X`, since the type `X` does not reference any regions
|
||||
pub fn skip_binder(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
|
@ -820,19 +833,19 @@ impl<T> Binder<T> {
|
|||
}
|
||||
|
||||
/// Unwraps and returns the value within, but only if it contains
|
||||
/// no bound regions at all. (In other words, if this binder --
|
||||
/// no bound vars at all. (In other words, if this binder --
|
||||
/// and indeed any enclosing binder -- doesn't bind anything at
|
||||
/// all.) Otherwise, returns `None`.
|
||||
///
|
||||
/// (One could imagine having a method that just unwraps a single
|
||||
/// binder, but permits late-bound regions bound by enclosing
|
||||
/// binder, but permits late-bound vars bound by enclosing
|
||||
/// binders, but that would require adjusting the debruijn
|
||||
/// indices, and given the shallow binding structure we often use,
|
||||
/// would not be that useful.)
|
||||
pub fn no_late_bound_regions<'tcx>(self) -> Option<T>
|
||||
where T : TypeFoldable<'tcx>
|
||||
pub fn no_bound_vars<'tcx>(self) -> Option<T>
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
if self.skip_binder().has_escaping_regions() {
|
||||
if self.skip_binder().has_escaping_bound_vars() {
|
||||
None
|
||||
} else {
|
||||
Some(self.skip_binder().clone())
|
||||
|
@ -1166,9 +1179,6 @@ pub enum RegionKind {
|
|||
/// `ClosureRegionRequirements` that are produced by MIR borrowck.
|
||||
/// See `ClosureRegionRequirements` for more details.
|
||||
ReClosureBound(RegionVid),
|
||||
|
||||
/// Canonicalized region, used only when preparing a trait query.
|
||||
ReCanonical(BoundTyIndex),
|
||||
}
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
|
||||
|
@ -1219,22 +1229,37 @@ pub enum InferTy {
|
|||
FreshTy(u32),
|
||||
FreshIntTy(u32),
|
||||
FreshFloatTy(u32),
|
||||
|
||||
/// Bound type variable, used only when preparing a trait query.
|
||||
BoundTy(BoundTy),
|
||||
}
|
||||
|
||||
newtype_index! {
|
||||
pub struct BoundTyIndex { .. }
|
||||
pub struct BoundVar { .. }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct BoundTy {
|
||||
pub level: DebruijnIndex,
|
||||
pub var: BoundTyIndex,
|
||||
pub index: DebruijnIndex,
|
||||
pub var: BoundVar,
|
||||
pub kind: BoundTyKind,
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct BoundTy { level, var });
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum BoundTyKind {
|
||||
Anon,
|
||||
Param(InternedString),
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct BoundTy { index, var, kind });
|
||||
impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
|
||||
|
||||
impl BoundTy {
|
||||
pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
|
||||
BoundTy {
|
||||
index,
|
||||
var,
|
||||
kind: BoundTyKind::Anon,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
|
@ -1264,7 +1289,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
|
|||
-> ty::ProjectionPredicate<'tcx>
|
||||
{
|
||||
// otherwise the escaping regions would be captured by the binders
|
||||
debug_assert!(!self_ty.has_escaping_regions());
|
||||
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
|
@ -1363,7 +1388,6 @@ impl RegionKind {
|
|||
RegionKind::ReEmpty => false,
|
||||
RegionKind::ReErased => false,
|
||||
RegionKind::ReClosureBound(..) => false,
|
||||
RegionKind::ReCanonical(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1450,10 +1474,6 @@ impl RegionKind {
|
|||
}
|
||||
ty::ReErased => {
|
||||
}
|
||||
ty::ReCanonical(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_CANONICAL_VARS;
|
||||
}
|
||||
ty::ReClosureBound(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
}
|
||||
|
@ -1865,6 +1885,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
Tuple(..) |
|
||||
Foreign(..) |
|
||||
Param(_) |
|
||||
Bound(..) |
|
||||
Infer(_) |
|
||||
Error => {
|
||||
vec![]
|
||||
|
@ -1930,7 +1951,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
|
||||
ty::Infer(ty::TyVar(_)) => false,
|
||||
|
||||
ty::Infer(ty::BoundTy(_)) |
|
||||
ty::Bound(_) |
|
||||
ty::Infer(ty::FreshTy(_)) |
|
||||
ty::Infer(ty::FreshIntTy(_)) |
|
||||
ty::Infer(ty::FreshFloatTy(_)) =>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use hir::def_id::DefId;
|
||||
use infer::canonical::Canonical;
|
||||
use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt};
|
||||
use ty::{self, BoundVar, Lift, List, Ty, TyCtxt};
|
||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
||||
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
|
||||
|
@ -355,7 +355,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T {
|
|||
span,
|
||||
root_ty: None,
|
||||
ty_stack_depth: 0,
|
||||
region_binders_passed: 0 };
|
||||
binders_passed: 0 };
|
||||
(*self).fold_with(&mut folder)
|
||||
}
|
||||
}
|
||||
|
@ -377,16 +377,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
ty_stack_depth: usize,
|
||||
|
||||
// Number of region binders we have passed through while doing the substitution
|
||||
region_binders_passed: u32,
|
||||
binders_passed: u32,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
|
||||
|
||||
fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
|
||||
self.region_binders_passed += 1;
|
||||
self.binders_passed += 1;
|
||||
let t = t.super_fold_with(self);
|
||||
self.region_binders_passed -= 1;
|
||||
self.binders_passed -= 1;
|
||||
t
|
||||
}
|
||||
|
||||
|
@ -471,12 +471,12 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
self.shift_regions_through_binders(ty)
|
||||
self.shift_vars_through_binders(ty)
|
||||
}
|
||||
|
||||
/// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs
|
||||
/// when we are substituting a type with escaping regions into a context where we have passed
|
||||
/// through region binders. That's quite a mouthful. Let's see an example:
|
||||
/// when we are substituting a type with escaping bound vars into a context where we have
|
||||
/// passed through binders. That's quite a mouthful. Let's see an example:
|
||||
///
|
||||
/// ```
|
||||
/// type Func<A> = fn(A);
|
||||
|
@ -516,25 +516,25 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
|
|||
/// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
|
||||
/// first case we do not increase the Debruijn index and in the second case we do. The reason
|
||||
/// is that only in the second case have we passed through a fn binder.
|
||||
fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})",
|
||||
ty, self.region_binders_passed, ty.has_escaping_regions());
|
||||
fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
|
||||
ty, self.binders_passed, ty.has_escaping_bound_vars());
|
||||
|
||||
if self.region_binders_passed == 0 || !ty.has_escaping_regions() {
|
||||
if self.binders_passed == 0 || !ty.has_escaping_bound_vars() {
|
||||
return ty;
|
||||
}
|
||||
|
||||
let result = ty::fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
|
||||
debug!("shift_regions: shifted result = {:?}", result);
|
||||
let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed);
|
||||
debug!("shift_vars: shifted result = {:?}", result);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
if self.region_binders_passed == 0 || !region.has_escaping_regions() {
|
||||
if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
|
||||
return region;
|
||||
}
|
||||
self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
|
||||
ty::fold::shift_region(self.tcx, region, self.binders_passed)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,15 +553,23 @@ impl CanonicalUserSubsts<'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| {
|
||||
self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
UnpackedKind::Type(ty) => match ty.sty {
|
||||
ty::Infer(ty::BoundTy(ref b)) => cvar == b.var,
|
||||
ty::Bound(b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(b.index, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
UnpackedKind::Lifetime(r) => match r {
|
||||
ty::ReCanonical(cvar1) => cvar == *cvar1,
|
||||
ty::ReLateBound(index, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*index, ty::INNERMOST);
|
||||
cvar == br.assert_bound_var()
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
erased_self_ty,
|
||||
predicates);
|
||||
|
||||
assert!(!erased_self_ty.has_escaping_regions());
|
||||
assert!(!erased_self_ty.has_escaping_bound_vars());
|
||||
|
||||
traits::elaborate_predicates(self, predicates)
|
||||
.filter_map(|predicate| {
|
||||
|
@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// construct such an object, but this seems
|
||||
// correct even if that code changes).
|
||||
let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
|
||||
if t == &erased_self_ty && !r.has_escaping_regions() {
|
||||
if t == &erased_self_ty && !r.has_escaping_bound_vars() {
|
||||
Some(*r)
|
||||
} else {
|
||||
None
|
||||
|
@ -951,7 +951,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::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
|
||||
ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
|
||||
|
||||
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
|
|
|
@ -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::Foreign(..) => {
|
||||
ty::Bound(..) | ty::Foreign(..) => {
|
||||
}
|
||||
ty::Array(ty, len) => {
|
||||
push_const(stack, len);
|
||||
|
|
|
@ -158,7 +158,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
let infcx = &mut self.infcx;
|
||||
let param_env = self.param_env;
|
||||
self.out.iter()
|
||||
.inspect(|pred| assert!(!pred.has_escaping_regions()))
|
||||
.inspect(|pred| assert!(!pred.has_escaping_bound_vars()))
|
||||
.flat_map(|pred| {
|
||||
let mut selcx = traits::SelectionContext::new(infcx);
|
||||
let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
|
||||
|
@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
|
||||
self.out.extend(
|
||||
trait_ref.substs.types()
|
||||
.filter(|ty| !ty.has_escaping_regions())
|
||||
.filter(|ty| !ty.has_escaping_bound_vars())
|
||||
.map(|ty| traits::Obligation::new(cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::WellFormed(ty))));
|
||||
|
@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
let trait_ref = data.trait_ref(self.infcx.tcx);
|
||||
self.compute_trait_ref(&trait_ref, Elaborate::None);
|
||||
|
||||
if !data.has_escaping_regions() {
|
||||
if !data.has_escaping_bound_vars() {
|
||||
let predicate = trait_ref.to_predicate();
|
||||
let cause = self.cause(traits::ProjectionWf(data));
|
||||
self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
|
||||
|
@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
|
||||
if !subty.has_escaping_regions() {
|
||||
if !subty.has_escaping_bound_vars() {
|
||||
let cause = self.cause(cause);
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
|
||||
|
@ -258,6 +258,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
ty::GeneratorWitness(..) |
|
||||
ty::Never |
|
||||
ty::Param(_) |
|
||||
ty::Bound(..) |
|
||||
ty::Foreign(..) => {
|
||||
// WfScalar, WfParameter, etc
|
||||
}
|
||||
|
@ -299,7 +300,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
|
||||
ty::Ref(r, rty, _) => {
|
||||
// WfReference
|
||||
if !r.has_escaping_regions() && !rty.has_escaping_regions() {
|
||||
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
|
||||
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
|
||||
self.out.push(
|
||||
traits::Obligation::new(
|
||||
|
@ -450,7 +451,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
.map(|pred| traits::Obligation::new(cause.clone(),
|
||||
self.param_env,
|
||||
pred))
|
||||
.filter(|pred| !pred.has_escaping_regions())
|
||||
.filter(|pred| !pred.has_escaping_bound_vars())
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -489,7 +490,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
// Note: in fact we only permit builtin traits, not `Bar<'d>`, I
|
||||
// am looking forward to the future here.
|
||||
|
||||
if !data.has_escaping_regions() {
|
||||
if !data.has_escaping_bound_vars() {
|
||||
let implicit_bounds =
|
||||
object_region_bounds(self.infcx.tcx, data);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use ty::subst::{self, Subst};
|
|||
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
|
||||
use ty::{Bool, Char, Adt};
|
||||
use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
|
||||
use ty::{Param, RawPtr, Ref, Never, Tuple};
|
||||
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::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
|
||||
|
@ -790,9 +790,6 @@ define_print! {
|
|||
ty::ReEarlyBound(ref data) => {
|
||||
write!(f, "{}", data.name)
|
||||
}
|
||||
ty::ReCanonical(_) => {
|
||||
write!(f, "'_")
|
||||
}
|
||||
ty::ReLateBound(_, br) |
|
||||
ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
|
||||
ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
|
||||
|
@ -860,10 +857,6 @@ define_print! {
|
|||
write!(f, "{:?}", vid)
|
||||
}
|
||||
|
||||
ty::ReCanonical(c) => {
|
||||
write!(f, "'?{}", c.index())
|
||||
}
|
||||
|
||||
ty::RePlaceholder(placeholder) => {
|
||||
write!(f, "RePlaceholder({:?})", placeholder)
|
||||
}
|
||||
|
@ -976,7 +969,6 @@ define_print! {
|
|||
ty::TyVar(_) => write!(f, "_"),
|
||||
ty::IntVar(_) => write!(f, "{}", "{integer}"),
|
||||
ty::FloatVar(_) => write!(f, "{}", "{float}"),
|
||||
ty::BoundTy(_) => write!(f, "_"),
|
||||
ty::FreshTy(v) => write!(f, "FreshTy({})", v),
|
||||
ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
|
||||
ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
|
||||
|
@ -988,7 +980,6 @@ define_print! {
|
|||
ty::TyVar(ref v) => write!(f, "{:?}", v),
|
||||
ty::IntVar(ref v) => write!(f, "{:?}", v),
|
||||
ty::FloatVar(ref v) => write!(f, "{:?}", v),
|
||||
ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()),
|
||||
ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
|
||||
ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
|
||||
ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
|
||||
|
@ -1119,6 +1110,19 @@ 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) => {
|
||||
match bound_ty.kind {
|
||||
ty::BoundTyKind::Anon => {
|
||||
if bound_ty.index == ty::INNERMOST {
|
||||
write!(f, "?{}", bound_ty.var.index())
|
||||
} else {
|
||||
write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index())
|
||||
}
|
||||
}
|
||||
|
||||
ty::BoundTyKind::Param(p) => write!(f, "{}", p),
|
||||
}
|
||||
}
|
||||
Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
|
||||
Dynamic(data, r) => {
|
||||
let r = r.print_to_string(cx);
|
||||
|
|
|
@ -426,7 +426,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
|||
|
||||
// These cannot exist in borrowck
|
||||
RegionKind::ReVar(..) |
|
||||
RegionKind::ReCanonical(..) |
|
||||
RegionKind::RePlaceholder(..) |
|
||||
RegionKind::ReClosureBound(..) |
|
||||
RegionKind::ReErased => span_bug!(borrow_span,
|
||||
|
|
|
@ -363,7 +363,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
|||
|
||||
ty::ReStatic => self.item_ub,
|
||||
|
||||
ty::ReCanonical(_) |
|
||||
ty::ReEmpty |
|
||||
ty::ReClosureBound(..) |
|
||||
ty::ReLateBound(..) |
|
||||
|
|
|
@ -558,7 +558,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
|
|||
// regions must appear in the argument
|
||||
// listing.
|
||||
let main_ret_ty = cx.tcx.erase_regions(
|
||||
&main_ret_ty.no_late_bound_regions().unwrap(),
|
||||
&main_ret_ty.no_bound_vars().unwrap(),
|
||||
);
|
||||
|
||||
if declare::get_defined_value(cx, "main").is_some() {
|
||||
|
|
|
@ -44,7 +44,7 @@ pub fn get_fn(
|
|||
debug!("get_fn(instance={:?})", instance);
|
||||
|
||||
assert!(!instance.substs.needs_infer());
|
||||
assert!(!instance.substs.has_escaping_regions());
|
||||
assert!(!instance.substs.has_escaping_bound_vars());
|
||||
assert!(!instance.substs.has_param_types());
|
||||
|
||||
let sig = instance.fn_sig(cx.tcx);
|
||||
|
|
|
@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
|||
ty::Infer(_) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Projection(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Opaque(..) |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Param(_) => {
|
||||
|
|
|
@ -285,7 +285,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
|
|||
|
||||
debug!("llvm_type({:#?})", self);
|
||||
|
||||
assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
|
||||
assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty);
|
||||
|
||||
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
||||
// types for Rust types that only differ in the choice of lifetimes.
|
||||
|
|
|
@ -616,22 +616,22 @@ fn escaping() {
|
|||
// Theta = [A -> &'a foo]
|
||||
env.create_simple_region_hierarchy();
|
||||
|
||||
assert!(!env.t_nil().has_escaping_regions());
|
||||
assert!(!env.t_nil().has_escaping_bound_vars());
|
||||
|
||||
let t_rptr_free1 = env.t_rptr_free(1);
|
||||
assert!(!t_rptr_free1.has_escaping_regions());
|
||||
assert!(!t_rptr_free1.has_escaping_bound_vars());
|
||||
|
||||
let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1());
|
||||
assert!(t_rptr_bound1.has_escaping_regions());
|
||||
assert!(t_rptr_bound1.has_escaping_bound_vars());
|
||||
|
||||
let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
|
||||
assert!(t_rptr_bound2.has_escaping_regions());
|
||||
assert!(t_rptr_bound2.has_escaping_bound_vars());
|
||||
|
||||
// t_fn = fn(A)
|
||||
let t_param = env.t_param(0);
|
||||
assert!(!t_param.has_escaping_regions());
|
||||
assert!(!t_param.has_escaping_bound_vars());
|
||||
let t_fn = env.t_fn(&[t_param], env.t_nil());
|
||||
assert!(!t_fn.has_escaping_regions());
|
||||
assert!(!t_fn.has_escaping_bound_vars());
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -718,6 +718,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
ty::Param(..) |
|
||||
ty::Infer(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Error |
|
||||
ty::Closure(..) |
|
||||
ty::Generator(..) |
|
||||
|
|
|
@ -277,8 +277,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
| ty::RePlaceholder(..)
|
||||
| ty::ReEmpty
|
||||
| ty::ReErased
|
||||
| ty::ReClosureBound(..)
|
||||
| ty::ReCanonical(..) => None,
|
||||
| ty::ReClosureBound(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,9 +82,9 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
// when we move to universes, we will, and this assertion
|
||||
// will start to fail.
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
query_constraint.no_late_bound_regions().unwrap_or_else(|| {
|
||||
query_constraint.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!(
|
||||
"query_constraint {:?} contained bound regions",
|
||||
"query_constraint {:?} contained bound vars",
|
||||
query_constraint,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -359,7 +359,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if ty.has_escaping_regions() || ty.references_error() {
|
||||
if ty.has_escaping_bound_vars() || ty.references_error() {
|
||||
span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
|
||||
} else {
|
||||
ty
|
||||
|
@ -2214,8 +2214,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
.enumerate()
|
||||
.filter_map(|(idx, constraint)| {
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
constraint.no_late_bound_regions().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound regions", constraint,);
|
||||
constraint.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", constraint,);
|
||||
});
|
||||
|
||||
match k1.unpack() {
|
||||
|
|
|
@ -905,12 +905,12 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
trait_ty: Ty<'tcx>,
|
||||
impl_ty: Ty<'tcx>,
|
||||
output: &mut Vec<MonoItem<'tcx>>) {
|
||||
assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
|
||||
!impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
|
||||
assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() &&
|
||||
!impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
|
||||
|
||||
if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
|
||||
let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
|
||||
assert!(!poly_trait_ref.has_escaping_regions());
|
||||
assert!(!poly_trait_ref.has_escaping_bound_vars());
|
||||
|
||||
// Walk all methods of the trait, including those of its supertraits
|
||||
let methods = tcx.vtable_methods(poly_trait_ref);
|
||||
|
@ -1082,7 +1082,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
|
|||
// regions must appear in the argument
|
||||
// listing.
|
||||
let main_ret_ty = self.tcx.erase_regions(
|
||||
&main_ret_ty.no_late_bound_regions().unwrap(),
|
||||
&main_ret_ty.no_bound_vars().unwrap(),
|
||||
);
|
||||
|
||||
let start_instance = Instance::resolve(
|
||||
|
|
|
@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
self.push_type_params(substs, iter::empty(), output);
|
||||
}
|
||||
ty::Error |
|
||||
ty::Bound(..) |
|
||||
ty::Infer(_) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Projection(..) |
|
||||
|
|
|
@ -844,7 +844,9 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
|||
let param_env = gcx.param_env(def_id);
|
||||
|
||||
// Normalize the sig.
|
||||
let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature");
|
||||
let sig = gcx.fn_sig(def_id)
|
||||
.no_bound_vars()
|
||||
.expect("LBR in ADT constructor signature");
|
||||
let sig = gcx.normalize_erasing_regions(param_env, sig);
|
||||
|
||||
let (adt_def, substs) = match sig.output().sty {
|
||||
|
|
|
@ -143,7 +143,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
|
|||
{
|
||||
let did = tcx.require_lang_item(lang_item);
|
||||
let poly_sig = tcx.fn_sig(did);
|
||||
let sig = poly_sig.no_late_bound_regions().unwrap();
|
||||
let sig = poly_sig.no_bound_vars().unwrap();
|
||||
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||
|
|
|
@ -506,6 +506,7 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
|
|||
ty::GeneratorWitness(..) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Infer(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Error => {
|
||||
bug!("unexpected type {:?}", ty)
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
|
|||
|
||||
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
|
||||
ty::Infer(..) | ty::Error => {
|
||||
ty::Bound(..) | ty::Infer(..) | ty::Error => {
|
||||
// By the time this code runs, all type variables ought to
|
||||
// be fully resolved.
|
||||
Err(NoSolution)
|
||||
|
|
|
@ -108,7 +108,7 @@ fn compute_implied_outlives_bounds<'tcx>(
|
|||
// From the full set of obligations, just filter down to the
|
||||
// region relationships.
|
||||
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
|
||||
assert!(!obligation.has_escaping_regions());
|
||||
assert!(!obligation.has_escaping_bound_vars());
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
|
@ -122,14 +122,14 @@ fn compute_implied_outlives_bounds<'tcx>(
|
|||
vec![]
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
|
||||
ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() {
|
||||
None => vec![],
|
||||
Some(ty::OutlivesPredicate(r_a, r_b)) => {
|
||||
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
|
||||
}
|
||||
},
|
||||
|
||||
ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
|
||||
ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() {
|
||||
None => vec![],
|
||||
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
|
||||
let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
|
||||
|
|
|
@ -93,6 +93,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
|
|||
ty::GeneratorWitness(..) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Infer(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Error => {
|
||||
bug!("unexpected type {:?}", ty);
|
||||
}
|
||||
|
|
|
@ -1748,7 +1748,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
|
|||
self.region_bounds.iter().map(|&(region_bound, span)| {
|
||||
// account for the binder being introduced below; no need to shift `param_ty`
|
||||
// because, at present at least, it can only refer to early-bound regions
|
||||
let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
|
||||
let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
|
||||
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
|
||||
(ty::Binder::dummy(outlives).to_predicate(), span)
|
||||
}).chain(
|
||||
|
|
|
@ -816,7 +816,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
|
|||
}
|
||||
// Replace constructor type with constructed type for tuple struct patterns.
|
||||
let pat_ty = pat_ty.fn_sig(tcx).output();
|
||||
let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
|
||||
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
|
||||
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
|
||||
|
|
|
@ -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::Infer(_) => None,
|
||||
ty::Bound(..) | ty::Infer(_) => None,
|
||||
|
||||
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
|
||||
ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |
|
||||
|
|
|
@ -460,7 +460,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Create a `PolyFnSig`. Note the oddity that late bound
|
||||
// regions appearing free in `expected_sig` are now bound up
|
||||
// in this binder we are creating.
|
||||
assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST));
|
||||
assert!(!expected_sig.sig.has_vars_bound_above(ty::INNERMOST));
|
||||
let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
|
||||
expected_sig.sig.inputs().iter().cloned(),
|
||||
expected_sig.sig.output(),
|
||||
|
|
|
@ -419,7 +419,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut structural_to_nomimal = FxHashMap::default();
|
||||
|
||||
let sig = tcx.fn_sig(def_id);
|
||||
let sig = sig.no_late_bound_regions().unwrap();
|
||||
let sig = sig.no_bound_vars().unwrap();
|
||||
if intr.inputs.len() != sig.inputs().len() {
|
||||
span_err!(tcx.sess, it.span, E0444,
|
||||
"platform-specific intrinsic has invalid number of \
|
||||
|
|
|
@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
value
|
||||
}
|
||||
};
|
||||
assert!(!bounds.has_escaping_regions());
|
||||
assert!(!bounds.has_escaping_bound_vars());
|
||||
|
||||
let cause = traits::ObligationCause::misc(span, self.body_id);
|
||||
obligations.extend(traits::predicates_for_generics(cause.clone(),
|
||||
|
|
|
@ -1374,7 +1374,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
fn_sig,
|
||||
substs);
|
||||
|
||||
assert!(!substs.has_escaping_regions());
|
||||
assert!(!substs.has_escaping_bound_vars());
|
||||
|
||||
// It is possible for type parameters or early-bound lifetimes
|
||||
// to appear in the signature of `self`. The substitutions we
|
||||
|
|
|
@ -653,8 +653,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
|
||||
debug!("register_predicate({:?})", obligation);
|
||||
if obligation.has_escaping_regions() {
|
||||
span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
|
||||
if obligation.has_escaping_bound_vars() {
|
||||
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}",
|
||||
obligation);
|
||||
}
|
||||
self.fulfillment_cx
|
||||
|
@ -1928,7 +1928,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if ty.has_escaping_regions() {
|
||||
if ty.has_escaping_bound_vars() {
|
||||
ty // FIXME: normalization and escaping regions
|
||||
} else {
|
||||
self.normalize_associated_types_in(span, &ty)
|
||||
|
@ -2431,7 +2431,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
cause: traits::ObligationCause<'tcx>,
|
||||
predicates: &ty::InstantiatedPredicates<'tcx>)
|
||||
{
|
||||
assert!(!predicates.has_escaping_regions());
|
||||
assert!(!predicates.has_escaping_bound_vars());
|
||||
|
||||
debug!("add_obligations_for_parameters(predicates={:?})",
|
||||
predicates);
|
||||
|
@ -5188,8 +5188,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
},
|
||||
);
|
||||
assert!(!substs.has_escaping_regions());
|
||||
assert!(!ty.has_escaping_regions());
|
||||
assert!(!substs.has_escaping_bound_vars());
|
||||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
// Write the "user substs" down first thing for later.
|
||||
let hir_id = self.tcx.hir.node_to_hir_id(node_id);
|
||||
|
|
|
@ -99,7 +99,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:
|
|||
|
||||
let span = tcx.hir.span(impl_node_id);
|
||||
let param_env = tcx.param_env(impl_did);
|
||||
assert!(!self_type.has_escaping_regions());
|
||||
assert!(!self_type.has_escaping_bound_vars());
|
||||
|
||||
debug!("visit_implementation_of_copy: self_type={:?} (free)",
|
||||
self_type);
|
||||
|
@ -176,7 +176,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
|
|||
let span = tcx.hir.span(impl_node_id);
|
||||
|
||||
let source = tcx.type_of(impl_did);
|
||||
assert!(!source.has_escaping_regions());
|
||||
assert!(!source.has_escaping_bound_vars());
|
||||
let target = {
|
||||
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
|
||||
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
|
||||
|
@ -356,7 +356,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
|
||||
let span = gcx.hir.span(impl_node_id);
|
||||
let param_env = gcx.param_env(impl_did);
|
||||
assert!(!source.has_escaping_regions());
|
||||
assert!(!source.has_escaping_bound_vars());
|
||||
|
||||
let err_info = CoerceUnsizedInfo { custom_kind: None };
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
|||
item_def_id: DefId,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() {
|
||||
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
|
||||
self.tcx().mk_projection(item_def_id, trait_ref.substs)
|
||||
} else {
|
||||
// no late-bound regions, we can just ignore the binder
|
||||
|
|
|
@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
|
|||
RegionKind::ReEmpty
|
||||
| RegionKind::ReErased
|
||||
| RegionKind::ReClosureBound(..)
|
||||
| RegionKind::ReCanonical(..)
|
||||
| RegionKind::ReScope(..)
|
||||
| RegionKind::ReVar(..)
|
||||
| RegionKind::RePlaceholder(..)
|
||||
|
|
|
@ -338,6 +338,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Bound(..) |
|
||||
ty::Infer(..) => {
|
||||
bug!("unexpected type encountered in \
|
||||
variance inference: {}",
|
||||
|
@ -426,7 +427,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
// way early-bound regions do, so we skip them here.
|
||||
}
|
||||
|
||||
ty::ReCanonical(_) |
|
||||
ty::ReFree(..) |
|
||||
ty::ReClosureBound(..) |
|
||||
ty::ReScope(..) |
|
||||
|
|
|
@ -1260,7 +1260,6 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
|
|||
ty::RePlaceholder(..) |
|
||||
ty::ReEmpty |
|
||||
ty::ReClosureBound(_) |
|
||||
ty::ReCanonical(_) |
|
||||
ty::ReErased => None
|
||||
}
|
||||
}
|
||||
|
@ -2733,6 +2732,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
|
||||
ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
|
||||
|
||||
ty::Bound(..) => panic!("Bound"),
|
||||
ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
|
||||
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
|
||||
ty::Infer(..) => panic!("Infer"),
|
||||
|
|
Loading…
Add table
Reference in a new issue