@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
223223 ( Ident :: empty ( ) , ItemKind :: Use ( tree) )
224224 } else if self . check_fn_front_matter ( def_final) {
225225 // FUNCTION ITEM
226- let ( ident, sig, generics, body) = self . parse_fn ( attrs, fn_parse_mode, lo) ?;
226+ let ( ident, sig, generics, body) = self . parse_fn ( attrs, fn_parse_mode, lo, Some ( vis ) ) ?;
227227 ( ident, ItemKind :: Fn ( Box :: new ( Fn { defaultness : def ( ) , sig, generics, body } ) ) )
228228 } else if self . eat_keyword ( kw:: Extern ) {
229229 if self . eat_keyword ( kw:: Crate ) {
@@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
15131513 let err = if self . check_fn_front_matter ( false ) {
15141514 // We use `parse_fn` to get a span for the function
15151515 let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
1516- if let Err ( mut db) = self . parse_fn ( & mut Vec :: new ( ) , fn_parse_mode, lo) {
1516+ if let Err ( mut db) = self . parse_fn ( & mut Vec :: new ( ) , fn_parse_mode, lo, None ) {
15171517 db. delay_as_bug ( ) ;
15181518 }
15191519 let mut err = self . struct_span_err (
@@ -1793,8 +1793,9 @@ impl<'a> Parser<'a> {
17931793 attrs : & mut Vec < Attribute > ,
17941794 fn_parse_mode : FnParseMode ,
17951795 sig_lo : Span ,
1796+ vis : Option < & Visibility > ,
17961797 ) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < Block > > ) > {
1797- let header = self . parse_fn_front_matter ( ) ?; // `const ... fn`
1798+ let header = self . parse_fn_front_matter ( vis ) ?; // `const ... fn`
17981799 let ident = self . parse_ident ( ) ?; // `foo`
17991800 let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
18001801 let decl =
@@ -1903,12 +1904,15 @@ impl<'a> Parser<'a> {
19031904 /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
19041905 /// up to and including the `fn` keyword. The formal grammar is:
19051906 ///
1906- /// ```
1907+ /// ```text
19071908 /// Extern = "extern" StringLit? ;
19081909 /// FnQual = "const"? "async"? "unsafe"? Extern? ;
19091910 /// FnFrontMatter = FnQual "fn" ;
19101911 /// ```
1911- pub ( super ) fn parse_fn_front_matter ( & mut self ) -> PResult < ' a , FnHeader > {
1912+ pub ( super ) fn parse_fn_front_matter (
1913+ & mut self ,
1914+ vis : Option < & Visibility > ,
1915+ ) -> PResult < ' a , FnHeader > {
19121916 let sp_start = self . token . span ;
19131917 let constness = self . parse_constness ( ) ;
19141918
@@ -1962,23 +1966,43 @@ impl<'a> Parser<'a> {
19621966 }
19631967 // Recover incorrect visibility order such as `async pub`.
19641968 else if self . check_keyword ( kw:: Pub ) {
1969+ let orig_vis = vis. unwrap_or ( & Visibility {
1970+ span : rustc_span:: DUMMY_SP ,
1971+ kind : VisibilityKind :: Inherited ,
1972+ tokens : None ,
1973+ } ) ;
1974+
19651975 let sp = sp_start. to ( self . prev_token . span ) ;
19661976 if let Ok ( snippet) = self . span_to_snippet ( sp) {
1967- let vis = match self . parse_visibility ( FollowedByType :: No ) {
1977+ let current_vis = match self . parse_visibility ( FollowedByType :: No ) {
19681978 Ok ( v) => v,
19691979 Err ( mut d) => {
19701980 d. cancel ( ) ;
19711981 return Err ( err) ;
19721982 }
19731983 } ;
1974- let vs = pprust:: vis_to_string ( & vis ) ;
1984+ let vs = pprust:: vis_to_string ( & current_vis ) ;
19751985 let vs = vs. trim_end ( ) ;
1976- err. span_suggestion (
1977- sp_start. to ( self . prev_token . span ) ,
1978- & format ! ( "visibility `{}` must come before `{}`" , vs, snippet) ,
1979- format ! ( "{} {}" , vs, snippet) ,
1980- Applicability :: MachineApplicable ,
1981- ) ;
1986+
1987+ // There was no explicit visibility
1988+ if matches ! ( orig_vis. kind, VisibilityKind :: Inherited ) {
1989+ err. span_suggestion (
1990+ sp,
1991+ & format ! ( "visibility `{}` must come before `{}`" , vs, snippet) ,
1992+ format ! ( "{} {}" , vs, snippet) ,
1993+ Applicability :: MachineApplicable ,
1994+ ) ;
1995+ }
1996+ // There was an explicit visibility
1997+ else {
1998+ err. span_suggestion (
1999+ current_vis. span ,
2000+ "there is already a visibility, remove this one" ,
2001+ "" . to_string ( ) ,
2002+ Applicability :: MachineApplicable ,
2003+ )
2004+ . span_note ( orig_vis. span , "explicit visibility first seen here" ) ;
2005+ }
19822006 }
19832007 }
19842008 return Err ( err) ;
0 commit comments