about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-30 18:25:44 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-12 17:54:48 +0100
commitc4bbe9cbbe9921646cdedb856e34dc951641ed96 (patch)
treec71c2d933922bb09df1c005a909463caa90be6f8
parent3eebe058e52b749d1a38926390c12900e91b0b2c (diff)
downloadrust-c4bbe9cbbe9921646cdedb856e34dc951641ed96.tar.gz
rust-c4bbe9cbbe9921646cdedb856e34dc951641ed96.zip
Alias `TraitItem` & `ImplItem`.
Allow defaultness on trait items syntactically.
-rw-r--r--src/librustc_parse/parser/item.rs6
-rw-r--r--src/librustc_passes/ast_validation.rs9
-rw-r--r--src/libsyntax/ast.rs22
-rw-r--r--src/libsyntax/mut_visit.rs3
-rw-r--r--src/libsyntax/print/pprust.rs1
-rw-r--r--src/libsyntax_expand/placeholders.rs1
-rw-r--r--src/test/ui/issues/issue-60075.stderr2
-rw-r--r--src/test/ui/parser/issue-32446.stderr4
-rw-r--r--src/test/ui/parser/macro/trait-non-item-macros.stderr4
-rw-r--r--src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr4
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs10
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr38
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-pass.rs13
13 files changed, 90 insertions, 27 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 34ef12e818c..c159fb66d50 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -714,9 +714,9 @@ impl<'a> Parser<'a> {
             id: DUMMY_NODE_ID,
             span: lo.to(self.prev_span),
             ident: name,
+            attrs,
             vis,
             defaultness,
-            attrs,
             generics,
             kind,
             tokens: None,
@@ -882,6 +882,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, TraitItem> {
         let lo = self.token.span;
         let vis = self.parse_visibility(FollowedByType::No)?;
+        let defaultness = self.parse_defaultness();
         let (name, kind, generics) = if self.eat_keyword(kw::Type) {
             self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
@@ -895,12 +896,13 @@ impl<'a> Parser<'a> {
 
         Ok(TraitItem {
             id: DUMMY_NODE_ID,
+            span: lo.to(self.prev_span),
             ident: name,
             attrs,
             vis,
+            defaultness,
             generics,
             kind,
-            span: lo.to(self.prev_span),
             tokens: None,
         })
     }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 202b6ae2f94..a078a36db7a 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -271,6 +271,14 @@ impl<'a> AstValidator<'a> {
                 forbid, and warn are the only allowed built-in attributes in function parameters")
             });
     }
+
+    fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
+        if let Defaultness::Default = defaultness {
+            self.err_handler()
+                .struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
+                .emit();
+        }
+    }
 }
 
 enum GenericPosition {
@@ -746,6 +754,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         self.invalid_visibility(&ti.vis, None);
+        self.check_defaultness(ti.span, ti.defaultness);
         visit::walk_trait_item(self, ti);
     }
 }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 92ba071a03d..964acfa92b9 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1603,25 +1603,13 @@ pub struct FnSig {
     pub decl: P<FnDecl>,
 }
 
