about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIvan Tham <pickfire@riseup.net>2020-12-08 00:32:13 +0800
committerIvan Tham <pickfire@riseup.net>2021-03-17 09:04:08 +0800
commit21c157442c1e97745b91b8c3286ceabbc9f7be3f (patch)
tree39ecec1819bc132cf4e7dc278313a2c337172d75
parentc44a5feb0526edf44782c2c3e9012b3e408be725 (diff)
downloadrust-21c157442c1e97745b91b8c3286ceabbc9f7be3f.tar.gz
rust-21c157442c1e97745b91b8c3286ceabbc9f7be3f.zip
Add pub as optional check_front_matter
async-pub check created a regression for default
-rw-r--r--compiler/rustc_parse/src/parser/item.rs21
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs4
-rw-r--r--src/test/ui/parser/default.rs4
-rw-r--r--src/test/ui/parser/default.stderr31
-rw-r--r--src/test/ui/parser/issue-63116.stderr4
5 files changed, 39 insertions, 25 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 2dc4edf9a14..65c104bf80b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -204,6 +204,7 @@ impl<'a> Parser<'a> {
         def: &mut Defaultness,
         req_name: ReqName,
     ) -> PResult<'a, Option<ItemInfo>> {
+        let def_final = def == &Defaultness::Final;
         let mut def = || mem::replace(def, Defaultness::Final);
 
         let info = if self.eat_keyword(kw::Use) {
@@ -226,7 +227,7 @@ impl<'a> Parser<'a> {
             }
 
             (Ident::invalid(), ItemKind::Use(tree))
-        } else if self.check_fn_front_matter() {
+        } else if self.check_fn_front_matter(def_final) {
             // FUNCTION ITEM
             let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
             (ident, ItemKind::Fn(box FnKind(def(), sig, generics, body)))
@@ -1636,19 +1637,27 @@ impl<'a> Parser<'a> {
     }
 
     /// Is the current token the start of an `FnHeader` / not a valid parse?
-    pub(super) fn check_fn_front_matter(&mut self) -> bool {
+    ///
+    /// `check_pub` adds additional `pub` to the checks in case users place it
+    /// wrongly, can be used to ensure `pub` never comes after `default`.
+    pub(super) fn check_fn_front_matter(&mut self, check_pub: bool) -> bool {
         // We use an over-approximation here.
         // `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
-        // `pub` is added in case users got confused with the ordering like `async pub fn`.
-        const QUALS: [Symbol; 5] = [kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern];
+        // `pub` is added in case users got confused with the ordering like `async pub fn`,
+        // only if it wasn't preceeded by `default` as `default pub` is invalid.
+        let quals: &[Symbol] = if check_pub {
+            &[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+        } else {
+            &[kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+        };
         self.check_keyword(kw::Fn) // Definitely an `fn`.
             // `$qual fn` or `$qual $qual`:
-            || QUALS.iter().any(|&kw| self.check_keyword(kw))
+            || quals.iter().any(|&kw| self.check_keyword(kw))
                 && self.look_ahead(1, |t| {
                     // `$qual fn`, e.g. `const fn` or `async fn`.
                     t.is_keyword(kw::Fn)
                     // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`.
-                    || t.is_non_raw_ident_where(|i| QUALS.contains(&i.name)
+                    || t.is_non_raw_ident_where(|i| quals.contains(&i.name)
                         // Rule out 2015 `const async: T = val`.
                         && i.is_reserved()
                         // Rule out unsafe extern block.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 8f03bfd4c3a..0f7b8ebd376 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -209,7 +209,7 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(kw::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
-        } else if self.check_fn_front_matter() {
+        } else if self.check_fn_front_matter(false) {
             // Function pointer type
             self.parse_ty_bare_fn(lo, Vec::new(), recover_return_sign)?
         } else if self.check_keyword(kw::For) {
@@ -217,7 +217,7 @@ impl<'a> Parser<'a> {
             //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
             //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
             let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-            if self.check_fn_front_matter() {
+            if self.check_fn_front_matter(false) {
                 self.parse_ty_bare_fn(lo, lifetime_defs, recover_return_sign)?
             } else {
                 let path = self.parse_path(PathStyle::Type)?;
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index 1e31a026d94..52338c1f13a 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 // Test successful and unsuccessful parsing of the `default` contextual keyword
 
 #![feature(specialization)]
@@ -22,7 +21,8 @@ impl Foo for u16 {
 
 impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo`
     default pub fn foo<T: Default>() -> T { T::default() }
-    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
+    //~^ ERROR `default` is not followed by an item
+    //~| ERROR non-item in item list
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 489613b1e09..5b763ae72f5 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,25 +1,30 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
-  --> $DIR/default.rs:24:13
+error: `default` is not followed by an item
+  --> $DIR/default.rs:23:5
+   |
+LL |     default pub fn foo<T: Default>() -> T { T::default() }
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+error: non-item in item list
+  --> $DIR/default.rs:23:13
    |
 LL | impl Foo for u32 {
-   |                  - while parsing this item list starting here
+   |                  - item list starts here
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
-   |             ^^^
-   |             |
-   |             expected one of 7 possible tokens
-   |             help: visibility `pub` must come before `default pub`: `pub default pub`
-LL |
+   |             ^^^ non-item starts here
+...
 LL | }
-   | - the item list ends here
+   | - item list ends here
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/default.rs:18:5
+  --> $DIR/default.rs:17:5
    |
 LL |     pub default fn foo<T: Default>() -> T {
    |     ^^^ `pub` not permitted here because it's implied
 
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default.rs:4:12
+  --> $DIR/default.rs:3:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -29,7 +34,7 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
 
 error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/default.rs:23:1
+  --> $DIR/default.rs:22:1
    |
 LL |     fn foo<T: Default>() -> T;
    |     -------------------------- `foo` from trait
@@ -37,7 +42,7 @@ LL |     fn foo<T: Default>() -> T;
 LL | impl Foo for u32 {
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0046, E0449.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issue-63116.stderr
index 8d46f9c0fc4..e249a93df92 100644
--- a/src/test/ui/parser/issue-63116.stderr
+++ b/src/test/ui/parser/issue-63116.stderr
@@ -1,4 +1,4 @@
-=rror: this file contains an unclosed delimiter
+error: this file contains an unclosed delimiter
   --> $DIR/issue-63116.rs:3:18
    |
 LL | impl W <s(f;Y(;]
@@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
 LL | impl W <s(f;Y(;]
    |            ^ expected one of 7 possible tokens
 
-error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, lifetime, or path, found `;`
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `:`, `<`, `=`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
   --> $DIR/issue-63116.rs:3:15
    |
 LL | impl W <s(f;Y(;]