Added support for trait aliases as object types.
This commit is contained in:
parent
34792d9f6a
commit
90041d638b
7 changed files with 43 additions and 34 deletions
|
@ -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),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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)?
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue