Added support for trait aliases as bounds.

This commit is contained in:
Alexander Regueiro 2018-10-12 01:50:03 +01:00
parent 8b096314a6
commit 34792d9f6a
12 changed files with 248 additions and 82 deletions

View File

@ -301,9 +301,7 @@ impl<'hir> Map<'hir> {
ItemKind::Struct(..) => Some(Def::Struct(def_id())),
ItemKind::Union(..) => Some(Def::Union(def_id())),
ItemKind::Trait(..) => Some(Def::Trait(def_id())),
ItemKind::TraitAlias(..) => {
bug!("trait aliases are not yet implemented (see issue #41517)")
},
ItemKind::TraitAlias(..) => Some(Def::TraitAlias(def_id())),
ItemKind::ExternCrate(_) |
ItemKind::Use(..) |
ItemKind::ForeignMod(..) |

View File

@ -1119,6 +1119,7 @@ for traits::Vtable<'gcx, N> where N: 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),
}
}
}
@ -1227,6 +1228,22 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
}
}
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

View File

@ -534,8 +534,11 @@ pub enum Vtable<'tcx, N> {
/// 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
@ -605,6 +608,13 @@ pub struct VtableFnPointerData<'tcx, N> {
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>,
@ -1067,6 +1077,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
VtableGenerator(c) => c.nested,
VtableObject(d) => d.nested,
VtableFnPointer(d) => d.nested,
VtableTraitAlias(d) => d.nested,
}
}
@ -1090,20 +1101,25 @@ impl<'tcx, N> Vtable<'tcx, N> {
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(),
}),
}
}
}

View File

@ -19,10 +19,7 @@ use super::PredicateObligation;
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;
@ -1073,7 +1070,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
super::VtableClosure(_) |
super::VtableGenerator(_) |
super::VtableFnPointer(_) |
super::VtableObject(_) => {
super::VtableObject(_) |
super::VtableTraitAlias(_) => {
debug!("assemble_candidates_from_impls: vtable={:?}",
vtable);
true
@ -1235,7 +1233,8 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
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,
@ -1486,7 +1485,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
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;

View File

@ -30,11 +30,11 @@ use super::{ObligationCause, PredicateObligation, TraitObligation};
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};
@ -271,6 +271,8 @@ enum SelectionCandidate<'tcx> {
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
FnPointerCandidate,
TraitAliasCandidate(DefId),
ObjectCandidate,
BuiltinObjectCandidate,
@ -286,12 +288,13 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
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);
@ -1452,7 +1455,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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;
@ -1632,6 +1635,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ambiguous: false,
};
self.assemble_candidates_for_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();
@ -1879,7 +1884,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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();
@ -1923,7 +1928,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
};
// 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 {
@ -1973,7 +1978,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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(_)) => {
@ -2250,6 +2255,24 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
}
fn assemble_candidates_for_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_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
//
@ -2300,7 +2323,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
| 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.
@ -2330,7 +2354,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
| FnPointerCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| BuiltinCandidate { .. } => true,
| BuiltinCandidate { .. }
| TraitAliasCandidate(..) => true,
ObjectCandidate | ProjectionCandidate => {
// Arbitrarily give param candidates priority
// over projection and object candidates.
@ -2724,15 +2749,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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)?;
@ -2744,13 +2774,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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 => {
@ -2758,13 +2789,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
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()))
}
@ -2998,10 +3028,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
) -> 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 {
@ -3053,7 +3083,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
) -> 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());
@ -3089,11 +3119,51 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, '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
@ -3151,7 +3221,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
.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

View File

