44//! conflicts between multiple such attributes attached to the same
55//! item.
66
7- use crate :: errors;
7+ use crate :: errors:: {
8+ self , AttrApplication , DebugVisualizerUnreadable , InvalidAttrAtCrateLevel , ObjectLifetimeErr ,
9+ OnlyHasEffectOn , TransparentIncompatible , UnrecognizedReprHint ,
10+ } ;
811use rustc_ast:: { ast, AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem } ;
912use rustc_data_structures:: fx:: FxHashMap ;
10- use rustc_errors:: { fluent, struct_span_err , Applicability , MultiSpan } ;
13+ use rustc_errors:: { fluent, Applicability , MultiSpan } ;
1114use rustc_expand:: base:: resolve_path;
1215use rustc_feature:: { AttributeDuplicates , AttributeType , BuiltinAttribute , BUILTIN_ATTRIBUTE_MAP } ;
1316use rustc_hir as hir;
@@ -164,17 +167,17 @@ impl CheckAttrVisitor<'_> {
164167 sym:: no_mangle => self . check_no_mangle ( hir_id, attr, span, target) ,
165168 sym:: deprecated => self . check_deprecated ( hir_id, attr, span, target) ,
166169 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 ) ,
168171 sym:: plugin_registrar => self . check_plugin_registrar ( hir_id, attr, target) ,
169172 sym:: macro_export => self . check_macro_export ( hir_id, attr, target) ,
170173 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 )
172175 }
173176 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 )
175178 }
176179 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 )
178181 }
179182 sym:: rustc_object_lifetime_default => self . check_object_lifetime_default ( hir_id) ,
180183 _ => { }
@@ -351,31 +354,17 @@ impl CheckAttrVisitor<'_> {
351354 hir_id : HirId ,
352355 attr : & Attribute ,
353356 target : Target ,
354- allowed_targets : & [ Target ] ,
357+ allowed_target : Target ,
355358 ) {
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 (
374361 UNUSED_ATTRIBUTES ,
375362 hir_id,
376363 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+ } ,
379368 ) ;
380369 }
381370 }
@@ -432,7 +421,7 @@ impl CheckAttrVisitor<'_> {
432421 ObjectLifetimeDefault :: Param ( def_id) => tcx. item_name ( def_id) . to_string ( ) ,
433422 ObjectLifetimeDefault :: Ambiguous => "Ambiguous" . to_owned ( ) ,
434423 } ;
435- tcx. sess . span_err ( p. span , & repr) ;
424+ tcx. sess . emit_err ( ObjectLifetimeErr { span : p. span , repr } ) ;
436425 }
437426 }
438427 }
@@ -1605,12 +1594,17 @@ impl CheckAttrVisitor<'_> {
16051594 continue ;
16061595 }
16071596
1608- let ( article , allowed_targets ) = match hint. name_or_empty ( ) {
1597+ match hint. name_or_empty ( ) {
16091598 sym:: C => {
16101599 is_c = true ;
16111600 match target {
16121601 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+ }
16141608 }
16151609 }
16161610 sym:: align => {
@@ -1626,20 +1620,30 @@ impl CheckAttrVisitor<'_> {
16261620
16271621 match target {
16281622 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+ }
16301629 }
16311630 }
16321631 sym:: packed => {
16331632 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+ } ) ;
16351637 } else {
16361638 continue ;
16371639 }
16381640 }
16391641 sym:: simd => {
16401642 is_simd = true ;
16411643 if target != Target :: Struct {
1642- ( "a" , "struct" )
1644+ self . tcx
1645+ . sess
1646+ . emit_err ( AttrApplication :: Struct { hint_span : hint. span ( ) , span } ) ;
16431647 } else {
16441648 continue ;
16451649 }
@@ -1648,7 +1652,12 @@ impl CheckAttrVisitor<'_> {
16481652 is_transparent = true ;
16491653 match target {
16501654 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+ }
16521661 }
16531662 }
16541663 sym:: i8
@@ -1665,35 +1674,18 @@ impl CheckAttrVisitor<'_> {
16651674 | sym:: usize => {
16661675 int_reprs += 1 ;
16671676 if target != Target :: Enum {
1668- ( "an" , "enum" )
1677+ self . tcx
1678+ . sess
1679+ . emit_err ( AttrApplication :: Enum { hint_span : hint. span ( ) , span } ) ;
16691680 } else {
16701681 continue ;
16711682 }
16721683 }
16731684 _ => {
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 ( ) } ) ;
16841686 continue ;
16851687 }
16861688 } ;
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 ( ) ;
16971689 }
16981690
16991691 // Just point at all repr hints if there are any incompatibilities.
@@ -1703,14 +1695,9 @@ impl CheckAttrVisitor<'_> {
17031695 // Error on repr(transparent, <anything else>).
17041696 if is_transparent && hints. len ( ) > 1 {
17051697 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 ( ) } ) ;
17141701 }
17151702 // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
17161703 if ( int_reprs > 1 )
@@ -1862,14 +1849,12 @@ impl CheckAttrVisitor<'_> {
18621849
18631850 match std:: fs:: File :: open ( & file) {
18641851 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+ } ) ;
18731858 false
18741859 }
18751860 }
@@ -2180,25 +2165,11 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
21802165 if attr. style == AttrStyle :: Inner {
21812166 for attr_to_check in ATTRS_TO_CHECK {
21822167 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+ } ) ;
22022173 }
22032174 }
22042175 }
0 commit comments