From b88a612d9a427f4d814bddbe9002821ecf9e0980 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 10 Aug 2021 01:05:11 +0200 Subject: [PATCH 1/6] Change error for pub in fn decl if already present --- compiler/rustc_parse/src/parser/item.rs | 50 ++++++++++++++++++------- compiler/rustc_parse/src/parser/ty.rs | 3 +- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 516e301ec3ae4..ece0e6da3318a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { (Ident::empty(), ItemKind::Use(tree)) } else if self.check_fn_front_matter(def_final) { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo)?; + let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, Some(vis))?; (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> { let err = if self.check_fn_front_matter(false) { // We use `parse_fn` to get a span for the function let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; - if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo) { + if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, None) { db.delay_as_bug(); } let mut err = self.struct_span_err( @@ -1793,8 +1793,9 @@ impl<'a> Parser<'a> { attrs: &mut Vec, fn_parse_mode: FnParseMode, sig_lo: Span, + vis: Option<&Visibility>, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { - let header = self.parse_fn_front_matter()?; // `const ... fn` + let header = self.parse_fn_front_matter(vis)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` let decl = @@ -1903,12 +1904,15 @@ impl<'a> Parser<'a> { /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, /// up to and including the `fn` keyword. The formal grammar is: /// - /// ``` + /// ```text /// Extern = "extern" StringLit? ; /// FnQual = "const"? "async"? "unsafe"? Extern? ; /// FnFrontMatter = FnQual "fn" ; /// ``` - pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { + pub(super) fn parse_fn_front_matter( + &mut self, + vis: Option<&Visibility>, + ) -> PResult<'a, FnHeader> { let sp_start = self.token.span; let constness = self.parse_constness(); @@ -1962,23 +1966,43 @@ impl<'a> Parser<'a> { } // Recover incorrect visibility order such as `async pub`. else if self.check_keyword(kw::Pub) { + let orig_vis = vis.unwrap_or(&Visibility { + span: rustc_span::DUMMY_SP, + kind: VisibilityKind::Inherited, + tokens: None, + }); + let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { - let vis = match self.parse_visibility(FollowedByType::No) { + let current_vis = match self.parse_visibility(FollowedByType::No) { Ok(v) => v, Err(mut d) => { d.cancel(); return Err(err); } }; - let vs = pprust::vis_to_string(&vis); + let vs = pprust::vis_to_string(¤t_vis); let vs = vs.trim_end(); - err.span_suggestion( - sp_start.to(self.prev_token.span), - &format!("visibility `{}` must come before `{}`", vs, snippet), - format!("{} {}", vs, snippet), - Applicability::MachineApplicable, - ); + + // There was no explicit visibility + if matches!(orig_vis.kind, VisibilityKind::Inherited) { + err.span_suggestion( + sp, + &format!("visibility `{}` must come before `{}`", vs, snippet), + format!("{} {}", vs, snippet), + Applicability::MachineApplicable, + ); + } + // There was an explicit visibility + else { + err.span_suggestion( + current_vis.span, + "there is already a visibility, remove this one", + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(orig_vis.span, "explicit visibility first seen here"); + } } } return Err(err); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 9bfde0e3900da..3dbe8bf93f305 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -474,7 +474,8 @@ impl<'a> Parser<'a> { params: Vec, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, TyKind> { - let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?; + let ast::FnHeader { ext, unsafety, constness, asyncness } = + self.parse_fn_front_matter(None)?; let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness { From 5cf96e70f49badf4a3085e80658a85e19ca4edda Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 10 Aug 2021 01:36:39 +0200 Subject: [PATCH 2/6] Add tests for misplaced/duplicated pub in fn decl --- .../ui/parser/issue-87694-duplicated-pub.rs | 5 +++++ .../ui/parser/issue-87694-duplicated-pub.stderr | 17 +++++++++++++++++ src/test/ui/parser/issue-87694-misplaced-pub.rs | 5 +++++ .../ui/parser/issue-87694-misplaced-pub.stderr | 10 ++++++++++ 4 files changed, 37 insertions(+) create mode 100644 src/test/ui/parser/issue-87694-duplicated-pub.rs create mode 100644 src/test/ui/parser/issue-87694-duplicated-pub.stderr create mode 100644 src/test/ui/parser/issue-87694-misplaced-pub.rs create mode 100644 src/test/ui/parser/issue-87694-misplaced-pub.stderr diff --git a/src/test/ui/parser/issue-87694-duplicated-pub.rs b/src/test/ui/parser/issue-87694-duplicated-pub.rs new file mode 100644 index 0000000000000..cf6e463d41d03 --- /dev/null +++ b/src/test/ui/parser/issue-87694-duplicated-pub.rs @@ -0,0 +1,5 @@ +pub const pub fn test() {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~| HELP there is already a visibility, remove this one +//~| NOTE explicit visibility first seen here diff --git a/src/test/ui/parser/issue-87694-duplicated-pub.stderr b/src/test/ui/parser/issue-87694-duplicated-pub.stderr new file mode 100644 index 0000000000000..9d62c3feb5536 --- /dev/null +++ b/src/test/ui/parser/issue-87694-duplicated-pub.stderr @@ -0,0 +1,17 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-87694-duplicated-pub.rs:1:11 + | +LL | pub const pub fn test() {} + | ^^^ + | | + | expected one of `async`, `extern`, `fn`, or `unsafe` + | help: there is already a visibility, remove this one + | +note: explicit visibility first seen here + --> $DIR/issue-87694-duplicated-pub.rs:1:1 + | +LL | pub const pub fn test() {} + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-87694-misplaced-pub.rs b/src/test/ui/parser/issue-87694-misplaced-pub.rs new file mode 100644 index 0000000000000..3f824617cade1 --- /dev/null +++ b/src/test/ui/parser/issue-87694-misplaced-pub.rs @@ -0,0 +1,5 @@ +const pub fn test() {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~| HELP visibility `pub` must come before `const` +//~| SUGGESTION pub const diff --git a/src/test/ui/parser/issue-87694-misplaced-pub.stderr b/src/test/ui/parser/issue-87694-misplaced-pub.stderr new file mode 100644 index 0000000000000..ac588ad5a7748 --- /dev/null +++ b/src/test/ui/parser/issue-87694-misplaced-pub.stderr @@ -0,0 +1,10 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-87694-misplaced-pub.rs:1:7 + | +LL | const pub fn test() {} + | ----- ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` + | | + | help: visibility `pub` must come before `const`: `pub const` + +error: aborting due to previous error + From 7bc8577d99d521ea600ede94f2a8ed3bcd6eb4fb Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 10 Aug 2021 02:00:25 +0200 Subject: [PATCH 3/6] Fix broken span and related tests --- compiler/rustc_parse/src/parser/item.rs | 2 +- src/test/ui/parser/duplicate-visibility.rs | 7 +++++-- src/test/ui/parser/duplicate-visibility.stderr | 10 ++++++++-- src/test/ui/parser/issue-87694-misplaced-pub.stderr | 5 +++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ece0e6da3318a..46da8ead549e1 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1987,7 +1987,7 @@ impl<'a> Parser<'a> { // There was no explicit visibility if matches!(orig_vis.kind, VisibilityKind::Inherited) { err.span_suggestion( - sp, + sp_start.to(self.prev_token.span), &format!("visibility `{}` must come before `{}`", vs, snippet), format!("{} {}", vs, snippet), Applicability::MachineApplicable, diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 87ba230eab556..3da4dd28b6d1a 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,6 +1,9 @@ fn main() {} -extern "C" { +extern "C" { //~ NOTE while parsing this item list starting here pub pub fn foo(); //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub` -} + //~| NOTE expected one of 9 possible tokens + //~| HELP there is already a visibility, remove this one + //~| NOTE explicit visibility first seen here +} //~ NOTE the item list ends here diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index d9815fc7395b4..b289f2d0adc81 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -7,10 +7,16 @@ LL | pub pub fn foo(); | ^^^ | | | expected one of 9 possible tokens - | help: visibility `pub` must come before `pub pub`: `pub pub pub` -LL | + | help: there is already a visibility, remove this one +... LL | } | - the item list ends here + | +note: explicit visibility first seen here + --> $DIR/duplicate-visibility.rs:4:5 + | +LL | pub pub fn foo(); + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-87694-misplaced-pub.stderr b/src/test/ui/parser/issue-87694-misplaced-pub.stderr index ac588ad5a7748..94c6a29efcb3b 100644 --- a/src/test/ui/parser/issue-87694-misplaced-pub.stderr +++ b/src/test/ui/parser/issue-87694-misplaced-pub.stderr @@ -2,8 +2,9 @@ error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` --> $DIR/issue-87694-misplaced-pub.rs:1:7 | LL | const pub fn test() {} - | ----- ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` - | | + | ------^^^ + | | | + | | expected one of `async`, `extern`, `fn`, or `unsafe` | help: visibility `pub` must come before `const`: `pub const` error: aborting due to previous error From 5c9950023bf6fbd2f55a4e9e5f1a54793bcfde54 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sat, 21 Aug 2021 14:39:28 +0200 Subject: [PATCH 4/6] Suggest remove on const async const instead of const const async --- compiler/rustc_parse/src/parser/item.rs | 61 ++++++++++++++++++------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 46da8ead549e1..6ea86fe9f45d7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1938,33 +1938,62 @@ impl<'a> Parser<'a> { Ok(false) => unreachable!(), Err(mut err) => { // Qualifier keywords ordering check + enum WrongKw { + Duplicated(Span), + Misplaced(Span), + } - // This will allow the machine fix to directly place the keyword in the correct place - let current_qual_sp = if self.check_keyword(kw::Const) { - Some(async_start_sp) + // This will allow the machine fix to directly place the keyword in the correct place or to indicate + // that the keyword is already present and the second instance should be removed. + let wrong_kw = if self.check_keyword(kw::Const) { + match constness { + Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Const::No => Some(WrongKw::Misplaced(async_start_sp)), + } } else if self.check_keyword(kw::Async) { - Some(unsafe_start_sp) + match asyncness { + Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), + Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), + } } else if self.check_keyword(kw::Unsafe) { - Some(ext_start_sp) + match unsafety { + Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), + } } else { None }; - if let Some(current_qual_sp) = current_qual_sp { - let current_qual_sp = current_qual_sp.to(self.prev_token.span); - if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) { - let invalid_qual_sp = self.token.uninterpolated_span(); - let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap(); + // The keyword is already present, suggest removal of the second instance + if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw { + let original_kw = self + .span_to_snippet(original_sp) + .expect("Span extracted directly from keyword should always work"); + + err.span_suggestion( + self.token.uninterpolated_span(), + &format!("`{}` already used earlier, remove this one", original_kw), + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(original_sp, &format!("`{}` first seen here", original_kw)); + } + // The keyword has not been seen yet, suggest correct placement in the function front matter + else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw { + let correct_pos_sp = correct_pos_sp.to(self.prev_token.span); + if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) { + let misplaced_qual_sp = self.token.uninterpolated_span(); + let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap(); err.span_suggestion( - current_qual_sp.to(invalid_qual_sp), - &format!("`{}` must come before `{}`", invalid_qual, current_qual), - format!("{} {}", invalid_qual, current_qual), - Applicability::MachineApplicable, - ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); + correct_pos_sp.to(misplaced_qual_sp), + &format!("`{}` must come before `{}`", misplaced_qual, current_qual), + format!("{} {}", misplaced_qual, current_qual), + Applicability::MachineApplicable, + ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); } } - // Recover incorrect visibility order such as `async pub`. + // Recover incorrect visibility order such as `async pub` else if self.check_keyword(kw::Pub) { let orig_vis = vis.unwrap_or(&Visibility { span: rustc_span::DUMMY_SP, From b0806b2de9a737e1b4821a4c163b29dcac088ce8 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 24 Oct 2021 15:11:11 +0200 Subject: [PATCH 5/6] Update test to new error message --- compiler/rustc_parse/src/parser/item.rs | 2 +- src/test/ui/parser/duplicate-visibility.rs | 2 +- src/test/ui/parser/duplicate-visibility.stderr | 2 +- src/test/ui/parser/issue-87694-duplicated-pub.rs | 2 +- .../ui/parser/issue-87694-duplicated-pub.stderr | 2 +- .../const-async-const.rs | 8 +++----- .../const-async-const.stderr | 16 ++++++++++------ 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6ea86fe9f45d7..f8b313cd0e9ec 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2026,7 +2026,7 @@ impl<'a> Parser<'a> { else { err.span_suggestion( current_vis.span, - "there is already a visibility, remove this one", + "there is already a visibility modifier, remove one", "".to_string(), Applicability::MachineApplicable, ) diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 3da4dd28b6d1a..32aeee294728a 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -4,6 +4,6 @@ extern "C" { //~ NOTE while parsing this item list starting here pub pub fn foo(); //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub` //~| NOTE expected one of 9 possible tokens - //~| HELP there is already a visibility, remove this one + //~| HELP there is already a visibility modifier, remove one //~| NOTE explicit visibility first seen here } //~ NOTE the item list ends here diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index b289f2d0adc81..97144ac2f642d 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -7,7 +7,7 @@ LL | pub pub fn foo(); | ^^^ | | | expected one of 9 possible tokens - | help: there is already a visibility, remove this one + | help: there is already a visibility modifier, remove one ... LL | } | - the item list ends here diff --git a/src/test/ui/parser/issue-87694-duplicated-pub.rs b/src/test/ui/parser/issue-87694-duplicated-pub.rs index cf6e463d41d03..e3ea61dc4ada6 100644 --- a/src/test/ui/parser/issue-87694-duplicated-pub.rs +++ b/src/test/ui/parser/issue-87694-duplicated-pub.rs @@ -1,5 +1,5 @@ pub const pub fn test() {} //~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` //~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` -//~| HELP there is already a visibility, remove this one +//~| HELP there is already a visibility modifier, remove one //~| NOTE explicit visibility first seen here diff --git a/src/test/ui/parser/issue-87694-duplicated-pub.stderr b/src/test/ui/parser/issue-87694-duplicated-pub.stderr index 9d62c3feb5536..8d242bc9de585 100644 --- a/src/test/ui/parser/issue-87694-duplicated-pub.stderr +++ b/src/test/ui/parser/issue-87694-duplicated-pub.stderr @@ -5,7 +5,7 @@ LL | pub const pub fn test() {} | ^^^ | | | expected one of `async`, `extern`, `fn`, or `unsafe` - | help: there is already a visibility, remove this one + | help: there is already a visibility modifier, remove one | note: explicit visibility first seen here --> $DIR/issue-87694-duplicated-pub.rs:1:1 diff --git a/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index 7c3d915a4c0d9..df0cd54399a53 100644 --- a/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -1,11 +1,9 @@ // edition:2018 -// Test that even when `const` is already present, the proposed fix is `const const async`, -// like for `pub pub`. +// Test that even when `const` is already present, the proposed fix is to remove the second `const` const async const fn test() {} //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` //~| NOTE expected one of `extern`, `fn`, or `unsafe` -//~| HELP `const` must come before `async` -//~| SUGGESTION const async -//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern` +//~| HELP `const` already used earlier, remove this one +//~| NOTE `const` first seen here diff --git a/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr index 56280912540a7..977c6ebfef352 100644 --- a/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr +++ b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr @@ -1,13 +1,17 @@ error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` - --> $DIR/const-async-const.rs:6:13 + --> $DIR/const-async-const.rs:5:13 | LL | const async const fn test() {} - | ------^^^^^ - | | | - | | expected one of `extern`, `fn`, or `unsafe` - | help: `const` must come before `async`: `const async` + | ^^^^^ + | | + | expected one of `extern`, `fn`, or `unsafe` + | help: `const` already used earlier, remove this one | - = note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern` +note: `const` first seen here + --> $DIR/const-async-const.rs:5:1 + | +LL | const async const fn test() {} + | ^^^^^ error: aborting due to previous error From be33ca7d5b9c79a649ff4c38e0d351df326ff93c Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Mon, 13 Dec 2021 22:41:42 +0100 Subject: [PATCH 6/6] Use Inherited Visibility instead of None when no vis is present --- compiler/rustc_parse/src/parser/item.rs | 27 +++++++++++++------------ compiler/rustc_parse/src/parser/ty.rs | 7 ++++++- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f8b313cd0e9ec..618aa3fd002a8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { (Ident::empty(), ItemKind::Use(tree)) } else if self.check_fn_front_matter(def_final) { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, Some(vis))?; + let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?; (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -1511,9 +1511,16 @@ impl<'a> Parser<'a> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { let err = if self.check_fn_front_matter(false) { + let inherited_vis = Visibility { + span: rustc_span::DUMMY_SP, + kind: VisibilityKind::Inherited, + tokens: None, + }; // We use `parse_fn` to get a span for the function let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; - if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, None) { + if let Err(mut db) = + self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis) + { db.delay_as_bug(); } let mut err = self.struct_span_err( @@ -1793,7 +1800,7 @@ impl<'a> Parser<'a> { attrs: &mut Vec, fn_parse_mode: FnParseMode, sig_lo: Span, - vis: Option<&Visibility>, + vis: &Visibility, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { let header = self.parse_fn_front_matter(vis)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` @@ -1909,10 +1916,10 @@ impl<'a> Parser<'a> { /// FnQual = "const"? "async"? "unsafe"? Extern? ; /// FnFrontMatter = FnQual "fn" ; /// ``` - pub(super) fn parse_fn_front_matter( - &mut self, - vis: Option<&Visibility>, - ) -> PResult<'a, FnHeader> { + /// + /// `vis` represents the visibility that was already parsed, if any. Use + /// `Visibility::Inherited` when no visibility is known. + pub(super) fn parse_fn_front_matter(&mut self, orig_vis: &Visibility) -> PResult<'a, FnHeader> { let sp_start = self.token.span; let constness = self.parse_constness(); @@ -1995,12 +2002,6 @@ impl<'a> Parser<'a> { } // Recover incorrect visibility order such as `async pub` else if self.check_keyword(kw::Pub) { - let orig_vis = vis.unwrap_or(&Visibility { - span: rustc_span::DUMMY_SP, - kind: VisibilityKind::Inherited, - tokens: None, - }); - let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { let current_vis = match self.parse_visibility(FollowedByType::No) { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 3dbe8bf93f305..02a774ba1291c 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -474,8 +474,13 @@ impl<'a> Parser<'a> { params: Vec, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, TyKind> { + let inherited_vis = rustc_ast::Visibility { + span: rustc_span::DUMMY_SP, + kind: rustc_ast::VisibilityKind::Inherited, + tokens: None, + }; let ast::FnHeader { ext, unsafety, constness, asyncness } = - self.parse_fn_front_matter(None)?; + self.parse_fn_front_matter(&inherited_vis)?; let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness {