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:
commit
a3f0f5107e
34
src/doc/unstable-book/src/language-features/trait-alias.md
Normal file
34
src/doc/unstable-book/src/language-features/trait-alias.md
Normal 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);
|
||||
}
|
||||
```
|
@ -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),
|
||||
|
@ -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(..) |
|
||||
|
@ -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
|
||||
|
@ -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, ..)
|
||||
|
@ -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(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
}
|
||||
|
||||
|
@ -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>> {
|
||||
|
@ -400,7 +400,9 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||
None
|
||||
}
|
||||
}
|
||||
traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
|
||||
traits::VtableAutoImpl(..) |
|
||||
traits::VtableParam(..) |
|
||||
traits::VtableTraitAlias(..) => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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),
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
|
@ -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 ";"
|
||||
|
65
src/test/run-pass/traits/trait-alias-bounds.rs
Normal file
65
src/test/run-pass/traits/trait-alias-bounds.rs
Normal 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>();
|
||||
}
|
27
src/test/run-pass/traits/trait-alias-object-type.rs
Normal file
27
src/test/run-pass/traits/trait-alias-object-type.rs
Normal 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));
|
||||
}
|
32
src/test/run-pass/traits/trait-alias-syntax.rs
Normal file
32
src/test/run-pass/traits/trait-alias-syntax.rs
Normal 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() {}
|
@ -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
|
||||
|
||||
|
13
src/test/ui/feature-gates/feature-gate-trait-alias.rs
Normal file
13
src/test/ui/feature-gates/feature-gate-trait-alias.rs
Normal 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() {}
|
11
src/test/ui/feature-gates/feature-gate-trait-alias.stderr
Normal file
11
src/test/ui/feature-gates/feature-gate-trait-alias.stderr
Normal 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`.
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
17
src/test/ui/traits/trait-alias-impl.rs
Normal file
17
src/test/ui/traits/trait-alias-impl.rs
Normal 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() {}
|
9
src/test/ui/traits/trait-alias-impl.stderr
Normal file
9
src/test/ui/traits/trait-alias-impl.stderr
Normal 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`.
|
19
src/test/ui/traits/trait-alias-objects.rs
Normal file
19
src/test/ui/traits/trait-alias-objects.rs
Normal 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();
|
||||
}
|
18
src/test/ui/traits/trait-alias-objects.stderr
Normal file
18
src/test/ui/traits/trait-alias-objects.stderr
Normal 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`.
|
17
src/test/ui/traits/trait-alias-wf.rs
Normal file
17
src/test/ui/traits/trait-alias-wf.rs
Normal 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() {}
|
16
src/test/ui/traits/trait-alias-wf.stderr
Normal file
16
src/test/ui/traits/trait-alias-wf.stderr
Normal 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`.
|
@ -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);
|
||||
}
|
||||
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user