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);
}
}
-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>,
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);
}
FreshTy(a),
FreshIntTy(a),
FreshFloatTy(a),
- BoundTy(a),
});
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
&VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher),
&VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher),
&VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher),
+ &VtableTraitAlias(ref table_alias) => table_alias.hash_stable(hcx, hasher),
}
}
}
}
}
+ impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+ for traits::VtableTraitAliasData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ let traits::VtableTraitAliasData {
+ alias_def_id,
+ substs,
+ ref nested,
+ } = *self;
+ alias_def_id.hash_stable(hcx, hasher);
+ substs.hash_stable(hcx, hasher);
+ nested.hash_stable(hcx, hasher);
+ }
+ }
+
impl_stable_hash_for!(
impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
max_universe, variables, value
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,
/// Same as above, but for a fn pointer type with the given signature.
VtableFnPointer(VtableFnPointerData<'tcx, N>),
- /// Vtable automatically generated for a generator
+ /// Vtable automatically generated for a generator.
VtableGenerator(VtableGeneratorData<'tcx, N>),
+
+ /// Vtable for a trait alias.
+ VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
}
/// Identifies a particular impl in the source, along with a set of
pub nested: Vec<N>
}
+ #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+ pub struct VtableTraitAliasData<'tcx, N> {
+ pub alias_def_id: DefId,
+ pub substs: &'tcx Substs<'tcx>,
+ pub nested: Vec<N>,
+ }
+
/// Creates predicate obligations from the generic bounds.
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
VtableGenerator(c) => c.nested,
VtableObject(d) => d.nested,
VtableFnPointer(d) => d.nested,
+ VtableTraitAlias(d) => d.nested,
}
}
trait_def_id: d.trait_def_id,
nested: d.nested.into_iter().map(f).collect(),
}),
- VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
- fn_ty: p.fn_ty,
- nested: p.nested.into_iter().map(f).collect(),
+ VtableClosure(c) => VtableClosure(VtableClosureData {
+ closure_def_id: c.closure_def_id,
+ substs: c.substs,
+ nested: c.nested.into_iter().map(f).collect(),
}),
VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
generator_def_id: c.generator_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect(),
}),
- VtableClosure(c) => VtableClosure(VtableClosureData {
- closure_def_id: c.closure_def_id,
- substs: c.substs,
- nested: c.nested.into_iter().map(f).collect(),
- })
+ VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
+ fn_ty: p.fn_ty,
+ nested: p.nested.into_iter().map(f).collect(),
+ }),
+ VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
+ alias_def_id: d.alias_def_id,
+ substs: d.substs,
+ nested: d.nested.into_iter().map(f).collect(),
+ }),
}
}
}
use super::Selection;
use super::SelectionContext;
use super::SelectionError;
- use super::VtableClosureData;
- use super::VtableGeneratorData;
- use super::VtableFnPointerData;
- use super::VtableImplData;
+ use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPointerData};
use super::util;
use hir::def_id::DefId;
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,
}
}
- 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
super::VtableClosure(_) |
super::VtableGenerator(_) |
super::VtableFnPointer(_) |
- super::VtableObject(_) => {
+ super::VtableObject(_) |
+ super::VtableTraitAlias(_) => {
debug!("assemble_candidates_from_impls: vtable={:?}",
vtable);
true
confirm_object_candidate(selcx, obligation, obligation_trait_ref),
super::VtableAutoImpl(..) |
super::VtableParam(..) |
- super::VtableBuiltin(..) =>
+ super::VtableBuiltin(..) |
+ super::VtableTraitAlias(..) =>
// we don't create Select candidates with this kind of resolution
span_bug!(
obligation.cause.span,
impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
-> Progress<'tcx>
{
- let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
+ let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
let tcx = selcx.tcx();
let param_env = obligation.param_env;
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
use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
use super::{
VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
- VtableObject, VtableParam,
+ VtableObject, VtableParam, VtableTraitAlias,
};
use super::{
VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
- VtableGeneratorData, VtableImplData, VtableObjectData,
+ VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
};
use dep_graph::{DepKind, DepNodeIndex};
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
FnPointerCandidate,
+ TraitAliasCandidate(DefId),
+
ObjectCandidate,
BuiltinObjectCandidate,
ImplCandidate(def_id) => ImplCandidate(def_id),
AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
ProjectionCandidate => ProjectionCandidate,
+ ClosureCandidate => ClosureCandidate,
+ GeneratorCandidate => GeneratorCandidate,
FnPointerCandidate => FnPointerCandidate,
+ TraitAliasCandidate(def_id) => TraitAliasCandidate(def_id),
ObjectCandidate => ObjectCandidate,
BuiltinObjectCandidate => BuiltinObjectCandidate,
BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
- ClosureCandidate => ClosureCandidate,
- GeneratorCandidate => GeneratorCandidate,
ParamCandidate(ref trait_ref) => {
return tcx.lift(trait_ref).map(ParamCandidate);
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);
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)
}
},
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`.
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.
//
"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)
let predicate = self.infcx()
.resolve_type_vars_if_possible(&obligation.predicate);
- // ok to skip binder because of the nature of the
+ // OK to skip binder because of the nature of the
// trait-ref-is-knowable check, which does not care about
// bound regions
let trait_ref = predicate.skip_binder().trait_ref;
ambiguous: false,
};
+ self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
+
// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.
let def_id = obligation.predicate.def_id();
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)
return Ok(());
}
- // ok to skip binder because the substs on generator types never
+ // OK to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters
let self_ty = *obligation.self_ty().skip_binder();
}
};
- // ok to skip binder because the substs on closure types never
+ // OK to skip binder because the substs on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters
match obligation.self_ty().skip_binder().sty {
return Ok(());
}
- // ok to skip binder because what we are inspecting doesn't involve bound regions
+ // OK to skip binder because what we are inspecting doesn't involve bound regions
let self_ty = *obligation.self_ty().skip_binder();
match self_ty.sty {
ty::Infer(ty::TyVar(_)) => {
obligation.self_ty().skip_binder()
);
- // Object-safety candidates are only applicable to object-safe
- // traits. Including this check is useful because it helps
- // inference in cases of traits like `BorrowFrom`, which are
- // not object-safe, and which rely on being able to infer the
- // self-type from one of the other inputs. Without this check,
- // these cases wind up being considered ambiguous due to a
- // (spurious) ambiguity introduced here.
- let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
- if !self.tcx().is_object_safe(predicate_trait_ref.def_id()) {
- return;
- }
-
self.probe(|this, _snapshot| {
// the code below doesn't care about regions, and the
// self-ty here doesn't escape this probe, so just erase
// 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.
}
}
+ fn assemble_candidates_for_trait_alias(
+ &mut self,
+ obligation: &TraitObligation<'tcx>,
+ candidates: &mut SelectionCandidateSet<'tcx>,
+ ) -> Result<(), SelectionError<'tcx>> {
+ // OK to skip binder here because the tests we do below do not involve bound regions
+ let self_ty = *obligation.self_ty().skip_binder();
+ debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
+
+ let def_id = obligation.predicate.def_id();
+
+ if ty::is_trait_alias(self.tcx(), def_id) {
+ candidates.vec.push(TraitAliasCandidate(def_id.clone()));
+ }
+
+ Ok(())
+ }
+
///////////////////////////////////////////////////////////////////////////
// WINNOW
//
| FnPointerCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
- | BuiltinCandidate { .. } => {
+ | BuiltinCandidate { .. }
+ | TraitAliasCandidate(..) => {
// Global bounds from the where clause should be ignored
// here (see issue #50825). Otherwise, we have a where
// clause so don't go around looking for impls.
| FnPointerCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
- | BuiltinCandidate { .. } => true,
+ | BuiltinCandidate { .. }
+ | TraitAliasCandidate(..) => true,
ObjectCandidate | ProjectionCandidate => {
// Arbitrarily give param candidates priority
// over projection and object candidates.
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(_)) => {
}
ty::UnnormalizedProjection(..)
- | ty::Infer(ty::BoundTy(_))
+ | ty::Bound(_)
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
| ty::Param(..)
| ty::Foreign(..)
| ty::Projection(..)
- | ty::Infer(ty::BoundTy(_))
+ | ty::Bound(_)
| ty::Infer(ty::TyVar(_))
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
Ok(VtableParam(obligations))
}
+ ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
+ obligation,
+ impl_def_id,
+ ))),
+
AutoImplCandidate(trait_def_id) => {
let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
Ok(VtableAutoImpl(data))
}
- ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
- obligation,
- impl_def_id,
- ))),
+ ProjectionCandidate => {
+ self.confirm_projection_candidate(obligation);
+ Ok(VtableParam(Vec::new()))
+ }
ClosureCandidate => {
let vtable_closure = self.confirm_closure_candidate(obligation)?;
Ok(VtableGenerator(vtable_generator))
}
- BuiltinObjectCandidate => {
- // This indicates something like `(Trait+Send) :
- // Send`. In this case, we know that this holds
- // because that's what the object type is telling us,
- // and there's really no additional obligations to
- // prove and no types in particular to unify etc.
- Ok(VtableParam(Vec::new()))
+ FnPointerCandidate => {
+ let data = self.confirm_fn_pointer_candidate(obligation)?;
+ Ok(VtableFnPointer(data))
+ }
+
+ TraitAliasCandidate(alias_def_id) => {
+ let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+ Ok(VtableTraitAlias(data))
}
ObjectCandidate => {
Ok(VtableObject(data))
}
- FnPointerCandidate => {
- let data = self.confirm_fn_pointer_candidate(obligation)?;
- Ok(VtableFnPointer(data))
- }
-
- ProjectionCandidate => {
- self.confirm_projection_candidate(obligation);
+ BuiltinObjectCandidate => {
+ // This indicates something like `(Trait+Send) :
+ // Send`. In this case, we know that this holds
+ // because that's what the object type is telling us,
+ // and there's really no additional obligations to
+ // prove and no types in particular to unify etc.
Ok(VtableParam(Vec::new()))
}
self.vtable_auto_impl(obligation, trait_def_id, types)
}
- /// See `confirm_auto_impl_candidate`
+ /// See `confirm_auto_impl_candidate`.
fn vtable_auto_impl(
&mut self,
obligation: &TraitObligation<'tcx>,
// this time not in a probe.
self.in_snapshot(|this, snapshot| {
let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot);
- debug!("confirm_impl_candidate substs={:?}", substs);
+ debug!("confirm_impl_candidate: substs={:?}", substs);
let cause = obligation.derived_cause(ImplDerivedObligation);
this.vtable_impl(
impl_def_id,
) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
debug!("confirm_object_candidate({:?})", obligation);
- // FIXME skipping binder here seems wrong -- we should
- // probably flatten the binder from the obligation and the
- // binder from the object. Have to try to make a broken test
- // case that results. -nmatsakis
+ // FIXME(nmatsakis) skipping binder here seems wrong -- we should
+ // probably flatten the binder from the obligation and the binder
+ // from the object. Have to try to make a broken test case that
+ // results.
let self_ty = self.infcx
.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!("confirm_fn_pointer_candidate({:?})", obligation);
- // ok to skip binder; it is reintroduced below
+ // OK to skip binder; it is reintroduced below
let self_ty = self.infcx
.shallow_resolve(*obligation.self_ty().skip_binder());
let sig = self_ty.fn_sig(self.tcx());
})
}
+ fn confirm_trait_alias_candidate(
+ &mut self,
+ obligation: &TraitObligation<'tcx>,
+ alias_def_id: DefId,
+ ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
+ debug!(
+ "confirm_trait_alias_candidate({:?}, {:?})",
+ obligation, alias_def_id
+ );
+
+ self.in_snapshot(|this, snapshot| {
+ let (predicate, placeholder_map) = this.infcx()
+ .replace_late_bound_regions_with_placeholders(&obligation.predicate);
+ let trait_ref = predicate.trait_ref;
+ let trait_def_id = trait_ref.def_id;
+ let substs = trait_ref.substs;
+
+ let trait_obligations = this.impl_or_trait_obligations(
+ obligation.cause.clone(),
+ obligation.recursion_depth,
+ obligation.param_env,
+ trait_def_id,
+ &substs,
+ placeholder_map,
+ snapshot,
+ );
+
+ debug!(
+ "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
+ trait_def_id, trait_obligations
+ );
+
+ VtableTraitAliasData {
+ alias_def_id,
+ substs: substs,
+ nested: trait_obligations,
+ }
+ })
+ }
+
fn confirm_generator_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- // ok to skip binder because the substs on generator types never
+ // OK to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters
let self_ty = self.infcx
.fn_trait_kind(obligation.predicate.def_id())
.unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
- // ok to skip binder because the substs on closure types never
+ // OK to skip binder because the substs on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters
let self_ty = self.infcx
// 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()
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 }
None
}
}
- traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
+ traits::VtableAutoImpl(..) |
+ traits::VtableParam(..) |
+ traits::VtableTraitAlias(..) => None
}
}
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};
// 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 |
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;
}
}
/// would be the type parameters.
Trait(PolyTraitPredicate<'tcx>),
- /// where 'a : 'b
+ /// where `'a : 'b`
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
- /// where T : 'a
+ /// where `T : 'a`
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
- /// where <T as TraitRef>::Name == X, approximately.
- /// See `ProjectionPredicate` struct for details.
+ /// where `<T as TraitRef>::Name == X`, approximately.
+ /// See the `ProjectionPredicate` struct for details.
Projection(PolyProjectionPredicate<'tcx>),
- /// no syntax: T WF
+ /// no syntax: `T` well-formed
WellFormed(Ty<'tcx>),
/// trait must be object-safe
ObjectSafe(DefId),
/// No direct syntax. May be thought of as `where T : FnFoo<...>`
- /// for some substitutions `...` and T being a closure type.
+ /// for some substitutions `...` and `T` being a closure type.
/// Satisfied (or refuted) once we know the closure's kind.
ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
}
}
+ Bound(..) |
Infer(..) => {
bug!("unexpected type `{:?}` in sized_constraint_for_ty",
ty)
}
}
- /// Determine whether an item is annotated with an attribute
+ /// Determine whether an item is annotated with an attribute.
pub fn has_attr(self, did: DefId, attr: &str) -> bool {
attr::contains_name(&self.get_attrs(did), attr)
}
self.optimized_mir(def_id).generator_layout.as_ref().unwrap()
}
- /// Given the def_id of an impl, return the def_id of the trait it implements.
+ /// Given the def-id of an impl, return the def_id of the trait it implements.
/// If it implements no trait, return `None`.
pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
self.impl_trait_ref(def_id).map(|tr| tr.def_id)
}
- /// If the given def ID describes a method belonging to an impl, return the
- /// ID of the impl that the method belongs to. Otherwise, return `None`.
+ /// If the given defid describes a method belonging to an impl, return the
+ /// def-id of the impl that the method belongs to. Otherwise, return `None`.
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
let item = if def_id.krate != LOCAL_CRATE {
if let Some(Def::Method(_)) = self.describe_def(def_id) {
})
}
- /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition
+ /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefId> {
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
if let Node::Item(item) = tcx.hir.get(node_id) {
None
}
- /// See `ParamEnv` struct def'n for details.
+ /// Returns `true` if `def_id` is a trait alias.
+ pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
+ if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+ if let Node::Item(item) = tcx.hir.get(node_id) {
+ if let hir::ItemKind::TraitAlias(..) = item.node {
+ return true;
+ }
+ }
+ }
+ false
+ }
+
+ /// See `ParamEnv` struct definition for details.
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ParamEnv<'tcx>
_ => 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
/// 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),
TraitRef { def_id: def_id, substs: substs }
}
- /// Returns a TraitRef of the form `P0: Foo<P1..Pn>` where `Pi`
+ /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
TraitRef {
/// 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,
}
}
-/// 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)]
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.
///
/// - 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
}
}
/// 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())
/// `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> {}
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)]
-> 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 {
RegionKind::ReEmpty => false,
RegionKind::ReErased => false,
RegionKind::ReClosureBound(..) => false,
- RegionKind::ReCanonical(..) => false,
}
}
}
ty::ReErased => {
}
- ty::ReCanonical(..) => {
- flags = flags | TypeFlags::HAS_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_CANONICAL_VARS;
- }
ty::ReClosureBound(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
}
Tuple(..) |
Foreign(..) |
Param(_) |
+ Bound(..) |
Infer(_) |
Error => {
vec![]
ty::Infer(ty::TyVar(_)) => false,
- ty::Infer(ty::BoundTy(_)) |
+ ty::Bound(_) |
ty::Infer(ty::FreshTy(_)) |
ty::Infer(ty::FreshIntTy(_)) |
ty::Infer(ty::FreshFloatTy(_)) =>
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| {
// 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
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
}
- /// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`).
+ /// True if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
pub fn is_trait(self, def_id: DefId) -> bool {
if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data {
true
// 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"),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
- //! Conversion from AST representation of types to the ty.rs
+ //! Conversion from AST representation of types to the `ty.rs`
//! representation. The main routine here is `ast_ty_to_ty()`: each use
//! is parameterized by an instance of `AstConv`.
item_segment: &hir::PathSegment)
-> &'tcx Substs<'tcx>
{
-
let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path(
span,
}
/// Given the type/region arguments provided to some path (along with
- /// an implicit Self, if this is a trait reference) returns the complete
+ /// an implicit `Self`, if this is a trait reference) returns the complete
/// set of substitutions. This may involve applying defaulted type parameters.
///
/// Note that the type listing given here is *exactly* what the user provided.
{
let trait_def_id = self.trait_def_id(trait_ref);
- debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
+ debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate(
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
- // ok to ignore Err() because ErrorReported (see above)
+ // ok to ignore Err because ErrorReported (see above)
Some((predicate.ok()?, binding.span))
}));
- debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
+ debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
trait_ref, poly_projections, poly_trait_ref);
poly_trait_ref
}
)
}
- /// Transform a PolyTraitRef into a PolyExistentialTraitRef by
- /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
+ /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
+ /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
-> ty::ExistentialTraitRef<'tcx> {
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
dummy_self,
&mut projection_bounds);
+ debug!("principal: {:?}", principal);
for trait_bound in trait_bounds[1..].iter() {
- // Sanity check for non-principal trait bounds
+ // sanity check for non-principal trait bounds
self.instantiate_poly_trait_ref(trait_bound,
dummy_self,
&mut vec![]);
})
});
- // check that there are no gross object safety violations,
+ // Check that there are no gross object safety violations;
// most importantly, that the supertraits don't contain Self,
- // to avoid ICE-s.
+ // to avoid ICEs.
let object_safety_violations =
- tcx.astconv_object_safety_violations(principal.def_id());
+ tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
if !object_safety_violations.is_empty() {
tcx.report_object_safety_error(
span, principal.def_id(), object_safety_violations)
return tcx.types.err;
}
- // use a btreeset to keep output in a more consistent order
+ // Use a BTreeSet to keep output in a more consistent order.
let mut associated_types = BTreeSet::default();
for tr in traits::supertraits(tcx, principal) {
v.sort_by(|a, b| a.stable_cmp(tcx, b));
let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
- // Explicitly specified region bound. Use that.
+ // Use explicitly-specified region bound.
let region_bound = if !lifetime.is_elided() {
self.ast_region_to_region(lifetime, None)
} else {
err.span_label(span, "associated type not allowed here").emit();
}
- // Check a type Path and convert it to a Ty.
+ // Check a type `Path` and convert it to a `Ty`.
pub fn def_to_ty(&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path,
/// Parses the programmer's textual representation of a type into our
/// internal notion of a type.
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
- debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
- ast_ty.id, ast_ty);
+ debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})",
+ ast_ty.id, ast_ty, ast_ty.node);
let tcx = self.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(
use std::iter;
+ struct OnlySelfBounds(bool);
+
///////////////////////////////////////////////////////////////////////////
// Main entry point
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
use rustc::hir::*;
// In the AST, bounds can derive from two places. Either
- // written inline like `<T:Foo>` or in a where clause like
- // `where T:Foo`.
+ // written inline like `<T : Foo>` or in a where clause like
+ // `where T : Foo`.
let param_id = tcx.hir.as_local_node_id(def_id).unwrap();
let param_owner = tcx.hir.ty_param_owner(param_id);
let icx = ItemCtxt::new(tcx, item_def_id);
result
.predicates
- .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty));
+ .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
+ OnlySelfBounds(true)));
result
}
impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
- /// Find bounds from hir::Generics. This requires scanning through the
+ /// Find bounds from `hir::Generics`. This requires scanning through the
/// AST. We do this to avoid having to convert *all* the bounds, which
/// would create artificial cycles. Instead we can only convert the
/// bounds for a type parameter `X` if `X::Foo` is used.
ast_generics: &hir::Generics,
param_id: ast::NodeId,
ty: Ty<'tcx>,
+ only_self_bounds: OnlySelfBounds,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let from_ty_params = ast_generics
.params
hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
_ => None,
})
- .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id))
- .flat_map(|bp| bp.bounds.iter())
- .flat_map(|b| predicates_from_bound(self, ty, b));
+ .flat_map(|bp| {
+ let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) {
+ Some(ty)
+ } else if !only_self_bounds.0 {
+ Some(self.to_ty(&bp.bounded_ty))
+ } else {
+ None
+ };
+ bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
+ })
+ .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
from_ty_params.chain(from_where_clauses).collect()
}
tcx.predicates_of(def_id);
}
hir::ItemKind::TraitAlias(..) => {
- span_err!(
- tcx.sess,
- it.span,
- E0645,
- "trait aliases are not yet implemented (see issue #41517)"
- );
+ tcx.generics_of(def_id);
+ tcx.at(it.span).super_predicates_of(def_id);
+ tcx.predicates_of(def_id);
}
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
tcx.generics_of(def_id);
let icx = ItemCtxt::new(tcx, trait_def_id);
- // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
+ // Convert the bounds that follow the colon, e.g. `Bar + Zed` in `trait Foo : Bar + Zed`.
let self_param_ty = tcx.mk_self_type();
let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
// Convert any explicit superbounds in the where clause,
- // e.g. `trait Foo where Self : Bar`:
- let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty);
+ // e.g. `trait Foo where Self : Bar`.
+ // In the case of trait aliases, however, we include all bounds in the where clause,
+ // so e.g. `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
+ // as one of its "superpredicates".
+ let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+ let superbounds2 = icx.type_parameter_bounds_in_generics(
+ generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
// Combine the two lists to form the complete set of superbounds:
let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect();
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
for &(pred, span) in &superbounds {
+ debug!("superbound: {:?}", pred);
if let ty::Predicate::Trait(bound) = pred {
tcx.at(span).super_predicates_of(bound.def_id());
}
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
+ let empty_trait_items = HirVec::new();
let mut predicates = UniquePredicates::new();
is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
generics
}
+ ItemKind::TraitAlias(ref generics, _) => {
+ is_trait = Some((ty::TraitRef::identity(tcx, def_id), &empty_trait_items));
+ generics
+ }
ItemKind::Existential(ExistTy {
ref bounds,
impl_trait_fn,
}
}
- /// Converts a specific GenericBound from the AST into a set of
+ /// Converts a specific `GenericBound` from the AST into a set of
/// predicates that apply to the self-type. A vector is returned
- /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
- /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
+ /// because this can be anywhere from zero predicates (`T : ?Sized` adds no
+ /// predicates) to one (`T : Foo`) to many (`T : Bar<X=i32>` adds `T : Bar`
/// and `<T as Bar>::X == i32`).
fn predicates_from_bound<'tcx>(
astconv: &dyn AstConv<'tcx, 'tcx>,