diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1acaa4c6eff5d..cb9c0578e8d49 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -104,7 +104,7 @@ impl CheckAttrVisitor<'tcx> { return; } - if matches!(target, Target::Fn | Target::Method(_) | Target::ForeignFn) { + if matches!(target, Target::Closure | Target::Fn | Target::Method(_) | Target::ForeignFn) { self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id)); } @@ -195,7 +195,7 @@ impl CheckAttrVisitor<'tcx> { /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid. fn check_non_exhaustive(&self, attr: &Attribute, span: &Span, target: Target) -> bool { match target { - Target::Struct | Target::Enum => true, + Target::Struct | Target::Enum | Target::Variant => true, _ => { struct_span_err!( self.tcx.sess, @@ -587,6 +587,9 @@ impl CheckAttrVisitor<'tcx> { for hint in &hints { let (article, allowed_targets) = match hint.name_or_empty() { + _ if !matches!(target, Target::Struct | Target::Enum | Target::Union) => { + ("a", "struct, enum, or union") + } name @ sym::C | name @ sym::align => { is_c |= name == sym::C; match target { @@ -652,12 +655,16 @@ impl CheckAttrVisitor<'tcx> { } _ => continue, }; - self.emit_repr_error( + + struct_span_err!( + self.tcx.sess, hint.span(), - *span, - &format!("attribute should be applied to {}", allowed_targets), - &format!("not {} {}", article, allowed_targets), + E0517, + "{}", + &format!("attribute should be applied to {} {}", article, allowed_targets) ) + .span_label(*span, &format!("not {} {}", article, allowed_targets)) + .emit(); } // Just point at all repr hints if there are any incompatibilities. @@ -703,56 +710,6 @@ impl CheckAttrVisitor<'tcx> { } } - fn emit_repr_error( - &self, - hint_span: Span, - label_span: Span, - hint_message: &str, - label_message: &str, - ) { - struct_span_err!(self.tcx.sess, hint_span, E0517, "{}", hint_message) - .span_label(label_span, label_message) - .emit(); - } - - fn check_stmt_attributes(&self, stmt: &hir::Stmt<'_>) { - // When checking statements ignore expressions, they will be checked later - if let hir::StmtKind::Local(ref l) = stmt.kind { - self.check_attributes(l.hir_id, &l.attrs, &stmt.span, Target::Statement, None); - for attr in l.attrs.iter() { - if self.tcx.sess.check_name(attr, sym::repr) { - self.emit_repr_error( - attr.span, - stmt.span, - "attribute should not be applied to a statement", - "not a struct, enum, or union", - ); - } - } - } - } - - fn check_expr_attributes(&self, expr: &hir::Expr<'_>) { - let target = match expr.kind { - hir::ExprKind::Closure(..) => Target::Closure, - _ => Target::Expression, - }; - self.check_attributes(expr.hir_id, &expr.attrs, &expr.span, target, None); - for attr in expr.attrs.iter() { - if self.tcx.sess.check_name(attr, sym::repr) { - self.emit_repr_error( - attr.span, - expr.span, - "attribute should not be applied to an expression", - "not defining a struct, enum, or union", - ); - } - } - if target == Target::Closure { - self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(expr.hir_id)); - } - } - fn check_used(&self, attrs: &'hir [Attribute], target: Target) { for attr in attrs { if self.tcx.sess.check_name(attr, sym::used) && target != Target::Static { @@ -808,14 +765,32 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { - self.check_stmt_attributes(stmt); + // When checking statements ignore expressions, they will be checked later. + if let hir::StmtKind::Local(ref l) = stmt.kind { + self.check_attributes(l.hir_id, &l.attrs, &stmt.span, Target::Statement, None); + } intravisit::walk_stmt(self, stmt) } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - self.check_expr_attributes(expr); + let target = match expr.kind { + hir::ExprKind::Closure(..) => Target::Closure, + _ => Target::Expression, + }; + + self.check_attributes(expr.hir_id, &expr.attrs, &expr.span, target, None); intravisit::walk_expr(self, expr) } + + fn visit_variant( + &mut self, + variant: &'tcx hir::Variant<'tcx>, + generics: &'tcx hir::Generics<'tcx>, + item_id: HirId, + ) { + self.check_attributes(variant.id, variant.attrs, &variant.span, Target::Variant, None); + intravisit::walk_variant(self, variant, generics, item_id) + } } fn is_c_like_enum(item: &Item<'_>) -> bool { diff --git a/src/test/ui/attr-usage-repr.rs b/src/test/ui/attr-usage-repr.rs index a0b82375e777d..8965decc37989 100644 --- a/src/test/ui/attr-usage-repr.rs +++ b/src/test/ui/attr-usage-repr.rs @@ -1,6 +1,6 @@ #![feature(repr_simd)] -#[repr(C)] //~ ERROR: attribute should be applied to struct, enum, or union +#[repr(C)] //~ ERROR: attribute should be applied to a struct, enum, or union fn f() {} #[repr(C)] @@ -12,7 +12,7 @@ struct SPacked(f64, f64); #[repr(simd)] struct SSimd(f64, f64); -#[repr(i8)] //~ ERROR: attribute should be applied to enum +#[repr(i8)] //~ ERROR: attribute should be applied to an enum struct SInt(f64, f64); #[repr(C)] @@ -21,10 +21,10 @@ enum EExtern { A, B } #[repr(align(8))] enum EAlign { A, B } -#[repr(packed)] //~ ERROR: attribute should be applied to struct +#[repr(packed)] //~ ERROR: attribute should be applied to a struct enum EPacked { A, B } -#[repr(simd)] //~ ERROR: attribute should be applied to struct +#[repr(simd)] //~ ERROR: attribute should be applied to a struct enum ESimd { A, B } #[repr(i8)] diff --git a/src/test/ui/attr-usage-repr.stderr b/src/test/ui/attr-usage-repr.stderr index 82d80d8d0b173..42f65625a466f 100644 --- a/src/test/ui/attr-usage-repr.stderr +++ b/src/test/ui/attr-usage-repr.stderr @@ -1,4 +1,4 @@ -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/attr-usage-repr.rs:3:8 | LL | #[repr(C)] @@ -6,7 +6,7 @@ LL | #[repr(C)] LL | fn f() {} | --------- not a struct, enum, or union -error[E0517]: attribute should be applied to enum +error[E0517]: attribute should be applied to an enum --> $DIR/attr-usage-repr.rs:15:8 | LL | #[repr(i8)] @@ -14,7 +14,7 @@ LL | #[repr(i8)] LL | struct SInt(f64, f64); | ---------------------- not an enum -error[E0517]: attribute should be applied to struct or union +error[E0517]: attribute should be applied to a struct or union --> $DIR/attr-usage-repr.rs:24:8 | LL | #[repr(packed)] @@ -22,7 +22,7 @@ LL | #[repr(packed)] LL | enum EPacked { A, B } | --------------------- not a struct or union -error[E0517]: attribute should be applied to struct +error[E0517]: attribute should be applied to a struct --> $DIR/attr-usage-repr.rs:27:8 | LL | #[repr(simd)] diff --git a/src/test/ui/error-codes/E0517.stderr b/src/test/ui/error-codes/E0517.stderr index 2cfca1724c81b..2f90d4d0baa5e 100644 --- a/src/test/ui/error-codes/E0517.stderr +++ b/src/test/ui/error-codes/E0517.stderr @@ -1,4 +1,4 @@ -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/E0517.rs:1:8 | LL | #[repr(C)] @@ -6,7 +6,7 @@ LL | #[repr(C)] LL | type Foo = u8; | -------------- not a struct, enum, or union -error[E0517]: attribute should be applied to struct or union +error[E0517]: attribute should be applied to a struct or union --> $DIR/E0517.rs:4:8 | LL | #[repr(packed)] @@ -14,7 +14,7 @@ LL | #[repr(packed)] LL | enum Foo2 {Bar, Baz} | -------------------- not a struct or union -error[E0517]: attribute should be applied to enum +error[E0517]: attribute should be applied to an enum --> $DIR/E0517.rs:7:8 | LL | #[repr(u8)] @@ -22,7 +22,7 @@ LL | #[repr(u8)] LL | struct Foo3 {bar: bool, baz: bool} | ---------------------------------- not an enum -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/E0517.rs:10:8 | LL | #[repr(C)] diff --git a/src/test/ui/inline-disallow-on-variant.rs b/src/test/ui/inline-disallow-on-variant.rs new file mode 100644 index 0000000000000..d92a4e8cc8df1 --- /dev/null +++ b/src/test/ui/inline-disallow-on-variant.rs @@ -0,0 +1,7 @@ +enum Foo { + #[inline] + //~^ ERROR attribute should be applied + Variant, +} + +fn main() {} diff --git a/src/test/ui/inline-disallow-on-variant.stderr b/src/test/ui/inline-disallow-on-variant.stderr new file mode 100644 index 0000000000000..1b176579bbbcf --- /dev/null +++ b/src/test/ui/inline-disallow-on-variant.stderr @@ -0,0 +1,12 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-disallow-on-variant.rs:2:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | +LL | Variant, + | ------- not a function or closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0518`. diff --git a/src/test/ui/issues/issue-31769.rs b/src/test/ui/issues/issue-31769.rs index 45eb5e4008089..f56c6ea565685 100644 --- a/src/test/ui/issues/issue-31769.rs +++ b/src/test/ui/issues/issue-31769.rs @@ -1,4 +1,4 @@ fn main() { #[inline] struct Foo; //~ ERROR attribute should be applied to function or closure - #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum, or union + #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to a struct, enum, or union } diff --git a/src/test/ui/issues/issue-31769.stderr b/src/test/ui/issues/issue-31769.stderr index 20534e1ae82c5..03e2f931c847b 100644 --- a/src/test/ui/issues/issue-31769.stderr +++ b/src/test/ui/issues/issue-31769.stderr @@ -4,7 +4,7 @@ error[E0518]: attribute should be applied to function or closure LL | #[inline] struct Foo; | ^^^^^^^^^ ----------- not a function or closure -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/issue-31769.rs:3:12 | LL | #[repr(C)] fn foo() {} diff --git a/src/test/ui/issues/issue-43988.rs b/src/test/ui/issues/issue-43988.rs index b80907560c385..4b3a0269baea2 100644 --- a/src/test/ui/issues/issue-43988.rs +++ b/src/test/ui/issues/issue-43988.rs @@ -13,18 +13,17 @@ fn main() { #[repr(nothing)] let _x = 0; - //~^^ ERROR attribute should not be applied to a statement + //~^^ ERROR attribute should be applied to a struct, enum, or union #[repr(something_not_real)] loop { () }; - //~^^^^ ERROR attribute should not be applied to an expression + //~^^^^ ERROR attribute should be applied to a struct, enum, or union #[repr] let _y = "123"; - //~^^ ERROR attribute should not be applied to a statement - //~| ERROR malformed `repr` attribute + //~^^ ERROR malformed `repr` attribute fn foo() {} @@ -33,6 +32,5 @@ fn main() { //~^^ ERROR attribute should be applied to function or closure let _z = #[repr] 1; - //~^ ERROR attribute should not be applied to an expression - //~| ERROR malformed `repr` attribute + //~^ ERROR malformed `repr` attribute } diff --git a/src/test/ui/issues/issue-43988.stderr b/src/test/ui/issues/issue-43988.stderr index 37e56168c1d64..f1205d447e4ba 100644 --- a/src/test/ui/issues/issue-43988.stderr +++ b/src/test/ui/issues/issue-43988.stderr @@ -5,7 +5,7 @@ LL | #[repr] | ^^^^^^^ help: must be of the form: `#[repr(C)]` error: malformed `repr` attribute input - --> $DIR/issue-43988.rs:35:14 + --> $DIR/issue-43988.rs:34:14 | LL | let _z = #[repr] 1; | ^^^^^^^ help: must be of the form: `#[repr(C)]` @@ -26,47 +26,33 @@ LL | #[inline(XYZ)] LL | let _b = 4; | ----------- not a function or closure -error[E0517]: attribute should not be applied to a statement - --> $DIR/issue-43988.rs:14:5 +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43988.rs:14:12 | LL | #[repr(nothing)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^ LL | let _x = 0; | ----------- not a struct, enum, or union -error[E0517]: attribute should not be applied to an expression - --> $DIR/issue-43988.rs:18:5 +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43988.rs:18:12 | LL | #[repr(something_not_real)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ LL | / loop { LL | | () LL | | }; - | |_____- not defining a struct, enum, or union - -error[E0517]: attribute should not be applied to a statement - --> $DIR/issue-43988.rs:24:5 - | -LL | #[repr] - | ^^^^^^^ -LL | let _y = "123"; - | --------------- not a struct, enum, or union + | |_____- not a struct, enum, or union error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43988.rs:31:5 + --> $DIR/issue-43988.rs:30:5 | LL | #[inline(ABC)] | ^^^^^^^^^^^^^^ LL | foo(); | ----- not a function or closure -error[E0517]: attribute should not be applied to an expression - --> $DIR/issue-43988.rs:35:14 - | -LL | let _z = #[repr] 1; - | ^^^^^^^ - not defining a struct, enum, or union - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0517, E0518. For more information about an error, try `rustc --explain E0517`. diff --git a/src/test/ui/issues/issue-74082.rs b/src/test/ui/issues/issue-74082.rs index 982f8ef02538b..e3e400c79d658 100644 --- a/src/test/ui/issues/issue-74082.rs +++ b/src/test/ui/issues/issue-74082.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] -#[repr(i128)] //~ ERROR: attribute should be applied to enum +#[repr(i128)] //~ ERROR: attribute should be applied to an enum struct Foo; -#[repr(u128)] //~ ERROR: attribute should be applied to enum +#[repr(u128)] //~ ERROR: attribute should be applied to an enum struct Bar; fn main() {} diff --git a/src/test/ui/issues/issue-74082.stderr b/src/test/ui/issues/issue-74082.stderr index 08fe415513d0d..12f5a3b27bb30 100644 --- a/src/test/ui/issues/issue-74082.stderr +++ b/src/test/ui/issues/issue-74082.stderr @@ -1,4 +1,4 @@ -error[E0517]: attribute should be applied to enum +error[E0517]: attribute should be applied to an enum --> $DIR/issue-74082.rs:3:8 | LL | #[repr(i128)] @@ -6,7 +6,7 @@ LL | #[repr(i128)] LL | struct Foo; | ----------- not an enum -error[E0517]: attribute should be applied to enum +error[E0517]: attribute should be applied to an enum --> $DIR/issue-74082.rs:6:8 | LL | #[repr(u128)] diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs index f82eb338f4c68..aa8f578adf61e 100644 --- a/src/test/ui/macros/issue-68060.rs +++ b/src/test/ui/macros/issue-68060.rs @@ -3,10 +3,7 @@ fn main() { .map( #[target_feature(enable = "")] //~^ ERROR: attribute should be applied to a function - //~| ERROR: the feature named `` is not valid for this target - //~| NOTE: `` is not valid for this target #[track_caller] - //~^ ERROR: `#[track_caller]` requires Rust ABI [E0737] |_| (), //~^ NOTE: not a function ) diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr index a01c3827bb5a5..1b58cf9c4ede5 100644 --- a/src/test/ui/macros/issue-68060.stderr +++ b/src/test/ui/macros/issue-68060.stderr @@ -7,18 +7,5 @@ LL | #[target_feature(enable = "")] LL | |_| (), | ------ not a function -error: the feature named `` is not valid for this target - --> $DIR/issue-68060.rs:4:30 - | -LL | #[target_feature(enable = "")] - | ^^^^^^^^^^^ `` is not valid for this target - -error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/issue-68060.rs:8:13 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0737`. diff --git a/src/test/ui/repr/repr-disallow-on-variant.rs b/src/test/ui/repr/repr-disallow-on-variant.rs new file mode 100644 index 0000000000000..90cad7e647b05 --- /dev/null +++ b/src/test/ui/repr/repr-disallow-on-variant.rs @@ -0,0 +1,9 @@ +struct Test; + +enum Foo { + #[repr(u8)] + //~^ ERROR attribute should be applied to a struct, enum, or union + Variant, +} + +fn main() {} diff --git a/src/test/ui/repr/repr-disallow-on-variant.stderr b/src/test/ui/repr/repr-disallow-on-variant.stderr new file mode 100644 index 0000000000000..70b45e393fcf1 --- /dev/null +++ b/src/test/ui/repr/repr-disallow-on-variant.stderr @@ -0,0 +1,12 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/repr-disallow-on-variant.rs:4:12 + | +LL | #[repr(u8)] + | ^^ +LL | +LL | Variant, + | ------- not a struct, enum, or union + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0517`. diff --git a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs index 308634651a384..870eda89c20d7 100644 --- a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs +++ b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs @@ -5,10 +5,10 @@ use std::num::NonZeroU16 as N16; #[repr(no_niche)] pub union Cloaked1 { _A: N16 } -//~^^ ERROR attribute should be applied to struct or enum [E0517] +//~^^ ERROR attribute should be applied to a struct or enum [E0517] #[repr(no_niche)] pub union Cloaked2 { _A: N16, _B: (u8, N8) } -//~^^ ERROR attribute should be applied to struct or enum [E0517] +//~^^ ERROR attribute should be applied to a struct or enum [E0517] fn main() { } diff --git a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr index 4c542c5f0da64..9af929d409473 100644 --- a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr +++ b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr @@ -1,4 +1,4 @@ -error[E0517]: attribute should be applied to struct or enum +error[E0517]: attribute should be applied to a struct or enum --> $DIR/repr-no-niche-inapplicable-to-unions.rs:6:8 | LL | #[repr(no_niche)] @@ -6,7 +6,7 @@ LL | #[repr(no_niche)] LL | pub union Cloaked1 { _A: N16 } | ------------------------------ not a struct or enum -error[E0517]: attribute should be applied to struct or enum +error[E0517]: attribute should be applied to a struct or enum --> $DIR/repr-no-niche-inapplicable-to-unions.rs:10:8 | LL | #[repr(no_niche)] diff --git a/src/test/ui/repr/repr-transparent-other-items.rs b/src/test/ui/repr/repr-transparent-other-items.rs index c3d772f6266c0..e537e3e1a6365 100644 --- a/src/test/ui/repr/repr-transparent-other-items.rs +++ b/src/test/ui/repr/repr-transparent-other-items.rs @@ -1,9 +1,9 @@ // See also repr-transparent.rs -#[repr(transparent)] //~ ERROR should be applied to struct +#[repr(transparent)] //~ ERROR should be applied to a struct fn cant_repr_this() {} -#[repr(transparent)] //~ ERROR should be applied to struct +#[repr(transparent)] //~ ERROR should be applied to a struct static CANT_REPR_THIS: u32 = 0; fn main() {} diff --git a/src/test/ui/repr/repr-transparent-other-items.stderr b/src/test/ui/repr/repr-transparent-other-items.stderr index 03df3569b42bc..14e6f13e1ae44 100644 --- a/src/test/ui/repr/repr-transparent-other-items.stderr +++ b/src/test/ui/repr/repr-transparent-other-items.stderr @@ -1,4 +1,4 @@ -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/repr-transparent-other-items.rs:3:8 | LL | #[repr(transparent)] @@ -6,7 +6,7 @@ LL | #[repr(transparent)] LL | fn cant_repr_this() {} | ---------------------- not a struct, enum, or union -error[E0517]: attribute should be applied to struct, enum, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/repr-transparent-other-items.rs:6:8 | LL | #[repr(transparent)]