1
Fork 0

Prohibit #[default] in invalid places

This commit is contained in:
Jacob Pratt 2021-07-17 01:05:57 -04:00
parent 5ae2371ceb
commit 72465b0a32
No known key found for this signature in database
GPG key ID: B80E19E4662B5AA4
3 changed files with 131 additions and 29 deletions

View file

@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
use crate::deriving::generic::*; use crate::deriving::generic::*;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::walk_list;
use rustc_ast::EnumDef; use rustc_ast::EnumDef;
use rustc_ast::VariantData; use rustc_ast::VariantData;
use rustc_ast::{Expr, MetaItem}; use rustc_ast::{Expr, MetaItem};
@ -19,6 +20,8 @@ pub fn expand_deriving_default(
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
) { ) {
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
let inline = cx.meta_word(span, sym::inline); let inline = cx.meta_word(span, sym::inline);
let attrs = vec![cx.attribute(inline)]; let attrs = vec![cx.attribute(inline)];
let trait_def = TraitDef { let trait_def = TraitDef {
@ -184,7 +187,10 @@ fn extract_default_variant<'a>(
}; };
if !matches!(variant.data, VariantData::Unit(..)) { if !matches!(variant.data, VariantData::Unit(..)) {
cx.struct_span_err(variant.ident.span, "`#[default]` may only be used on unit variants") cx.struct_span_err(
variant.ident.span,
"the `#[default]` attribute may only be used on unit enum variants",
)
.help("consider a manual implementation of `Default`") .help("consider a manual implementation of `Default`")
.emit(); .emit();
@ -253,3 +259,31 @@ fn validate_default_attribute(
} }
Ok(()) Ok(())
} }
struct DetectNonVariantDefaultAttr<'a, 'b> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
if attr.has_name(kw::Default) {
self.cx
.struct_span_err(
attr.span,
"the `#[default]` attribute may only be used on unit enum variants",
)
.emit();
}
rustc_ast::visit::walk_attribute(self, attr);
}
fn visit_variant(&mut self, v: &'a rustc_ast::Variant) {
self.visit_ident(v.ident);
self.visit_vis(&v.vis);
self.visit_variant_data(&v.data);
walk_list!(self, visit_anon_const, &v.disr_expr);
for attr in &v.attrs {
rustc_ast::visit::walk_attribute(self, attr);
}
}
}

View file

