@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
223
223
( Ident :: empty ( ) , ItemKind :: Use ( tree) )
224
224
} else if self . check_fn_front_matter ( def_final) {
225
225
// 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 ) ) ?;
227
227
( ident, ItemKind :: Fn ( Box :: new ( Fn { defaultness : def ( ) , sig, generics, body } ) ) )
228
228
} else if self . eat_keyword ( kw:: Extern ) {
229
229
if self . eat_keyword ( kw:: Crate ) {
@@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
1513
1513
let err = if self . check_fn_front_matter ( false ) {
1514
1514
// We use `parse_fn` to get a span for the function
1515
1515
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 ) {
1517
1517
db. delay_as_bug ( ) ;
1518
1518
}
1519
1519
let mut err = self . struct_span_err (
@@ -1793,8 +1793,9 @@ impl<'a> Parser<'a> {
1793
1793
attrs : & mut Vec < Attribute > ,
1794
1794
fn_parse_mode : FnParseMode ,
1795
1795
sig_lo : Span ,
1796
+ vis : Option < & Visibility > ,
1796
1797
) -> 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`
1798
1799
let ident = self . parse_ident ( ) ?; // `foo`
1799
1800
let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
1800
1801
let decl =
@@ -1903,12 +1904,15 @@ impl<'a> Parser<'a> {
1903
1904
/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
1904
1905
/// up to and including the `fn` keyword. The formal grammar is:
1905
1906
///
1906
- /// ```
1907
+ /// ```text
1907
1908
/// Extern = "extern" StringLit? ;
1908
1909
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
1909
1910
/// FnFrontMatter = FnQual "fn" ;
1910
1911
/// ```
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 > {
1912
1916
let sp_start = self . token . span ;
1913
1917
let constness = self . parse_constness ( ) ;
1914
1918
@@ -1962,23 +1966,43 @@ impl<'a> Parser<'a> {
1962
1966
}
1963
1967
// Recover incorrect visibility order such as `async pub`.
1964
1968
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
+
1965
1975
let sp = sp_start. to ( self . prev_token . span ) ;
1966
1976
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 ) {
1968
1978
Ok ( v) => v,
1969
1979
Err ( mut d) => {
1970
1980
d. cancel ( ) ;
1971
1981
return Err ( err) ;
1972
1982
}
1973
1983
} ;
1974
- let vs = pprust:: vis_to_string ( & vis ) ;
1984
+ let vs = pprust:: vis_to_string ( & current_vis ) ;
1975
1985
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
+ }
1982
2006
}
1983
2007
}
1984
2008
return Err ( err) ;
0 commit comments