}
}
}
+ ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => {
+ for &TyParam { ref bounds, ref default, span, .. } in ty_params {
+ if !bounds.is_empty() {
+ self.err_handler().span_err(span,
+ "type parameters on the left side of a \
+ trait alias cannot be bounded");
+ }
+ if !default.is_none() {
+ self.err_handler().span_err(span,
+ "type parameters on the left side of a \
+ trait alias cannot have defaults");
+ }
+ }
+ }
ItemKind::Mod(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path");
///
/// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
+ /// Trait alias
+ ///
+ /// E.g. `trait Foo = Bar + Quux;`
+ TraitAlias(Generics, TyParamBounds),
/// Auto trait implementation.
///
/// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
ItemKind::Struct(..) => "struct",
ItemKind::Union(..) => "union",
ItemKind::Trait(..) => "trait",
+ ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Mac(..) |
ItemKind::MacroDef(..) |
ItemKind::Impl(..) |
folder.fold_bounds(bounds),
items.move_flat_map(|item| folder.fold_trait_item(item)),
),
+ ItemKind::TraitAlias(generics, bounds) => ItemKind::TraitAlias(
+ folder.fold_generics(generics),
+ folder.fold_bounds(bounds)),
ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)),
ItemKind::MacroDef(def) => ItemKind::MacroDef(folder.fold_macro_def(def)),
}
}
}
- /// Parse trait Foo { ... }
+ /// Parse `trait Foo { ... }` or `trait Foo = Bar;`
fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
let ident = self.parse_ident()?;
let mut tps = self.parse_generics()?;
Vec::new()
};
- tps.where_clause = self.parse_where_clause()?;
-
- self.expect(&token::OpenDelim(token::Brace))?;
- let mut trait_items = vec![];
- while !self.eat(&token::CloseDelim(token::Brace)) {
- let mut at_end = false;
- match self.parse_trait_item(&mut at_end) {
- Ok(item) => trait_items.push(item),
- Err(mut e) => {
- e.emit();
- if !at_end {
- self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+ if self.eat(&token::Eq) {
+ // it's a trait alias
+ let bounds = self.parse_ty_param_bounds()?;
+ tps.where_clause = self.parse_where_clause()?;
+ self.expect(&token::Semi)?;
+ if unsafety != Unsafety::Normal {
+ self.span_err(self.prev_span, "trait aliases cannot be unsafe");
+ }
+ Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
+ } else {
+ // it's a normal trait
+ tps.where_clause = self.parse_where_clause()?;
+ self.expect(&token::OpenDelim(token::Brace))?;
+ let mut trait_items = vec![];
+ while !self.eat(&token::CloseDelim(token::Brace)) {
+ let mut at_end = false;
+ match self.parse_trait_item(&mut at_end) {
+ Ok(item) => trait_items.push(item),
+ Err(mut e) => {
+ e.emit();
+ if !at_end {
+ self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+ }
}
}
}
+ Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
}
- Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
}
/// Parses items implementations variants
}
self.bclose(item.span)?;
}
+ ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
+ self.head("")?;
+ self.print_visibility(&item.vis)?;
+ self.word_nbsp("trait")?;
+ self.print_ident(item.ident)?;
+ self.print_generics(generics)?;
+ let mut real_bounds = Vec::with_capacity(bounds.len());
+ // FIXME(durka) this seems to be some quite outdated syntax
+ for b in bounds.iter() {
+ if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
+ self.s.space()?;
+ self.word_space("for ?")?;
+ self.print_trait_ref(&ptr.trait_ref)?;
+ } else {
+ real_bounds.push(b.clone());
+ }
+ }
+ self.print_bounds(" = ", &real_bounds[..])?;
+ self.print_where_clause(&generics.where_clause)?;
+ self.s.word(";")?;
+ }
ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
self.print_path(&node.path, false, 0, false)?;
self.s.word("! ")?;
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_trait_item, methods);
}
+ ItemKind::TraitAlias(ref generics, ref bounds) => {
+ visitor.visit_generics(generics);
+ walk_list!(visitor, visit_ty_param_bound, bounds);
+ }
ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Alias1<T> = Default where T: Clone; // ok
+trait Alias2<T: Clone = ()> = Default;
+ //~^ERROR type parameters on the left side of a trait alias cannot be bounded
+ //~^^ERROR type parameters on the left side of a trait alias cannot have defaults
+
+impl Alias1 { //~ERROR expected type, found trait alias
+ fn foo() {}
+}
+
+fn main() {}
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait SimpleAlias = Default;
+trait GenericAlias<T> = Iterator<Item=T>;
+trait Partial<T> = IntoIterator<Item=T>;
+
+trait Things<T> {}
+trait Romeo {}
+struct The<T>(T);
+struct Fore<T>(T);
+impl<T, U> Things<T> for The<U> {}
+impl<T> Romeo for Fore<T> {}
+
+trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
+trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
+
+trait CD = Clone + Default;
+
+fn foo<T: CD>() -> (T, T) {
+ let one = T::default();
+ let two = one.clone();
+ (one, two)
+}
+
+fn main() {
+ let both = foo();
+ assert_eq!(both.0, 0);
+ assert_eq!(both.1, 0);
+ let both: (i32, i32) = foo();
+ assert_eq!(both.0, 0);
+ assert_eq!(both.1, 0);
+}
+