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 {
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

@ -538,9 +538,9 @@ impl<'a> PathSource<'a> {
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 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
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 {

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 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
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,
@ -948,8 +947,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
)
}
/// 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);
@ -1347,7 +1346,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
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 +1441,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
/// 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

@ -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 @@ impl Invocation {
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

@ -1532,7 +1532,7 @@ impl<'a> Parser<'a> {
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)?
}

View File

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