Add support for default trait impls in libsyntax

This commit is contained in:
Flavio Percoco 2015-01-22 22:14:52 +01:00
parent 2b01a37ec3
commit 6a2f16e136
8 changed files with 60 additions and 19 deletions

View File

@ -1641,6 +1641,10 @@ pub enum Item_ {
Generics, Generics,
TyParamBounds, TyParamBounds,
Vec<TraitItem>), Vec<TraitItem>),
// Default trait implementations
// `impl Trait for ..`
ItemDefTrait(Unsafety, TraitRef),
ItemImpl(Unsafety, ItemImpl(Unsafety,
ImplPolarity, ImplPolarity,
Generics, Generics,
@ -1666,7 +1670,8 @@ impl Item_ {
ItemStruct(..) => "struct", ItemStruct(..) => "struct",
ItemTrait(..) => "trait", ItemTrait(..) => "trait",
ItemMac(..) | ItemMac(..) |
ItemImpl(..) => "item" ItemImpl(..) |
ItemDefTrait(..) => "item"
} }
} }
} }

View File

@ -1044,6 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemStruct(..) => "struct", ItemStruct(..) => "struct",
ItemTrait(..) => "trait", ItemTrait(..) => "trait",
ItemImpl(..) => "impl", ItemImpl(..) => "impl",
ItemDefTrait(..) => "default impl",
ItemMac(..) => "macro" ItemMac(..) => "macro"
}; };
format!("{} {}{}", item_str, path_str, id_str) format!("{} {}{}", item_str, path_str, id_str)

View File

