Auto merge of #55101 - alexreg:trait-aliases, r=nikomatsakis

Implement trait aliases (RFC 1733)

Extends groundwork done in https://github.com/rust-lang/rust/pull/45047, and fully implements https://github.com/rust-lang/rfcs/pull/1733.

CC @durka @nikomatsakis
This commit is contained in:
bors 2018-11-03 17:30:37 +00:00
commit a3f0f5107e
42 changed files with 631 additions and 332 deletions

View File

@ -0,0 +1,34 @@
# `trait_alias`
The tracking issue for this feature is: [#41517]
[#41417]: https://github.com/rust-lang/rust/issues/41517
------------------------
The `trait_alias` feature adds support for trait aliases. These allow aliases
to be created for one or more traits (currently just a single regular trait plus
any number of auto-traits), and used wherever traits would normally be used as
either bounds or trait objects.
```rust
#![feature(trait_alias)]
trait Foo = std::fmt::Debug + Send;
trait Bar = Foo + Sync;
// Use trait alias as bound on type parameter.
fn foo<T: Foo>(v: &T) {
println!("{:?}", v);
}
pub fn main() {
foo(&1);
// Use trait alias for trait objects.
let a: &Bar = &123;
println!("{:?}", a);
let b = Box::new(456) as Box<dyn Foo>;
println!("{:?}", b);
}
```

View File

@ -4875,23 +4875,24 @@ fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::
let node = match qpath {
hir::QPath::Resolved(None, path) => {
// Turn trait object paths into `TyKind::TraitObject` instead.
if let Def::Trait(_) = path.def {
let principal = hir::PolyTraitRef {
bound_generic_params: hir::HirVec::new(),
trait_ref: hir::TraitRef {
path: path.and_then(|path| path),
ref_id: id.node_id,
hir_ref_id: id.hir_id,
},
span,
};
match path.def {
Def::Trait(_) | Def::TraitAlias(_) => {
let principal = hir::PolyTraitRef {
bound_generic_params: hir::HirVec::new(),
trait_ref: hir::TraitRef {
path: path.and_then(|path| path),
ref_id: id.node_id,
hir_ref_id: id.hir_id,
},
span,
};
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.
id = self.next_id();
hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
} else {
hir::TyKind::Path(hir::QPath::Resolved(None, path))
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.
id = self.next_id();
hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
}
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
}
}
_ => hir::TyKind::Path(qpath),

View File

@ -301,9 +301,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
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

@ -1118,6 +1118,7 @@ fn hash_stable<W: StableHasherResult>(&self,
&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),
}
}
}
@ -1226,6 +1227,22 @@ fn hash_stable<W: StableHasherResult>(&self,
}
}
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

@ -447,6 +447,17 @@ fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
map
}
/// In traits, there is an implicit `Self` type parameter which comes before the generics.
/// We have to account for this when computing the index of the other generic parameters.
/// This function returns whether there is such an implicit parameter defined on the given item.
fn sub_items_have_self_param(node: &hir::ItemKind) -> bool {
match *node {
hir::ItemKind::Trait(..) |
hir::ItemKind::TraitAlias(..) => true,
_ => false,
}
}
impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.tcx.hir)
@ -522,8 +533,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
hir::ItemKind::Impl(..) => true,
_ => false,
};
// These kinds of items have only early bound lifetime parameters.
let mut index = if let hir::ItemKind::Trait(..) = item.node {
// These kinds of items have only early-bound lifetime parameters.
let mut index = if sub_items_have_self_param(&item.node) {
1 // Self comes before lifetimes
} else {
0
@ -1602,8 +1613,8 @@ fn visit_early_late<F>(
let mut index = 0;
if let Some(parent_id) = parent_id {
let parent = self.tcx.hir.expect_item(parent_id);
if let hir::ItemKind::Trait(..) = parent.node {
index += 1; // Self comes first.
if sub_items_have_self_param(&parent.node) {
index += 1; // Self comes before lifetimes
}
match parent.node {
hir::ItemKind::Trait(_, _, ref generics, ..)

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 @@ pub fn nested_obligations(self) -> Vec<N> {
VtableGenerator(c) => c.nested,
VtableObject(d) => d.nested,
VtableFnPointer(d) => d.nested,
VtableTraitAlias(d) => d.nested,
}
}
@ -1090,20 +1101,25 @@ pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
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::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::{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 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
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 @@ fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<
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 @@ fn assemble_candidates<'o>(
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();
@ -1879,7 +1884,7 @@ fn assemble_generator_candidates(
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 @@ fn assemble_closure_candidates(
}
};
// 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 @@ fn assemble_fn_pointer_candidates(
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(_)) => {
@ -2238,6 +2243,24 @@ fn assemble_candidates_for_unsizing(
}
}
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
//
@ -2288,7 +2311,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
| 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.
@ -2318,7 +2342,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
| FnPointerCandidate
| BuiltinObjectCandidate
| BuiltinUnsizeCandidate
| BuiltinCandidate { .. } => true,
| BuiltinCandidate { .. }
| TraitAliasCandidate(..) => true,
ObjectCandidate | ProjectionCandidate => {
// Arbitrarily give param candidates priority
// over projection and object candidates.
@ -2712,15 +2737,20 @@ fn confirm_candidate(
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)?;
@ -2732,13 +2762,14 @@ fn confirm_candidate(
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 => {
@ -2746,13 +2777,12 @@ fn confirm_candidate(
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()))
}
@ -2865,7 +2895,7 @@ fn confirm_auto_impl_candidate(
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>,
@ -2922,7 +2952,7 @@ fn confirm_impl_candidate(
// 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,
@ -2986,10 +3016,10 @@ fn confirm_object_candidate(
) -> 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 {
@ -3041,7 +3071,7 @@ fn confirm_fn_pointer_candidate(
) -> 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());
@ -3077,11 +3107,51 @@ fn confirm_fn_pointer_candidate(
})
}
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
@ -3139,7 +3209,7 @@ fn confirm_closure_candidate(
.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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
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 @@ impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> {
} 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 @@ impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
(traits::VtableParam)(a),
(traits::VtableBuiltin)(a),
(traits::VtableObject)(a),
(traits::VtableTraitAlias)(a),
} where N: TypeFoldable<'tcx>
}

View File

@ -333,7 +333,7 @@ fn new(base: I) -> FilterToTraits<I> {
}
}
impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
type Item = ty::PolyTraitRef<'tcx>;
fn next(&mut self) -> Option<ty::PolyTraitRef<'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

@ -1046,24 +1046,24 @@ pub enum Predicate<'tcx> {
/// 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),
@ -2797,7 +2797,7 @@ pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
}
}
/// 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)
}
@ -2811,14 +2811,14 @@ pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'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) {
@ -2983,7 +2983,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) {
@ -2995,7 +2995,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

@ -650,7 +650,7 @@ pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
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 {

View File

@ -527,7 +527,7 @@ pub fn is_closure(self, def_id: DefId) -> bool {
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

View File

@ -403,25 +403,6 @@ fn visit_item(&mut self, item: &'a Item) {
}
}
}
ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
for param in params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => {
if !param.bounds.is_empty() {
self.err_handler()
.span_err(param.ident.span, "type parameters on the left \
side of a trait alias cannot be bounded");
}
if !default.is_none() {
self.err_handler()
.span_err(param.ident.span, "type parameters on the left \
side of a trait alias cannot have defaults");
}
}
}
}
}
ItemKind::Mod(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path");

View File

@ -538,9 +538,9 @@ fn is_expected(self, def: Def) -> bool {
match self {
PathSource::Type => match def {
Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
Def::Existential(..) |
Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
Def::SelfTy(..) | Def::Existential(..) |
Def::ForeignTy(..) => true,
_ => false,
},
@ -3122,7 +3122,10 @@ fn smart_resolve_path_fragment(&mut self,
return (err, candidates);
}
(Def::TyAlias(..), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used for traits");
err.span_label(span, "type aliases cannot be used as traits");
if nightly_options::is_nightly_build() {
err.note("did you mean to use a trait alias?");
}
return (err, candidates);
}
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
@ -3888,7 +3891,7 @@ fn adjust_local_def(&mut self,
// report an error.
if record_used {
resolve_error(self, span,
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
}
return Def::Err;
}
@ -3896,7 +3899,7 @@ fn adjust_local_def(&mut self,
// Still doesn't deal with upvars
if record_used {
resolve_error(self, span,
ResolutionError::AttemptToUseNonConstantValueInConstant);
ResolutionError::AttemptToUseNonConstantValueInConstant);
}
return Def::Err;
}

View File

@ -8,7 +8,7 @@
// 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`.
@ -181,7 +181,6 @@ pub fn ast_path_substs_for_ty(&self,
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,
@ -545,7 +544,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
}
/// 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.
@ -722,7 +721,7 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
{
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);
@ -739,11 +738,11 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
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
}
@ -948,8 +947,8 @@ fn ast_path_to_ty(&self,
)
}
/// 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);
@ -975,9 +974,10 @@ fn conv_object_ty_poly_trait_ref(&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![]);
@ -1009,9 +1009,9 @@ fn conv_object_ty_poly_trait_ref(&self,
})
});
// 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.global_tcx().astconv_object_safety_violations(principal.def_id());
if !object_safety_violations.is_empty() {
@ -1021,7 +1021,7 @@ fn conv_object_ty_poly_trait_ref(&self,
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) {
@ -1060,7 +1060,7 @@ fn conv_object_ty_poly_trait_ref(&self,
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 {
@ -1347,7 +1347,7 @@ pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) {
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,
@ -1442,8 +1442,8 @@ pub fn def_to_ty(&self,
/// 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();

View File

@ -153,6 +153,9 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def
hir::ItemKind::Trait(..) => {
check_trait(tcx, item);
}
hir::ItemKind::TraitAlias(..) => {
check_trait(tcx, item);
}
_ => {}
}
}

View File

@ -58,6 +58,8 @@
use std::iter;
struct OnlySelfBounds(bool);
///////////////////////////////////////////////////////////////////////////
// Main entry point
@ -245,8 +247,8 @@ fn type_param_predicates<'a, 'tcx>(
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);
@ -317,12 +319,13 @@ fn type_param_predicates<'a, 'tcx>(
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.
@ -331,6 +334,7 @@ fn type_parameter_bounds_in_generics(
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
@ -350,9 +354,17 @@ fn type_parameter_bounds_in_generics(
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()
}
@ -419,12 +431,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);
@ -693,15 +702,20 @@ fn super_predicates_of<'a, 'tcx>(
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();
@ -709,6 +723,7 @@ fn super_predicates_of<'a, 'tcx>(
// 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());
}
@ -1678,6 +1693,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let empty_trait_items = HirVec::new();
let mut predicates = UniquePredicates::new();
@ -1722,6 +1738,10 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
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,
@ -2010,10 +2030,10 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
}
}
/// 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>,

View File

@ -288,9 +288,9 @@ pub enum TraitBoundModifier {
}
/// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and
/// detects Copy, Send and Sync.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifier),

View File

@ -252,7 +252,7 @@ pub fn span(&self) -> Span {
pub struct MacroExpander<'a, 'b:'a> {
pub cx: &'a mut ExtCtxt<'b>,
monotonic: bool, // c.f. `cx.monotonic_expander()`
monotonic: bool, // cf. `cx.monotonic_expander()`
}
impl<'a, 'b> MacroExpander<'a, 'b> {

View File

@ -1635,19 +1635,13 @@ fn visit_item(&mut self, i: &'a ast::Item) {
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 @@ fn visit_item(&mut self, i: &'a ast::Item) {
"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

@ -1295,7 +1295,7 @@ fn token_is_bare_fn_keyword(&mut self) -> bool {
self.check_keyword(keywords::Extern) && self.is_extern_non_path()
}
/// parse a TyKind::BareFn type:
/// parse a `TyKind::BareFn` type:
fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
/*
@ -1532,7 +1532,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
let path = match bounds[0] {
GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
_ => self.bug("unexpected lifetime bound"),
GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
};
self.parse_remaining_bounds(Vec::new(), path, lo, true)?
}
@ -5779,7 +5779,7 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
// Method macro.
// method macro
Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
ast::ImplItemKind::Macro(mac)))
} else {
@ -6792,11 +6792,11 @@ fn parse_item_foreign_mod(&mut self,
Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs))
}
/// Parse type Foo = Bar;
/// Parse `type Foo = Bar;`
/// or
/// existential type Foo: Bar;
/// `existential type Foo: Bar;`
/// or
/// return None without modifying the parser state
/// `return None` without modifying the parser state
fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
// This parses the grammar:
// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"

View File

@ -0,0 +1,65 @@
// 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)]
use std::marker::PhantomData;
trait Empty {}
trait EmptyAlias = Empty;
trait CloneDefault = Clone + Default;
trait SendSyncAlias = Send + Sync;
trait WhereSendAlias = where Self: Send;
trait SendEqAlias<T> = Send where T: PartialEq<Self>;
trait I32Iterator = Iterator<Item = i32>;
#[allow(dead_code)]
struct Foo<T: SendSyncAlias>(PhantomData<T>);
#[allow(dead_code)]
struct Bar<T>(PhantomData<T>) where T: SendSyncAlias;
impl EmptyAlias {}
impl<T: SendSyncAlias> Empty for T {}
fn a<T: CloneDefault>() -> (T, T) {
let one = T::default();
let two = one.clone();
(one, two)
}
fn b(x: &impl SendEqAlias<i32>) -> bool {
22_i32 == *x
}
fn c<T: I32Iterator>(x: &mut T) -> Option<i32> {
x.next()
}
fn d<T: SendSyncAlias>() {
is_send_and_sync::<T>();
}
fn is_send_and_sync<T: Send + Sync>() {}
fn main() {
let both = a::<i32>();
assert_eq!(both.0, 0);
assert_eq!(both.1, 0);
let both: (i32, i32) = a();
assert_eq!(both.0, 0);
assert_eq!(both.1, 0);
assert!(b(&22));
assert_eq!(c(&mut vec![22].into_iter()), Some(22));
d::<i32>();
}

View File

@ -0,0 +1,27 @@
// 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 = PartialEq<i32> + Send;
trait Bar = Foo + Sync;
trait I32Iterator = Iterator<Item = i32>;
pub fn main() {
let a: &dyn Bar = &123;
assert!(*a == 123);
let b = Box::new(456) as Box<dyn Foo>;
assert!(*b == 456);
// FIXME(alexreg): associated type should be gotten from trait alias definition
// let c: &dyn I32Iterator = &vec![123].into_iter();
// assert_eq!(c.next(), Some(123));
}

View File

@ -0,0 +1,32 @@
// 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 SimpleAlias = Default;
trait GenericAlias<T> = Iterator<Item = T>;
trait Partial<T> = IntoIterator<Item = T>;
trait SpecificAlias = GenericAlias<i32>;
trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>;
trait StaticAlias = 'static;
trait Things<T> {}
trait Romeo {}
#[allow(dead_code)]
struct The<T>(T);
#[allow(dead_code)]
struct Fore<T>(T);
impl<T, U> Things<T> for The<U> {}
impl<T> Romeo for Fore<T> {}
trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
fn main() {}

View File

@ -2,7 +2,9 @@ error[E0404]: expected trait, found type alias `Bar`
--> $DIR/two_files.rs:15:6
|
LL | impl Bar for Baz { } //~ ERROR expected trait, found type alias
| ^^^ type aliases cannot be used for traits
| ^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
error: aborting due to previous error

View File

@ -0,0 +1,13 @@
// 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.
trait Foo = Default;
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0658]: trait aliases are experimental (see issue #41517)
--> $DIR/feature-gate-trait-alias.rs:11:1
|
LL | trait Foo = Default;
| ^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(trait_alias)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -2,7 +2,9 @@ error[E0404]: expected trait, found type alias `Foo`
--> $DIR/issue-3907.rs:20:6
|
LL | impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
| ^^^ type aliases cannot be used for traits
| ^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
help: possible better candidate is found in another module, you can import it into scope
|
LL | use issue_3907::Foo;

View File

@ -11,7 +11,9 @@ LL | impl K for isize {} //~ ERROR expected trait, found type alias `K`
| ^
| |
| did you mean `I`?
| type aliases cannot be used for traits
| type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
error: aborting due to 2 previous errors

View File

@ -8,7 +8,9 @@ error[E0404]: expected trait, found type alias `Typedef`
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:16:8
|
LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
|
= note: did you mean to use a trait alias?
error: aborting due to 2 previous errors

View File

@ -1,27 +0,0 @@
// Copyright 2017 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.
// gate-test-trait_alias
trait Alias1<T> = Default where T: Clone; // ok
//~^ERROR trait aliases are not yet fully implemented
trait Alias2<T: Clone = ()> = Default;
//~^ERROR type parameters on the left side of a trait alias cannot be bounded
//~^^ERROR type parameters on the left side of a trait alias cannot have defaults
//~^^^ERROR trait aliases are not yet fully implemented
impl Alias1 { //~ERROR expected type, found trait alias
}
impl Alias1 for () { //~ERROR expected trait, found trait alias
}
fn main() {}

View File

@ -1,44 +0,0 @@
error: type parameters on the left side of a trait alias cannot be bounded
--> $DIR/trait-alias-fail.rs:15:14
|
LL | trait Alias2<T: Clone = ()> = Default;
| ^
error: type parameters on the left side of a trait alias cannot have defaults
--> $DIR/trait-alias-fail.rs:15:14
|
LL | trait Alias2<T: Clone = ()> = Default;
| ^
error[E0573]: expected type, found trait alias `Alias1`
--> $DIR/trait-alias-fail.rs:20:6
|
LL | impl Alias1 { //~ERROR expected type, found trait alias
| ^^^^^^ not a type
error[E0404]: expected trait, found trait alias `Alias1`
--> $DIR/trait-alias-fail.rs:23:6
|
LL | impl Alias1 for () { //~ERROR expected trait, found trait alias
| ^^^^^^ not a trait
error[E0658]: trait aliases are not yet fully implemented (see issue #41517)
--> $DIR/trait-alias-fail.rs:13:1
|
LL | trait Alias1<T> = Default where T: Clone; // ok
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(trait_alias)] to the crate attributes to enable
error[E0658]: trait aliases are not yet fully implemented (see issue #41517)
--> $DIR/trait-alias-fail.rs:15:1
|
LL | trait Alias2<T: Clone = ()> = Default;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(trait_alias)] to the crate attributes to enable
error: aborting due to 6 previous errors
Some errors occurred: E0404, E0573, E0658.
For more information about an error, try `rustc --explain E0404`.

View File

@ -0,0 +1,17 @@
// 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 DefaultAlias = Default;
impl DefaultAlias for () {}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0404]: expected trait, found trait alias `DefaultAlias`
--> $DIR/trait-alias-impl.rs:15:6
|
LL | impl DefaultAlias for () {}
| ^^^^^^^^^^^^ not a trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0404`.

View File

@ -0,0 +1,19 @@
// 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 EqAlias = Eq;
trait IteratorAlias = Iterator;
fn main() {
let _: &dyn EqAlias = &123;
let _: &dyn IteratorAlias = &vec![123].into_iter();
}

View File

@ -0,0 +1,18 @@
error[E0038]: the trait `EqAlias` cannot be made into an object
--> $DIR/trait-alias-objects.rs:17:13
|
LL | let _: &dyn EqAlias = &123;
| ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
--> $DIR/trait-alias-objects.rs:18:13
|
LL | let _: &dyn IteratorAlias = &vec![123].into_iter();
| ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
error: aborting due to 2 previous errors
Some errors occurred: E0038, E0191.
For more information about an error, try `rustc --explain E0038`.

View File

@ -0,0 +1,17 @@
// 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 {}
trait A<T: Foo> {}
trait B<T> = A<T>; // T cannot be unbounded
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0277]: the trait bound `T: Foo` is not satisfied
--> $DIR/trait-alias-wf.rs:15:1
|
LL | trait B<T> = A<T>; // T cannot be unbounded
| ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
|
= help: consider adding a `where T: Foo` bound
note: required by `A`
--> $DIR/trait-alias-wf.rs:14:1
|
LL | trait A<T: Foo> {}
| ^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,43 +0,0 @@
// Copyright 2017 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 SimpleAlias = Default; //~ERROR E0645
trait GenericAlias<T> = Iterator<Item=T>; //~ERROR E0645
trait Partial<T> = IntoIterator<Item=T>; //~ERROR E0645
trait Things<T> {}
trait Romeo {}
struct The<T>(T);
struct Fore<T>(T);
impl<T, U> Things<T> for The<U> {}
impl<T> Romeo for Fore<T> {}
trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645
trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>; //~ERROR E0645
trait CD = Clone + Default; //~ERROR E0645
fn foo<T: CD>() -> (T, T) {
let one = T::default();
let two = one.clone();
(one, two)
}
fn main() {
let both = foo();
assert_eq!(both.0, 0);
assert_eq!(both.1, 0);
let both: (i32, i32) = foo();
assert_eq!(both.0, 0);
assert_eq!(both.1, 0);
}

View File

@ -1,39 +0,0 @@
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:13:1
|
LL | trait SimpleAlias = Default; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:14:1
|
LL | trait GenericAlias<T> = Iterator<Item=T>; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:15:1
|
LL | trait Partial<T> = IntoIterator<Item=T>; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:24:1
|
LL | trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:25:1
|
LL | trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0645]: trait aliases are not yet implemented (see issue #41517)
--> $DIR/trait-alias.rs:27:1
|
LL | trait CD = Clone + Default; //~ERROR E0645
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0645`.