-/// Represents an item declaration within a trait declaration,
+pub type TraitItem = ImplItem<TraitItemKind>;
+
+/// Represents the kind of an item declaration within a trait declaration,
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
 /// signature) or provided (meaning it has a default implementation).
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct TraitItem {
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    pub ident: Ident,
-
-    pub generics: Generics,
-    pub kind: TraitItemKind,
-    /// See `Item::tokens` for what this is.
-    pub tokens: Option<TokenStream>,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum TraitItemKind {
     Const(P<Ty>, Option<P<Expr>>),
     Method(FnSig, Option<P<Block>>),
@@ -1631,7 +1619,7 @@ pub enum TraitItemKind {
 
 /// Represents anything within an `impl` block.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ImplItem {
+pub struct ImplItem<K = ImplItemKind> {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
@@ -1640,7 +1628,7 @@ pub struct ImplItem {
 
     pub defaultness: Defaultness,
     pub generics: Generics,
-    pub kind: ImplItemKind,
+    pub kind: K,
     /// See `Item::tokens` for what this is.
     pub tokens: Option<TokenStream>,
 }
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index f8795d885d2..9d0a29f2951 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -939,7 +939,8 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
 pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
     -> SmallVec<[TraitItem; 1]>
 {
-    let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
+    let TraitItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
+        &mut item;
     visitor.visit_id(id);
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f0c5fb32fb1..2e3ea5e2444 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1550,6 +1550,7 @@ impl<'a> State<'a> {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(ti.span.lo());
         self.print_outer_attributes(&ti.attrs);
+        self.print_defaultness(ti.defaultness);
         match ti.kind {
             ast::TraitItemKind::Const(ref ty, ref default) => {
                 self.print_associated_const(
diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs
index faea04e691b..6057be9826a 100644
--- a/src/libsyntax_expand/placeholders.rs
+++ b/src/libsyntax_expand/placeholders.rs
@@ -53,6 +53,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
             id, span, ident, vis, attrs, generics,
             kind: ast::TraitItemKind::Macro(mac_placeholder()),
+            defaultness: ast::Defaultness::Final,
             tokens: None,
         }]),
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr
index e0b15130c33..e8ef981f515 100644
--- a/src/test/ui/issues/issue-60075.stderr
+++ b/src/test/ui/issues/issue-60075.stderr
@@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
 LL |         });
    |          ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
   --> $DIR/issue-60075.rs:6:11
    |
 LL |     fn qux() -> Option<usize> {
diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr
index 70256a59231..1a97f54160b 100644
--- a/src/test/ui/parser/issue-32446.stderr
+++ b/src/test/ui/parser/issue-32446.stderr
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
   --> $DIR/issue-32446.rs:4:11
    |
 LL | trait T { ... }
-   |           ^^^ expected one of 9 possible tokens
+   |           ^^^ expected one of 10 possible tokens
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr
index 0a433ab278e..7647ba500e0 100644
--- a/src/test/ui/parser/macro/trait-non-item-macros.stderr
+++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
+error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
   --> $DIR/trait-non-item-macros.rs:2:19
    |
 LL |     ($a:expr) => ($a)
-   |                   ^^ expected one of 8 possible tokens
+   |                   ^^ expected one of 9 possible tokens
 ...
 LL |     bah!(2);
    |     -------- in this macro invocation
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index cbaf9315e85..7e8abf22d55 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -7,11 +7,11 @@ LL | trait T {
 LL | fn main() {}
    |                                                                  ^
 
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
+error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
   --> $DIR/missing-close-brace-in-trait.rs:5:12
    |
 LL | pub(crate) struct Bar<T>();
-   |            ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
+   |            ^^^^^^ expected one of 7 possible tokens
 
 error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
   --> $DIR/missing-close-brace-in-trait.rs:1:1
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
new file mode 100644
index 00000000000..b67e30637aa
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
@@ -0,0 +1,10 @@
+fn main() {}
+
+trait X {
+    default const A: u8; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default const B: u8 = 0;  //~ ERROR `default` is only allowed on items in `impl` definitions
+    default type D; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default type C: Ord; //~ ERROR `default` is only allowed on items in `impl` definitions
+    default fn f1(); //~ ERROR `default` is only allowed on items in `impl` definitions
+    default fn f2() {} //~ ERROR `default` is only allowed on items in `impl` definitions
+}
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
new file mode 100644
index 00000000000..48b502a1506
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -0,0 +1,38 @@
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:4:5
+   |
+LL |     default const A: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:5:5
+   |
+LL |     default const B: u8 = 0;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5
+   |
+LL |     default type D;
+   |     ^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5
+   |
+LL |     default type C: Ord;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5
+   |
+LL |     default fn f1();
+   |     ^^^^^^^^^^^^^^^^
+
+error: `default` is only allowed on items in `impl` definitions
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5
+   |
+LL |     default fn f2() {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/trait-item-with-defaultness-pass.rs b/src/test/ui/parser/trait-item-with-defaultness-pass.rs
new file mode 100644
index 00000000000..a6318bd99e2
--- /dev/null
+++ b/src/test/ui/parser/trait-item-with-defaultness-pass.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+trait X {
+    default const A: u8;
+    default const B: u8 = 0;
+    default type D;
+    default type C: Ord;
+    default fn f1();
+    default fn f2() {}
+}