@ -252,8 +252,12 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime {
/// hint of where they came from, (previously they would all just be /// hint of where they came from, (previously they would all just be
/// listed as `__extensions__::method_name::hash`, with no indication /// listed as `__extensions__::method_name::hash`, with no indication
/// of the type). /// of the type).
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident { pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident {
let mut pretty = pprust::ty_to_string(ty); let mut pretty = match ty {
Some(t) => pprust::ty_to_string(t),
None => String::from_str("..")
};
match *trait_ref { match *trait_ref {
Some(ref trait_ref) => { Some(ref trait_ref) => {
pretty.push('.'); pretty.push('.');

View File

@ -498,7 +498,7 @@ impl<'a> TraitDef<'a> {
// Just mark it now since we know that it'll end up used downstream // Just mark it now since we know that it'll end up used downstream
attr::mark_used(&attr); attr::mark_used(&attr);
let opt_trait_ref = Some(trait_ref); let opt_trait_ref = Some(trait_ref);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type); let ident = ast_util::impl_pretty_name(&opt_trait_ref, Some(&*self_type));
let mut a = vec![attr]; let mut a = vec![attr];
a.extend(self.attributes.iter().cloned()); a.extend(self.attributes.iter().cloned());
cx.item( cx.item(

View File

@ -999,6 +999,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
let struct_def = folder.fold_struct_def(struct_def); let struct_def = folder.fold_struct_def(struct_def);
ItemStruct(struct_def, folder.fold_generics(generics)) ItemStruct(struct_def, folder.fold_generics(generics))
} }
ItemDefTrait(unsafety, ref trait_ref) => {
ItemDefTrait(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
}
ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
let new_impl_items = impl_items.into_iter().flat_map(|item| { let new_impl_items = impl_items.into_iter().flat_map(|item| {
folder.fold_impl_item(item).into_iter() folder.fold_impl_item(item).into_iter()
@ -1150,7 +1153,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
let ident = match node { let ident = match node {
// The node may have changed, recompute the "pretty" impl name. // The node may have changed, recompute the "pretty" impl name.
ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
ast_util::impl_pretty_name(maybe_trait, &**ty) ast_util::impl_pretty_name(maybe_trait, Some(&**ty))
} }
_ => ident _ => ident
}; };

View File

@ -31,7 +31,7 @@ use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefTrait};
use ast::{ItemExternCrate, ItemUse}; use ast::{ItemExternCrate, ItemUse};
use ast::{LifetimeDef, Lit, Lit_}; use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitBool, LitChar, LitByte, LitBinary};
@ -4783,10 +4783,13 @@ impl<'a> Parser<'a> {
(impl_items, inner_attrs) (impl_items, inner_attrs)
} }
/// Parses two variants (with the region/type params always optional): /// Parses items implementations variants
/// impl<T> Foo { ... } /// impl<T> Foo { ... }
/// impl<T> ToString for ~[T] { ... } /// impl<T> ToString for &'static T { ... }
/// impl Send for .. {}
fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
let impl_span = self.span;
// First, parse type parameters if necessary. // First, parse type parameters if necessary.
let mut generics = self.parse_generics(); let mut generics = self.parse_generics();
@ -4807,7 +4810,7 @@ impl<'a> Parser<'a> {
// Parse traits, if necessary. // Parse traits, if necessary.
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
// New-style trait. Reinterpret the type as a trait. // New-style trait. Reinterpret the type as a trait.
let opt_trait_ref = match ty.node { match ty.node {
TyPath(ref path, node_id) => { TyPath(ref path, node_id) => {
Some(TraitRef { Some(TraitRef {
path: (*path).clone(), path: (*path).clone(),
@ -4818,10 +4821,7 @@ impl<'a> Parser<'a> {
self.span_err(ty.span, "not a trait"); self.span_err(ty.span, "not a trait");
None None
} }
}; }
ty = self.parse_ty_sum();
opt_trait_ref
} else { } else {
match polarity { match polarity {
ast::ImplPolarity::Negative => { ast::ImplPolarity::Negative => {
@ -4834,14 +4834,27 @@ impl<'a> Parser<'a> {
None None
}; };
self.parse_where_clause(&mut generics); if self.eat(&token::DotDot) {
let (impl_items, attrs) = self.parse_impl_items(); if generics.is_parameterized() {
self.span_err(impl_span, "default trait implementations are not \
allowed to have genercis");
}
let ident = ast_util::impl_pretty_name(&opt_trait, &*ty); self.expect(&token::OpenDelim(token::Brace));
self.expect(&token::CloseDelim(token::Brace));
(ast_util::impl_pretty_name(&opt_trait, None),
ItemDefTrait(unsafety, opt_trait.unwrap()), None)
} else {
if opt_trait.is_some() {
ty = self.parse_ty_sum();
}
self.parse_where_clause(&mut generics);
let (impl_items, attrs) = self.parse_impl_items();
(ident, (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)),
ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
Some(attrs)) Some(attrs))
}
} }
/// Parse a::B<String,i32> /// Parse a::B<String,i32>

View File

@ -926,6 +926,18 @@ impl<'a> State<'a> {
try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
} }
ast::ItemDefTrait(unsafety, ref trait_ref) => {
try!(self.head(""));
try!(self.print_visibility(item.vis));
try!(self.print_unsafety(unsafety));
try!(self.word_nbsp("impl"));
try!(self.print_trait_ref(trait_ref));
try!(space(&mut self.s));
try!(self.word_space("for"));
try!(self.word_space(".."));
try!(self.bopen());
try!(self.bclose(item.span));
}
ast::ItemImpl(unsafety, ast::ItemImpl(unsafety,
polarity, polarity,
ref generics, ref generics,

View File

@ -282,6 +282,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_generics(type_parameters); visitor.visit_generics(type_parameters);
walk_enum_def(visitor, enum_definition, type_parameters) walk_enum_def(visitor, enum_definition, type_parameters)
} }
ItemDefTrait(_, ref trait_ref) => {
visitor.visit_trait_ref(trait_ref)
}
ItemImpl(_, _, ItemImpl(_, _,
ref type_parameters, ref type_parameters,
ref trait_reference, ref trait_reference,