@@ -25,7 +25,7 @@ use crate::parse::{token, ParseSess};
25
25
use crate :: symbol:: { Symbol , kw, sym} ;
26
26
use crate :: tokenstream:: TokenTree ;
27
27
28
- use errors:: { DiagnosticBuilder , Handler } ;
28
+ use errors:: { Applicability , DiagnosticBuilder , Handler } ;
29
29
use rustc_data_structures:: fx:: FxHashMap ;
30
30
use rustc_target:: spec:: abi:: Abi ;
31
31
use syntax_pos:: { Span , DUMMY_SP } ;
@@ -1422,7 +1422,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
1422
1422
Normal ,
1423
1423
template ! (
1424
1424
Word ,
1425
- List : r#"/*opt*/ since = "version", /*opt*/ note = "reason"# ,
1425
+ List : r#"/*opt*/ since = "version", /*opt*/ note = "reason"" # ,
1426
1426
NameValueStr : "reason"
1427
1427
) ,
1428
1428
Ungated
@@ -1858,24 +1858,32 @@ impl<'a> PostExpansionVisitor<'a> {
1858
1858
1859
1859
match attr. parse_meta ( self . context . parse_sess ) {
1860
1860
Ok ( meta) => if !should_skip ( name) && !template. compatible ( & meta. node ) {
1861
+ let error_msg = format ! ( "malformed `{}` attribute input" , name) ;
1861
1862
let mut msg = "attribute must be of the form " . to_owned ( ) ;
1863
+ let mut suggestions = vec ! [ ] ;
1862
1864
let mut first = true ;
1863
1865
if template. word {
1864
1866
first = false ;
1865
- msg. push_str ( & format ! ( "`#[{}{}]`" , name, "" ) ) ;
1867
+ let code = format ! ( "#[{}]" , name) ;
1868
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1869
+ suggestions. push ( code) ;
1866
1870
}
1867
1871
if let Some ( descr) = template. list {
1868
1872
if !first {
1869
1873
msg. push_str ( " or " ) ;
1870
1874
}
1871
1875
first = false ;
1872
- msg. push_str ( & format ! ( "`#[{}({})]`" , name, descr) ) ;
1876
+ let code = format ! ( "#[{}({})]" , name, descr) ;
1877
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1878
+ suggestions. push ( code) ;
1873
1879
}
1874
1880
if let Some ( descr) = template. name_value_str {
1875
1881
if !first {
1876
1882
msg. push_str ( " or " ) ;
1877
1883
}
1878
- msg. push_str ( & format ! ( "`#[{} = \" {}\" ]`" , name, descr) ) ;
1884
+ let code = format ! ( "#[{} = \" {}\" ]" , name, descr) ;
1885
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1886
+ suggestions. push ( code) ;
1879
1887
}
1880
1888
if should_warn ( name) {
1881
1889
self . context . parse_sess . buffer_lint (
@@ -1885,7 +1893,17 @@ impl<'a> PostExpansionVisitor<'a> {
1885
1893
& msg,
1886
1894
) ;
1887
1895
} else {
1888
- self . context . parse_sess . span_diagnostic . span_err ( meta. span , & msg) ;
1896
+ self . context . parse_sess . span_diagnostic . struct_span_err ( meta. span , & error_msg)
1897
+ . span_suggestions (
1898
+ meta. span ,
1899
+ if suggestions. len ( ) == 1 {
1900
+ "must be of the form"
1901
+ } else {
1902
+ "the following are the possible correct uses"
1903
+ } ,
1904
+ suggestions. into_iter ( ) ,
1905
+ Applicability :: HasPlaceholders ,
1906
+ ) . emit ( ) ;
1889
1907
}
1890
1908
}
1891
1909
Err ( mut err) => err. emit ( ) ,
@@ -2298,6 +2316,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
2298
2316
let mut err = struct_span_err ! ( span_handler, span, E0557 , "feature has been removed" ) ;
2299
2317
if let Some ( reason) = reason {
2300
2318
err. span_note ( span, reason) ;
2319
+ } else {
2320
+ err. span_label ( span, "feature has been removed" ) ;
2301
2321
}
2302
2322
err. emit ( ) ;
2303
2323
}
@@ -2379,12 +2399,24 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
2379
2399
None => continue ,
2380
2400
} ;
2381
2401
2402
+ let bad_input = |span| {
2403
+ struct_span_err ! ( span_handler, span, E0556 , "malformed `feature` attribute input" )
2404
+ } ;
2405
+
2382
2406
for mi in list {
2383
2407
let name = match mi. ident ( ) {
2384
2408
Some ( ident) if mi. is_word ( ) => ident. name ,
2385
- _ => {
2386
- span_err ! ( span_handler, mi. span( ) , E0556 ,
2387
- "malformed feature, expected just one word" ) ;
2409
+ Some ( ident) => {
2410
+ bad_input ( mi. span ( ) ) . span_suggestion (
2411
+ mi. span ( ) ,
2412
+ "expected just one word" ,
2413
+ format ! ( "{}" , ident. name) ,
2414
+ Applicability :: MaybeIncorrect ,
2415
+ ) . emit ( ) ;
2416
+ continue
2417
+ }
2418
+ None => {
2419
+ bad_input ( mi. span ( ) ) . span_label ( mi. span ( ) , "expected just one word" ) . emit ( ) ;
2388
2420
continue
2389
2421
}
2390
2422
} ;
0 commit comments