4
4
//! conflicts between multiple such attributes attached to the same
5
5
//! item.
6
6
7
- use crate :: errors;
7
+ use crate :: errors:: {
8
+ self , AttrApplication , DebugVisualizerUnreadable , InvalidAttrAtCrateLevel , ObjectLifetimeErr ,
9
+ OnlyHasEffectOn , TransparentIncompatible , UnrecognizedReprHint ,
10
+ } ;
8
11
use rustc_ast:: { ast, AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem } ;
9
12
use rustc_data_structures:: fx:: FxHashMap ;
10
- use rustc_errors:: { fluent, struct_span_err , Applicability , MultiSpan } ;
13
+ use rustc_errors:: { fluent, Applicability , MultiSpan } ;
11
14
use rustc_expand:: base:: resolve_path;
12
15
use rustc_feature:: { AttributeDuplicates , AttributeType , BuiltinAttribute , BUILTIN_ATTRIBUTE_MAP } ;
13
16
use rustc_hir as hir;
@@ -164,17 +167,17 @@ impl CheckAttrVisitor<'_> {
164
167
sym:: no_mangle => self . check_no_mangle ( hir_id, attr, span, target) ,
165
168
sym:: deprecated => self . check_deprecated ( hir_id, attr, span, target) ,
166
169
sym:: macro_use | sym:: macro_escape => self . check_macro_use ( hir_id, attr, target) ,
167
- sym:: path => self . check_generic_attr ( hir_id, attr, target, & [ Target :: Mod ] ) ,
170
+ sym:: path => self . check_generic_attr ( hir_id, attr, target, Target :: Mod ) ,
168
171
sym:: plugin_registrar => self . check_plugin_registrar ( hir_id, attr, target) ,
169
172
sym:: macro_export => self . check_macro_export ( hir_id, attr, target) ,
170
173
sym:: ignore | sym:: should_panic | sym:: proc_macro_derive => {
171
- self . check_generic_attr ( hir_id, attr, target, & [ Target :: Fn ] )
174
+ self . check_generic_attr ( hir_id, attr, target, Target :: Fn )
172
175
}
173
176
sym:: automatically_derived => {
174
- self . check_generic_attr ( hir_id, attr, target, & [ Target :: Impl ] )
177
+ self . check_generic_attr ( hir_id, attr, target, Target :: Impl )
175
178
}
176
179
sym:: no_implicit_prelude => {
177
- self . check_generic_attr ( hir_id, attr, target, & [ Target :: Mod ] )
180
+ self . check_generic_attr ( hir_id, attr, target, Target :: Mod )
178
181
}
179
182
sym:: rustc_object_lifetime_default => self . check_object_lifetime_default ( hir_id) ,
180
183
_ => { }
@@ -351,31 +354,17 @@ impl CheckAttrVisitor<'_> {
351
354
hir_id : HirId ,
352
355
attr : & Attribute ,
353
356
target : Target ,
354
- allowed_targets : & [ Target ] ,
357
+ allowed_target : Target ,
355
358
) {
356
- if !allowed_targets. iter ( ) . any ( |t| t == & target) {
357
- let name = attr. name_or_empty ( ) ;
358
- let mut i = allowed_targets. iter ( ) ;
359
- // Pluralize
360
- let b = i. next ( ) . map_or_else ( String :: new, |t| t. to_string ( ) + "s" ) ;
361
- let supported_names = i. enumerate ( ) . fold ( b, |mut b, ( i, allowed_target) | {
362
- if allowed_targets. len ( ) > 2 && i == allowed_targets. len ( ) - 2 {
363
- b. push_str ( ", and " ) ;
364
- } else if allowed_targets. len ( ) == 2 && i == allowed_targets. len ( ) - 2 {
365
- b. push_str ( " and " ) ;
366
- } else {
367
- b. push_str ( ", " ) ;
368
- }
369
- // Pluralize
370
- b. push_str ( & ( allowed_target. to_string ( ) + "s" ) ) ;
371
- b
372
- } ) ;
373
- self . tcx . struct_span_lint_hir (
359
+ if target != allowed_target {
360
+ self . tcx . emit_spanned_lint (
374
361
UNUSED_ATTRIBUTES ,
375
362
hir_id,
376
363
attr. span ,
377
- & format ! ( "`#[{name}]` only has an effect on {}" , supported_names) ,
378
- |lint| lint,
364
+ OnlyHasEffectOn {
365
+ attr_name : attr. name_or_empty ( ) ,
366
+ target_name : allowed_target. name ( ) . replace ( " " , "_" ) ,
367
+ } ,
379
368
) ;
380
369
}
381
370
}
@@ -432,7 +421,7 @@ impl CheckAttrVisitor<'_> {
432
421
ObjectLifetimeDefault :: Param ( def_id) => tcx. item_name ( def_id) . to_string ( ) ,
433
422
ObjectLifetimeDefault :: Ambiguous => "Ambiguous" . to_owned ( ) ,
434
423
} ;
435
- tcx. sess . span_err ( p. span , & repr) ;
424
+ tcx. sess . emit_err ( ObjectLifetimeErr { span : p. span , repr } ) ;
436
425
}
437
426
}
438
427
}
@@ -1605,12 +1594,17 @@ impl CheckAttrVisitor<'_> {
1605
1594
continue ;
1606
1595
}
1607
1596
1608
- let ( article , allowed_targets ) = match hint. name_or_empty ( ) {
1597
+ match hint. name_or_empty ( ) {
1609
1598
sym:: C => {
1610
1599
is_c = true ;
1611
1600
match target {
1612
1601
Target :: Struct | Target :: Union | Target :: Enum => continue ,
1613
- _ => ( "a" , "struct, enum, or union" ) ,
1602
+ _ => {
1603
+ self . tcx . sess . emit_err ( AttrApplication :: StructEnumUnion {
1604
+ hint_span : hint. span ( ) ,
1605
+ span,
1606
+ } ) ;
1607
+ }
1614
1608
}
1615
1609
}
1616
1610
sym:: align => {
@@ -1626,20 +1620,30 @@ impl CheckAttrVisitor<'_> {
1626
1620
1627
1621
match target {
1628
1622
Target :: Struct | Target :: Union | Target :: Enum | Target :: Fn => continue ,
1629
- _ => ( "a" , "struct, enum, function, or union" ) ,
1623
+ _ => {
1624
+ self . tcx . sess . emit_err ( AttrApplication :: StructEnumFunctionUnion {
1625
+ hint_span : hint. span ( ) ,
1626
+ span,
1627
+ } ) ;
1628
+ }
1630
1629
}
1631
1630
}
1632
1631
sym:: packed => {
1633
1632
if target != Target :: Struct && target != Target :: Union {
1634
- ( "a" , "struct or union" )
1633
+ self . tcx . sess . emit_err ( AttrApplication :: StructUnion {
1634
+ hint_span : hint. span ( ) ,
1635
+ span,
1636
+ } ) ;
1635
1637
} else {
1636
1638
continue ;
1637
1639
}
1638
1640
}
1639
1641
sym:: simd => {
1640
1642
is_simd = true ;
1641
1643
if target != Target :: Struct {
1642
- ( "a" , "struct" )
1644
+ self . tcx
1645
+ . sess
1646
+ . emit_err ( AttrApplication :: Struct { hint_span : hint. span ( ) , span } ) ;
1643
1647
} else {
1644
1648
continue ;
1645
1649
}
@@ -1648,7 +1652,12 @@ impl CheckAttrVisitor<'_> {
1648
1652
is_transparent = true ;
1649
1653
match target {
1650
1654
Target :: Struct | Target :: Union | Target :: Enum => continue ,
1651
- _ => ( "a" , "struct, enum, or union" ) ,
1655
+ _ => {
1656
+ self . tcx . sess . emit_err ( AttrApplication :: StructEnumUnion {
1657
+ hint_span : hint. span ( ) ,
1658
+ span,
1659
+ } ) ;
1660
+ }
1652
1661
}
1653
1662
}
1654
1663
sym:: i8
@@ -1665,35 +1674,18 @@ impl CheckAttrVisitor<'_> {
1665
1674
| sym:: usize => {
1666
1675
int_reprs += 1 ;
1667
1676
if target != Target :: Enum {
1668
- ( "an" , "enum" )
1677
+ self . tcx
1678
+ . sess
1679
+ . emit_err ( AttrApplication :: Enum { hint_span : hint. span ( ) , span } ) ;
1669
1680
} else {
1670
1681
continue ;
1671
1682
}
1672
1683
}
1673
1684
_ => {
1674
- struct_span_err ! (
1675
- self . tcx. sess,
1676
- hint. span( ) ,
1677
- E0552 ,
1678
- "unrecognized representation hint"
1679
- )
1680
- . help ( "valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
1681
- `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
1682
- . emit ( ) ;
1683
-
1685
+ self . tcx . sess . emit_err ( UnrecognizedReprHint { span : hint. span ( ) } ) ;
1684
1686
continue ;
1685
1687
}
1686
1688
} ;
1687
-
1688
- struct_span_err ! (
1689
- self . tcx. sess,
1690
- hint. span( ) ,
1691
- E0517 ,
1692
- "{}" ,
1693
- & format!( "attribute should be applied to {article} {allowed_targets}" )
1694
- )
1695
- . span_label ( span, & format ! ( "not {article} {allowed_targets}" ) )
1696
- . emit ( ) ;
1697
1689
}
1698
1690
1699
1691
// Just point at all repr hints if there are any incompatibilities.
@@ -1703,14 +1695,9 @@ impl CheckAttrVisitor<'_> {
1703
1695
// Error on repr(transparent, <anything else>).
1704
1696
if is_transparent && hints. len ( ) > 1 {
1705
1697
let hint_spans: Vec < _ > = hint_spans. clone ( ) . collect ( ) ;
1706
- struct_span_err ! (
1707
- self . tcx. sess,
1708
- hint_spans,
1709
- E0692 ,
1710
- "transparent {} cannot have other repr hints" ,
1711
- target
1712
- )
1713
- . emit ( ) ;
1698
+ self . tcx
1699
+ . sess
1700
+ . emit_err ( TransparentIncompatible { hint_spans, target : target. to_string ( ) } ) ;
1714
1701
}
1715
1702
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
1716
1703
if ( int_reprs > 1 )
@@ -1862,14 +1849,12 @@ impl CheckAttrVisitor<'_> {
1862
1849
1863
1850
match std:: fs:: File :: open ( & file) {
1864
1851
Ok ( _) => true ,
1865
- Err ( err) => {
1866
- self . tcx
1867
- . sess
1868
- . struct_span_err (
1869
- meta_item. span ,
1870
- & format ! ( "couldn't read {}: {}" , file. display( ) , err) ,
1871
- )
1872
- . emit ( ) ;
1852
+ Err ( error) => {
1853
+ self . tcx . sess . emit_err ( DebugVisualizerUnreadable {
1854
+ span : meta_item. span ,
1855
+ file : & file,
1856
+ error,
1857
+ } ) ;
1873
1858
false
1874
1859
}
1875
1860
}
@@ -2180,25 +2165,11 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
2180
2165
if attr. style == AttrStyle :: Inner {
2181
2166
for attr_to_check in ATTRS_TO_CHECK {
2182
2167
if attr. has_name ( * attr_to_check) {
2183
- let mut err = tcx. sess . struct_span_err (
2184
- attr. span ,
2185
- & format ! (
2186
- "`{}` attribute cannot be used at crate level" ,
2187
- attr_to_check. to_ident_string( )
2188
- ) ,
2189
- ) ;
2190
- // Only emit an error with a suggestion if we can create a
2191
- // string out of the attribute span
2192
- if let Ok ( src) = tcx. sess . source_map ( ) . span_to_snippet ( attr. span ) {
2193
- let replacement = src. replace ( "#!" , "#" ) ;
2194
- err. span_suggestion_verbose (
2195
- attr. span ,
2196
- "perhaps you meant to use an outer attribute" ,
2197
- replacement,
2198
- rustc_errors:: Applicability :: MachineApplicable ,
2199
- ) ;
2200
- }
2201
- err. emit ( ) ;
2168
+ tcx. sess . emit_err ( InvalidAttrAtCrateLevel {
2169
+ span : attr. span ,
2170
+ snippet : tcx. sess . source_map ( ) . span_to_snippet ( attr. span ) . ok ( ) ,
2171
+ name : * attr_to_check,
2172
+ } ) ;
2202
2173
}
2203
2174
}
2204
2175
}
0 commit comments