@ -5,8 +5,40 @@
#![feature(asm, llvm_asm)] #![feature(asm, llvm_asm)]
#![feature(trace_macros, concat_idents)] #![feature(trace_macros, concat_idents)]
#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)]
#![feature(derive_default_enum)] #![feature(derive_default_enum)]
#[derive(Default)]
struct DefaultInnerAttrStruct {
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
foo: (),
}
#[derive(Default)]
struct DefaultInnerAttrTupleStruct(#[default] ());
//~^ ERROR the `#[default]` attribute may only be used on unit enum variants
#[derive(Default)]
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
struct DefaultOuterAttrStruct {}
#[derive(Default)]
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
enum DefaultOuterAttrEnum {
#[default]
Foo,
}
#[rustfmt::skip] // needs some work to handle this case
#[repr(u8)]
#[derive(Default)]
enum AttrOnInnerExpression {
Foo = #[default] 0, //~ ERROR the `#[default]` attribute may only be used on unit enum variants
Bar([u8; #[default] 1]), //~ ERROR the `#[default]` attribute may only be used on unit enum variants
#[default]
Baz,
}
#[derive(Default)] //~ ERROR no default declared #[derive(Default)] //~ ERROR no default declared
enum NoDeclaredDefault { enum NoDeclaredDefault {
Foo, Foo,
@ -50,7 +82,7 @@ enum ManyDefaultAttrs {
#[derive(Default)] #[derive(Default)]
enum DefaultHasFields { enum DefaultHasFields {
#[default] #[default]
Foo {}, //~ ERROR `#[default]` may only be used on unit variants Foo {}, //~ ERROR the `#[default]` attribute may only be used on unit enum variants
Bar, Bar,
} }

View file

@ -1,5 +1,41 @@
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:13:5
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:18:36
|
LL | struct DefaultInnerAttrTupleStruct(#[default] ());
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:22:1
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:26:1
|
LL | #[default]
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:36:11
|
LL | Foo = #[default] 0,
| ^^^^^^^^^^
error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:37:14
|
LL | Bar([u8; #[default] 1]),
| ^^^^^^^^^^
error: no default declared error: no default declared
--> $DIR/macros-nonfatal-errors.rs:10:10 --> $DIR/macros-nonfatal-errors.rs:42:10
| |
LL | #[derive(Default)] LL | #[derive(Default)]
| ^^^^^^^ | ^^^^^^^
@ -8,7 +44,7 @@ LL | #[derive(Default)]
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: multiple declared defaults error: multiple declared defaults
--> $DIR/macros-nonfatal-errors.rs:16:10 --> $DIR/macros-nonfatal-errors.rs:48:10
| |
LL | #[derive(Default)] LL | #[derive(Default)]
| ^^^^^^^ | ^^^^^^^
@ -26,7 +62,7 @@ LL | Baz,
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `#[default]` attribute does not accept a value error: `#[default]` attribute does not accept a value
--> $DIR/macros-nonfatal-errors.rs:28:5 --> $DIR/macros-nonfatal-errors.rs:60:5
| |
LL | #[default = 1] LL | #[default = 1]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -34,7 +70,7 @@ LL | #[default = 1]
= help: try using `#[default]` = help: try using `#[default]`
error: multiple `#[default]` attributes error: multiple `#[default]` attributes
--> $DIR/macros-nonfatal-errors.rs:36:5 --> $DIR/macros-nonfatal-errors.rs:68:5
| |
LL | #[default] LL | #[default]
| ---------- `#[default]` used here | ---------- `#[default]` used here
@ -45,13 +81,13 @@ LL | Foo,
| |
= note: only one `#[default]` attribute is needed = note: only one `#[default]` attribute is needed
help: try removing this help: try removing this
--> $DIR/macros-nonfatal-errors.rs:35:5 --> $DIR/macros-nonfatal-errors.rs:67:5
| |
LL | #[default] LL | #[default]
| ^^^^^^^^^^ | ^^^^^^^^^^
error: multiple `#[default]` attributes error: multiple `#[default]` attributes
--> $DIR/macros-nonfatal-errors.rs:46:5 --> $DIR/macros-nonfatal-errors.rs:78:5
| |
LL | #[default] LL | #[default]
| ---------- `#[default]` used here | ---------- `#[default]` used here
@ -63,7 +99,7 @@ LL | Foo,
| |
= note: only one `#[default]` attribute is needed = note: only one `#[default]` attribute is needed
help: try removing these help: try removing these
--> $DIR/macros-nonfatal-errors.rs:43:5 --> $DIR/macros-nonfatal-errors.rs:75:5
| |
LL | #[default] LL | #[default]
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -72,8 +108,8 @@ LL | #[default]
LL | #[default] LL | #[default]
| ^^^^^^^^^^ | ^^^^^^^^^^
error: `#[default]` may only be used on unit variants error: the `#[default]` attribute may only be used on unit enum variants
--> $DIR/macros-nonfatal-errors.rs:53:5 --> $DIR/macros-nonfatal-errors.rs:85:5
| |
LL | Foo {}, LL | Foo {},
| ^^^ | ^^^
@ -81,7 +117,7 @@ LL | Foo {},
= help: consider a manual implementation of `Default` = help: consider a manual implementation of `Default`
error: default variant must be exhaustive error: default variant must be exhaustive
--> $DIR/macros-nonfatal-errors.rs:61:5 --> $DIR/macros-nonfatal-errors.rs:93:5
| |
LL | #[non_exhaustive] LL | #[non_exhaustive]
| ----------------- declared `#[non_exhaustive]` here | ----------------- declared `#[non_exhaustive]` here
@ -91,43 +127,43 @@ LL | Foo,
= help: consider a manual implementation of `Default` = help: consider a manual implementation of `Default`
error: asm template must be a string literal error: asm template must be a string literal
--> $DIR/macros-nonfatal-errors.rs:66:10 --> $DIR/macros-nonfatal-errors.rs:98:10
| |
LL | asm!(invalid); LL | asm!(invalid);
| ^^^^^^^ | ^^^^^^^
error: inline assembly must be a string literal error: inline assembly must be a string literal
--> $DIR/macros-nonfatal-errors.rs:67:15 --> $DIR/macros-nonfatal-errors.rs:99:15
| |
LL | llvm_asm!(invalid); LL | llvm_asm!(invalid);
| ^^^^^^^ | ^^^^^^^
error: concat_idents! requires ident args. error: concat_idents! requires ident args.
--> $DIR/macros-nonfatal-errors.rs:69:5 --> $DIR/macros-nonfatal-errors.rs:101:5
| |
LL | concat_idents!("not", "idents"); LL | concat_idents!("not", "idents");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: argument must be a string literal error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:71:17 --> $DIR/macros-nonfatal-errors.rs:103:17
| |
LL | option_env!(invalid); LL | option_env!(invalid);
| ^^^^^^^ | ^^^^^^^
error: expected string literal error: expected string literal
--> $DIR/macros-nonfatal-errors.rs:72:10 --> $DIR/macros-nonfatal-errors.rs:104:10
| |
LL | env!(invalid); LL | env!(invalid);
| ^^^^^^^ | ^^^^^^^
error: expected string literal error: expected string literal
--> $DIR/macros-nonfatal-errors.rs:73:10 --> $DIR/macros-nonfatal-errors.rs:105:10
| |
LL | env!(foo, abr, baz); LL | env!(foo, abr, baz);
| ^^^ | ^^^
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
--> $DIR/macros-nonfatal-errors.rs:74:5 --> $DIR/macros-nonfatal-errors.rs:106:5
| |
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -135,7 +171,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: format argument must be a string literal error: format argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:76:13 --> $DIR/macros-nonfatal-errors.rs:108:13
| |
LL | format!(invalid); LL | format!(invalid);
| ^^^^^^^ | ^^^^^^^
@ -146,19 +182,19 @@ LL | format!("{}", invalid);
| ^^^^^ | ^^^^^
error: argument must be a string literal error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:78:14 --> $DIR/macros-nonfatal-errors.rs:110:14
| |
LL | include!(invalid); LL | include!(invalid);
| ^^^^^^^ | ^^^^^^^
error: argument must be a string literal error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:80:18 --> $DIR/macros-nonfatal-errors.rs:112:18
| |
LL | include_str!(invalid); LL | include_str!(invalid);
| ^^^^^^^ | ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:81:5 --> $DIR/macros-nonfatal-errors.rs:113:5
| |
LL | include_str!("i'd be quite surprised if a file with this name existed"); LL | include_str!("i'd be quite surprised if a file with this name existed");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -166,13 +202,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed")
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
error: argument must be a string literal error: argument must be a string literal
--> $DIR/macros-nonfatal-errors.rs:82:20 --> $DIR/macros-nonfatal-errors.rs:114:20
| |
LL | include_bytes!(invalid); LL | include_bytes!(invalid);
| ^^^^^^^ | ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:83:5 --> $DIR/macros-nonfatal-errors.rs:115:5
| |
LL | include_bytes!("i'd be quite surprised if a file with this name existed"); LL | include_bytes!("i'd be quite surprised if a file with this name existed");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -180,10 +216,10 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
error: trace_macros! accepts only `true` or `false` error: trace_macros! accepts only `true` or `false`
--> $DIR/macros-nonfatal-errors.rs:85:5 --> $DIR/macros-nonfatal-errors.rs:117:5
| |
LL | trace_macros!(invalid); LL | trace_macros!(invalid);
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 21 previous errors error: aborting due to 27 previous errors