@@ -1938,33 +1938,62 @@ impl<'a> Parser<'a> {
1938
1938
Ok ( false ) => unreachable ! ( ) ,
1939
1939
Err ( mut err) => {
1940
1940
// Qualifier keywords ordering check
1941
+ enum WrongKw {
1942
+ Duplicated ( Span ) ,
1943
+ Misplaced ( Span ) ,
1944
+ }
1941
1945
1942
- // This will allow the machine fix to directly place the keyword in the correct place
1943
- let current_qual_sp = if self . check_keyword ( kw:: Const ) {
1944
- Some ( async_start_sp)
1946
+ // This will allow the machine fix to directly place the keyword in the correct place or to indicate
1947
+ // that the keyword is already present and the second instance should be removed.
1948
+ let wrong_kw = if self . check_keyword ( kw:: Const ) {
1949
+ match constness {
1950
+ Const :: Yes ( sp) => Some ( WrongKw :: Duplicated ( sp) ) ,
1951
+ Const :: No => Some ( WrongKw :: Misplaced ( async_start_sp) ) ,
1952
+ }
1945
1953
} else if self . check_keyword ( kw:: Async ) {
1946
- Some ( unsafe_start_sp)
1954
+ match asyncness {
1955
+ Async :: Yes { span, .. } => Some ( WrongKw :: Duplicated ( span) ) ,
1956
+ Async :: No => Some ( WrongKw :: Misplaced ( unsafe_start_sp) ) ,
1957
+ }
1947
1958
} else if self . check_keyword ( kw:: Unsafe ) {
1948
- Some ( ext_start_sp)
1959
+ match unsafety {
1960
+ Unsafe :: Yes ( sp) => Some ( WrongKw :: Duplicated ( sp) ) ,
1961
+ Unsafe :: No => Some ( WrongKw :: Misplaced ( ext_start_sp) ) ,
1962
+ }
1949
1963
} else {
1950
1964
None
1951
1965
} ;
1952
1966
1953
- if let Some ( current_qual_sp) = current_qual_sp {
1954
- let current_qual_sp = current_qual_sp. to ( self . prev_token . span ) ;
1955
- if let Ok ( current_qual) = self . span_to_snippet ( current_qual_sp) {
1956
- let invalid_qual_sp = self . token . uninterpolated_span ( ) ;
1957
- let invalid_qual = self . span_to_snippet ( invalid_qual_sp) . unwrap ( ) ;
1967
+ // The keyword is already present, suggest removal of the second instance
1968
+ if let Some ( WrongKw :: Duplicated ( original_sp) ) = wrong_kw {
1969
+ let original_kw = self
1970
+ . span_to_snippet ( original_sp)
1971
+ . expect ( "Span extracted directly from keyword should always work" ) ;
1972
+
1973
+ err. span_suggestion (
1974
+ self . token . uninterpolated_span ( ) ,
1975
+ & format ! ( "`{}` already used earlier, remove this one" , original_kw) ,
1976
+ "" . to_string ( ) ,
1977
+ Applicability :: MachineApplicable ,
1978
+ )
1979
+ . span_note ( original_sp, & format ! ( "`{}` first seen here" , original_kw) ) ;
1980
+ }
1981
+ // The keyword has not been seen yet, suggest correct placement in the function front matter
1982
+ else if let Some ( WrongKw :: Misplaced ( correct_pos_sp) ) = wrong_kw {
1983
+ let correct_pos_sp = correct_pos_sp. to ( self . prev_token . span ) ;
1984
+ if let Ok ( current_qual) = self . span_to_snippet ( correct_pos_sp) {
1985
+ let misplaced_qual_sp = self . token . uninterpolated_span ( ) ;
1986
+ let misplaced_qual = self . span_to_snippet ( misplaced_qual_sp) . unwrap ( ) ;
1958
1987
1959
1988
err. span_suggestion (
1960
- current_qual_sp . to ( invalid_qual_sp ) ,
1961
- & format ! ( "`{}` must come before `{}`" , invalid_qual , current_qual) ,
1962
- format ! ( "{} {}" , invalid_qual , current_qual) ,
1963
- Applicability :: MachineApplicable ,
1964
- ) . note ( "keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`" ) ;
1989
+ correct_pos_sp . to ( misplaced_qual_sp ) ,
1990
+ & format ! ( "`{}` must come before `{}`" , misplaced_qual , current_qual) ,
1991
+ format ! ( "{} {}" , misplaced_qual , current_qual) ,
1992
+ Applicability :: MachineApplicable ,
1993
+ ) . note ( "keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`" ) ;
1965
1994
}
1966
1995
}
1967
- // Recover incorrect visibility order such as `async pub`.
1996
+ // Recover incorrect visibility order such as `async pub`
1968
1997
else if self . check_keyword ( kw:: Pub ) {
1969
1998
let orig_vis = vis. unwrap_or ( & Visibility {
1970
1999
span : rustc_span:: DUMMY_SP ,
0 commit comments