diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 140e21b5d04b756cb0a1abcf4e838f74a56e3231..d57b23b8b1b920d7a9e71b6833efb8f292256af8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1641,6 +1641,10 @@ pub enum Item_ { Generics, TyParamBounds, Vec), + + // Default trait implementations + // `impl Trait for ..` + ItemDefTrait(Unsafety, TraitRef), ItemImpl(Unsafety, ImplPolarity, Generics, @@ -1666,7 +1670,8 @@ pub fn descriptive_variant(&self) -> &str { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemMac(..) | - ItemImpl(..) => "item" + ItemImpl(..) | + ItemDefTrait(..) => "item" } } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index ba08f61b5575ccef6c7817b9ddc712605b296a1e..7903a3a1bfcaebc83ee0b74d54439b4b0913d16c 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -1044,6 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemImpl(..) => "impl", + ItemDefTrait(..) => "default impl", ItemMac(..) => "macro" }; format!("{} {}{}", item_str, path_str, id_str) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f660296fcd7b6c72892ac064bf3c0963376256a0..f1228c1d36308a365d968d36ed34660fdd5d18bb 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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 /// listed as `__extensions__::method_name::hash`, with no indication /// of the type). -pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { - let mut pretty = pprust::ty_to_string(ty); +pub fn impl_pretty_name(trait_ref: &Option, ty: Option<&Ty>) -> Ident { + let mut pretty = match ty { + Some(t) => pprust::ty_to_string(t), + None => String::from_str("..") + }; + match *trait_ref { Some(ref trait_ref) => { pretty.push('.'); diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b912ed34ae0ad19c780be51cbd640736a7020053..df6b73b4c97a0988f7dbe063e0d5bb6c96e1b503 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -498,7 +498,7 @@ fn create_derived_impl(&self, // Just mark it now since we know that it'll end up used downstream attr::mark_used(&attr); 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]; a.extend(self.attributes.iter().cloned()); cx.item( diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1fb0642d24ff74fdb0665916b7a66516da204901..31e5a876374fe99bec7f2f5bd9144d86c375ed21 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -999,6 +999,9 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { let struct_def = folder.fold_struct_def(struct_def); 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) => { let new_impl_items = impl_items.into_iter().flat_map(|item| { folder.fold_impl_item(item).into_iter() @@ -1150,7 +1153,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span} let ident = match node { // The node may have changed, recompute the "pretty" impl name. ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { - ast_util::impl_pretty_name(maybe_trait, &**ty) + ast_util::impl_pretty_name(maybe_trait, Some(&**ty)) } _ => ident }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 370201e53825efef69f01d9c7313127f3a436cef..55c4afc36a547fe1f14c8a06b13c2286db83a327 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -31,7 +31,7 @@ use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; 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::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; @@ -4783,10 +4783,13 @@ fn parse_impl_items(&mut self) -> (Vec, Vec) { (impl_items, inner_attrs) } - /// Parses two variants (with the region/type params always optional): + /// Parses items implementations variants /// impl Foo { ... } - /// impl ToString for ~[T] { ... } + /// impl ToString for &'static T { ... } + /// impl Send for .. {} fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { + let impl_span = self.span; + // First, parse type parameters if necessary. let mut generics = self.parse_generics(); @@ -4807,7 +4810,7 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. - let opt_trait_ref = match ty.node { + match ty.node { TyPath(ref path, node_id) => { Some(TraitRef { path: (*path).clone(), @@ -4818,10 +4821,7 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { self.span_err(ty.span, "not a trait"); None } - }; - - ty = self.parse_ty_sum(); - opt_trait_ref + } } else { match polarity { ast::ImplPolarity::Negative => { @@ -4834,14 +4834,27 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { None }; - self.parse_where_clause(&mut generics); - let (impl_items, attrs) = self.parse_impl_items(); + if self.eat(&token::DotDot) { + 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, - ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), - Some(attrs)) + (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)), + ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), + Some(attrs)) + } } /// Parse a::B diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f26578e740120d8f33695834534ac2a6c6d15d1d..d5b17b5798b83bc6710b0cb700f0a656730a0368 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -926,6 +926,18 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { 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, polarity, ref generics, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 21cb62b0a0c112818f30308c2ec7f3888906950d..9654e7a005b37854f7cfa61d003738a36c9669b5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -282,6 +282,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_enum_def(visitor, enum_definition, type_parameters) } + ItemDefTrait(_, ref trait_ref) => { + visitor.visit_trait_ref(trait_ref) + } ItemImpl(_, _, ref type_parameters, ref trait_reference,