Added support for trait aliases as object types.

This commit is contained in:
Alexander Regueiro 2018-10-22 00:45:24 +01:00
parent 34792d9f6a
commit 90041d638b
7 changed files with 43 additions and 34 deletions

View file

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

View file

@ -538,9 +538,9 @@ impl<'a> PathSource<'a> {
match self { match self {
PathSource::Type => match def { PathSource::Type => match def {
Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) | Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
Def::Existential(..) | Def::SelfTy(..) | Def::Existential(..) |
Def::ForeignTy(..) => true, Def::ForeignTy(..) => true,
_ => false, _ => false,
}, },
@ -3122,7 +3122,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
return (err, candidates); return (err, candidates);
} }
(Def::TyAlias(..), PathSource::Trait(_)) => { (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); return (err, candidates);
} }
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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 //! representation. The main routine here is `ast_ty_to_ty()`: each use
//! is parameterized by an instance of `AstConv`. //! is parameterized by an instance of `AstConv`.
@ -181,7 +181,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
item_segment: &hir::PathSegment) item_segment: &hir::PathSegment)
-> &'tcx Substs<'tcx> -> &'tcx Substs<'tcx>
{ {
let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| { let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path( self.create_substs_for_ast_path(
span, span,
@ -948,8 +947,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
) )
} }
/// Transform a PolyTraitRef into a PolyExistentialTraitRef by /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
/// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF). /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
-> ty::ExistentialTraitRef<'tcx> { -> ty::ExistentialTraitRef<'tcx> {
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF); assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
@ -1347,7 +1346,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
err.span_label(span, "associated type not allowed here").emit(); 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, pub fn def_to_ty(&self,
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path, path: &hir::Path,
@ -1442,8 +1441,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
/// Parses the programmer's textual representation of a type into our /// Parses the programmer's textual representation of a type into our
/// internal notion of a type. /// internal notion of a type.
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})", debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})",
ast_ty.id, ast_ty); ast_ty.id, ast_ty, ast_ty.node);
let tcx = self.tcx(); let tcx = self.tcx();

View file

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

View file

@ -252,7 +252,7 @@ impl Invocation {
pub struct MacroExpander<'a, 'b:'a> { pub struct MacroExpander<'a, 'b:'a> {
pub cx: &'a mut ExtCtxt<'b>, 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> { impl<'a, 'b> MacroExpander<'a, 'b> {

View file

@ -1532,7 +1532,7 @@ impl<'a> Parser<'a> {
if maybe_bounds && bounds.len() == 1 && !trailing_plus => { if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
let path = match bounds[0] { let path = match bounds[0] {
GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), 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)? self.parse_remaining_bounds(Vec::new(), path, lo, true)?
} }

View file

@ -10,7 +10,8 @@
#![feature(trait_alias)] #![feature(trait_alias)]
trait Foo = std::fmt::Debug; type Foo = std::fmt::Debug;
type Bar = Foo;
fn foo<T: Foo>(v: &T) { fn foo<T: Foo>(v: &T) {
println!("{:?}", v); println!("{:?}", v);
@ -18,5 +19,10 @@ fn foo<T: Foo>(v: &T) {
pub fn main() { pub fn main() {
foo(&12345); foo(&12345);
let foo: &Foo = &0i32;
let bar1: &Bar = &54321;
println!("{:?}", bar1);
let bar2 = Box::new(42) as Box<dyn Foo>;
println!("{:?}", bar2);
} }