1
Fork 0

Auto merge of #77015 - davidtwco:check-attr-variant-closure-expr, r=lcnr

passes: `check_attr` on more targets

This PR modifies `check_attr` so that:

- Enum variants are now checked (some attributes would not have been prohibited on variants previously).
- `check_expr_attributes` and `check_stmt_attributes` are removed as `check_attributes` can perform the same checks. This means that codegen attribute errors aren't shown if there are other errors first (e.g. from other attributes, as shown in `src/test/ui/macros/issue-68060.rs` changes below).
This commit is contained in:
bors 2020-10-23 17:32:04 +00:00
commit 7bade6ef73
20 changed files with 114 additions and 131 deletions

View file

@ -104,7 +104,7 @@ impl CheckAttrVisitor<'tcx> {
return; 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)); 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. /// 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 { fn check_non_exhaustive(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target { match target {
Target::Struct | Target::Enum => true, Target::Struct | Target::Enum | Target::Variant => true,
_ => { _ => {
struct_span_err!( struct_span_err!(
self.tcx.sess, self.tcx.sess,
@ -587,6 +587,9 @@ impl CheckAttrVisitor<'tcx> {
for hint in &hints { for hint in &hints {
let (article, allowed_targets) = match hint.name_or_empty() { 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 => { name @ sym::C | name @ sym::align => {
is_c |= name == sym::C; is_c |= name == sym::C;
match target { match target {
@ -652,12 +655,16 @@ impl CheckAttrVisitor<'tcx> {
} }
_ => continue, _ => continue,
}; };
self.emit_repr_error(
struct_span_err!(
self.tcx.sess,
hint.span(), hint.span(),
*span, E0517,
&format!("attribute should be applied to {}", allowed_targets), "{}",
&format!("not {} {}", article, allowed_targets), &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. // 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) { fn check_used(&self, attrs: &'hir [Attribute], target: Target) {
for attr in attrs { for attr in attrs {
if self.tcx.sess.check_name(attr, sym::used) && target != Target::Static { 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>) { 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) intravisit::walk_stmt(self, stmt)
} }
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { 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) 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 { fn is_c_like_enum(item: &Item<'_>) -> bool {

View file

@ -1,6 +1,6 @@
#![feature(repr_simd)] #![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() {} fn f() {}
#[repr(C)] #[repr(C)]
@ -12,7 +12,7 @@ struct SPacked(f64, f64);
#[repr(simd)] #[repr(simd)]
struct SSimd(f64, f64); 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); struct SInt(f64, f64);
#[repr(C)] #[repr(C)]
@ -21,10 +21,10 @@ enum EExtern { A, B }
#[repr(align(8))] #[repr(align(8))]
enum EAlign { A, B } 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 } 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 } enum ESimd { A, B }
#[repr(i8)] #[repr(i8)]

View file

@ -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 --> $DIR/attr-usage-repr.rs:3:8
| |
LL | #[repr(C)] LL | #[repr(C)]
@ -6,7 +6,7 @@ LL | #[repr(C)]
LL | fn f() {} LL | fn f() {}
| --------- not a struct, enum, or union | --------- 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 --> $DIR/attr-usage-repr.rs:15:8
| |
LL | #[repr(i8)] LL | #[repr(i8)]
@ -14,7 +14,7 @@ LL | #[repr(i8)]
LL | struct SInt(f64, f64); LL | struct SInt(f64, f64);
| ---------------------- not an enum | ---------------------- 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 --> $DIR/attr-usage-repr.rs:24:8
| |
LL | #[repr(packed)] LL | #[repr(packed)]
@ -22,7 +22,7 @@ LL | #[repr(packed)]
LL | enum EPacked { A, B } LL | enum EPacked { A, B }
| --------------------- not a struct or union | --------------------- 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 --> $DIR/attr-usage-repr.rs:27:8
| |
LL | #[repr(simd)] LL | #[repr(simd)]

View file

@ -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 --> $DIR/E0517.rs:1:8
| |
LL | #[repr(C)] LL | #[repr(C)]
@ -6,7 +6,7 @@ LL | #[repr(C)]
LL | type Foo = u8; LL | type Foo = u8;
| -------------- not a struct, enum, or union | -------------- 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 --> $DIR/E0517.rs:4:8
| |
LL | #[repr(packed)] LL | #[repr(packed)]
@ -14,7 +14,7 @@ LL | #[repr(packed)]
LL | enum Foo2 {Bar, Baz} LL | enum Foo2 {Bar, Baz}
| -------------------- not a struct or union | -------------------- 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 --> $DIR/E0517.rs:7:8
| |
LL | #[repr(u8)] LL | #[repr(u8)]
@ -22,7 +22,7 @@ LL | #[repr(u8)]
LL | struct Foo3 {bar: bool, baz: bool} LL | struct Foo3 {bar: bool, baz: bool}
| ---------------------------------- not an enum | ---------------------------------- 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 --> $DIR/E0517.rs:10:8
| |
LL | #[repr(C)] LL | #[repr(C)]

View file

@ -0,0 +1,7 @@
enum Foo {
#[inline]
//~^ ERROR attribute should be applied
Variant,
}
fn main() {}

View file

@ -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`.

View file

@ -1,4 +1,4 @@
fn main() { fn main() {
#[inline] struct Foo; //~ ERROR attribute should be applied to function or closure #[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
} }

View file

@ -4,7 +4,7 @@ error[E0518]: attribute should be applied to function or closure
LL | #[inline] struct Foo; LL | #[inline] struct Foo;
| ^^^^^^^^^ ----------- not a function or closure | ^^^^^^^^^ ----------- 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 --> $DIR/issue-31769.rs:3:12
| |
LL | #[repr(C)] fn foo() {} LL | #[repr(C)] fn foo() {}

View file

@ -13,18 +13,17 @@ fn main() {
#[repr(nothing)] #[repr(nothing)]
let _x = 0; 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)] #[repr(something_not_real)]
loop { loop {
() ()
}; };
//~^^^^ ERROR attribute should not be applied to an expression //~^^^^ ERROR attribute should be applied to a struct, enum, or union
#[repr] #[repr]
let _y = "123"; let _y = "123";
//~^^ ERROR attribute should not be applied to a statement //~^^ ERROR malformed `repr` attribute
//~| ERROR malformed `repr` attribute
fn foo() {} fn foo() {}
@ -33,6 +32,5 @@ fn main() {
//~^^ ERROR attribute should be applied to function or closure //~^^ ERROR attribute should be applied to function or closure
let _z = #[repr] 1; let _z = #[repr] 1;
//~^ ERROR attribute should not be applied to an expression //~^ ERROR malformed `repr` attribute
//~| ERROR malformed `repr` attribute
} }

View file

@ -5,7 +5,7 @@ LL | #[repr]
| ^^^^^^^ help: must be of the form: `#[repr(C)]` | ^^^^^^^ help: must be of the form: `#[repr(C)]`
error: malformed `repr` attribute input error: malformed `repr` attribute input
--> $DIR/issue-43988.rs:35:14 --> $DIR/issue-43988.rs:34:14
| |
LL | let _z = #[repr] 1; LL | let _z = #[repr] 1;
| ^^^^^^^ help: must be of the form: `#[repr(C)]` | ^^^^^^^ help: must be of the form: `#[repr(C)]`
@ -26,47 +26,33 @@ LL | #[inline(XYZ)]
LL | let _b = 4; LL | let _b = 4;
| ----------- not a function or closure | ----------- not a function or closure
error[E0517]: attribute should not be applied to a statement error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-43988.rs:14:5 --> $DIR/issue-43988.rs:14:12
| |
LL | #[repr(nothing)] LL | #[repr(nothing)]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^
LL | let _x = 0; LL | let _x = 0;
| ----------- not a struct, enum, or union | ----------- not a struct, enum, or union
error[E0517]: attribute should not be applied to an expression error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-43988.rs:18:5 --> $DIR/issue-43988.rs:18:12
| |
LL | #[repr(something_not_real)] LL | #[repr(something_not_real)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
LL | / loop { LL | / loop {
LL | | () LL | | ()
LL | | }; LL | | };
| |_____- not defining a struct, enum, or union | |_____- not 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
error[E0518]: attribute should be applied to function or closure 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 | #[inline(ABC)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
LL | foo(); LL | foo();
| ----- not a function or closure | ----- not a function or closure
error[E0517]: attribute should not be applied to an expression error: aborting due to 7 previous errors
--> $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
Some errors have detailed explanations: E0517, E0518. Some errors have detailed explanations: E0517, E0518.
For more information about an error, try `rustc --explain E0517`. For more information about an error, try `rustc --explain E0517`.

View file

@ -1,9 +1,9 @@
#![allow(dead_code)] #![allow(dead_code)]
#[repr(i128)] //~ ERROR: attribute should be applied to enum #[repr(i128)] //~ ERROR: attribute should be applied to an enum
struct Foo; struct Foo;
#[repr(u128)] //~ ERROR: attribute should be applied to enum #[repr(u128)] //~ ERROR: attribute should be applied to an enum
struct Bar; struct Bar;
fn main() {} fn main() {}

View file

@ -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 --> $DIR/issue-74082.rs:3:8
| |
LL | #[repr(i128)] LL | #[repr(i128)]
@ -6,7 +6,7 @@ LL | #[repr(i128)]
LL | struct Foo; LL | struct Foo;
| ----------- not an enum | ----------- 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 --> $DIR/issue-74082.rs:6:8
| |
LL | #[repr(u128)] LL | #[repr(u128)]

View file

@ -3,10 +3,7 @@ fn main() {
.map( .map(
#[target_feature(enable = "")] #[target_feature(enable = "")]
//~^ ERROR: attribute should be applied to a function //~^ 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] #[track_caller]
//~^ ERROR: `#[track_caller]` requires Rust ABI [E0737]
|_| (), |_| (),
//~^ NOTE: not a function //~^ NOTE: not a function
) )

View file

@ -7,18 +7,5 @@ LL | #[target_feature(enable = "")]
LL | |_| (), LL | |_| (),
| ------ not a function | ------ not a function
error: the feature named `` is not valid for this target error: aborting due to previous error
--> $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
For more information about this error, try `rustc --explain E0737`.

View file

@ -0,0 +1,9 @@
struct Test;
enum Foo {
#[repr(u8)]
//~^ ERROR attribute should be applied to a struct, enum, or union
Variant,
}
fn main() {}

View file

@ -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`.

View file

@ -5,10 +5,10 @@ use std::num::NonZeroU16 as N16;
#[repr(no_niche)] #[repr(no_niche)]
pub union Cloaked1 { _A: N16 } 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)] #[repr(no_niche)]
pub union Cloaked2 { _A: N16, _B: (u8, N8) } 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() { } fn main() { }

View file

@ -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 --> $DIR/repr-no-niche-inapplicable-to-unions.rs:6:8
| |
LL | #[repr(no_niche)] LL | #[repr(no_niche)]
@ -6,7 +6,7 @@ LL | #[repr(no_niche)]
LL | pub union Cloaked1 { _A: N16 } LL | pub union Cloaked1 { _A: N16 }
| ------------------------------ not a struct or enum | ------------------------------ 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 --> $DIR/repr-no-niche-inapplicable-to-unions.rs:10:8
| |
LL | #[repr(no_niche)] LL | #[repr(no_niche)]

View file

@ -1,9 +1,9 @@
// See also repr-transparent.rs // 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() {} 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; static CANT_REPR_THIS: u32 = 0;
fn main() {} fn main() {}

View file

@ -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 --> $DIR/repr-transparent-other-items.rs:3:8
| |
LL | #[repr(transparent)] LL | #[repr(transparent)]
@ -6,7 +6,7 @@ LL | #[repr(transparent)]
LL | fn cant_repr_this() {} LL | fn cant_repr_this() {}
| ---------------------- not a struct, enum, or union | ---------------------- 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 --> $DIR/repr-transparent-other-items.rs:6:8
| |
LL | #[repr(transparent)] LL | #[repr(transparent)]