mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
Added support for trait aliases as bounds.
This commit is contained in:
parent
8b096314a6
commit
34792d9f6a
@ -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(..) |
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,9 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||
None
|
||||
}
|
||||
}
|
||||
traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
|
||||
traits::VtableAutoImpl(..) |
|
||||
traits::VtableParam(..) |
|
||||
traits::VtableTraitAlias(..) => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
22
src/test/run-pass/traits/trait-alias.rs
Normal file
22
src/test/run-pass/traits/trait-alias.rs
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user