@ -62,6 +62,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
}
}
}
@ -70,7 +72,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableImpl(impl_def_id={:?}, substs={:?}, nested={:?})",
"VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
self.impl_def_id, self.substs, self.nested
)
}
@ -80,7 +82,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableGenerator(generator_def_id={:?}, substs={:?}, nested={:?})",
"VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
self.generator_def_id, self.substs, self.nested
)
}
@ -90,7 +92,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableClosure(closure_def_id={:?}, substs={:?}, nested={:?})",
"VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
self.closure_def_id, self.substs, self.nested
)
}
@ -98,7 +100,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "VtableBuiltin(nested={:?})", self.nested)
write!(f, "VtableBuiltinData(nested={:?})", self.nested)
}
}
@ -116,7 +118,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableObject(upcast={:?}, vtable_base={}, nested={:?})",
"VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
self.upcast_trait_ref, self.vtable_base, self.nested
)
}
@ -126,12 +128,22 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableFnPointer(fn_ty={:?}, nested={:?})",
"VtableFnPointerData(fn_ty={:?}, nested={:?})",
self.fn_ty, self.nested
)
}
}
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
self.alias_def_id, self.substs, self.nested
)
}
}
impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
@ -321,6 +333,17 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
nested,
})
),
traits::VtableTraitAlias(traits::VtableTraitAliasData {
alias_def_id,
substs,
nested,
}) => tcx.lift(&substs).map(|substs|
traits::VtableTraitAlias(traits::VtableTraitAliasData {
alias_def_id,
substs,
nested,
})
),
}
}
}
@ -386,6 +409,12 @@ BraceStructTypeFoldableImpl! {
} where N: TypeFoldable<'tcx>
}
BraceStructTypeFoldableImpl! {
impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableTraitAliasData<'tcx, N> {
alias_def_id, substs, nested
} where N: TypeFoldable<'tcx>
}
EnumTypeFoldableImpl! {
impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
(traits::VtableImpl)(a),
@ -396,6 +425,7 @@ EnumTypeFoldableImpl! {
(traits::VtableParam)(a),
(traits::VtableBuiltin)(a),
(traits::VtableObject)(a),
(traits::VtableTraitAlias)(a),
} where N: TypeFoldable<'tcx>
}

View File

@ -400,7 +400,9 @@ fn resolve_associated_item<'a, 'tcx>(
None
}
}
traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
traits::VtableAutoImpl(..) |
traits::VtableParam(..) |
traits::VtableTraitAlias(..) => None
}
}

View File

@ -2801,7 +2801,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
/// 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)
}
@ -2815,14 +2815,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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) {
@ -2987,7 +2987,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
})
}
/// 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) {
@ -2999,7 +2999,19 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
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>

View File

@ -3888,7 +3888,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// report an error.
if record_used {
resolve_error(self, span,
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
}
return Def::Err;
}
@ -3896,7 +3896,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// Still doesn't deal with upvars
if record_used {
resolve_error(self, span,
ResolutionError::AttemptToUseNonConstantValueInConstant);
ResolutionError::AttemptToUseNonConstantValueInConstant);
}
return Def::Err;
}

View File

@ -419,12 +419,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
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);

View File

@ -1635,19 +1635,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if name == "packed" {
gate_feature_post!(&self, repr_packed, attr.span,
"the `#[repr(packed(n))]` attribute \
is experimental");
is experimental");
}
}
}
}
}
ast::ItemKind::TraitAlias(..) => {
gate_feature_post!(&self, trait_alias,
i.span,
"trait aliases are not yet fully implemented");
}
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
if polarity == ast::ImplPolarity::Negative {
gate_feature_post!(&self, optin_builtin_traits,
@ -1669,6 +1663,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
"auto traits are experimental and possibly buggy");
}
ast::ItemKind::TraitAlias(..) => {
gate_feature_post!(
&self,
trait_alias,
i.span,
"trait aliases are experimental"
);
}
ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
let msg = "`macro` is experimental";
gate_feature_post!(&self, decl_macro, i.span, msg);

View File

@ -0,0 +1,22 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(trait_alias)]
trait Foo = std::fmt::Debug;
fn foo<T: Foo>(v: &T) {
println!("{:?}", v);
}
pub fn main() {
foo(&12345);
let foo: &Foo = &0i32;
}