passes: prohibit attrs on generic params

This commit modifies the `check_attr` pass so that attribute placement
on generic parameters is checked for validity.

Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
David Wood 2020-11-15 13:03:30 +00:00
parent 2e5723137b
commit 75eb72cc9c
No known key found for this signature in database
GPG Key ID: 2592E76C87381FD9
6 changed files with 147 additions and 5 deletions

View File

@ -9,6 +9,13 @@ use crate::{Item, ItemKind, TraitItem, TraitItemKind};
use std::fmt::{self, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum GenericParamKind {
Type,
Lifetime,
Const,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum MethodKind {
Trait { body: bool },
@ -43,6 +50,7 @@ pub enum Target {
ForeignFn,
ForeignStatic,
ForeignTy,
GenericParam(GenericParamKind),
}
impl Display for Target {
@ -77,6 +85,11 @@ impl Display for Target {
Target::ForeignFn => "foreign function",
Target::ForeignStatic => "foreign static item",
Target::ForeignTy => "foreign type",
Target::GenericParam(kind) => match kind {
GenericParamKind::Type => "type parameter",
GenericParamKind::Lifetime => "lifetime parameter",
GenericParamKind::Const => "const parameter",
},
}
)
}
@ -124,4 +137,14 @@ impl Target {
hir::ForeignItemKind::Type => Target::ForeignTy,
}
}
pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
match generic_param.kind {
hir::GenericParamKind::Type { .. } => Target::GenericParam(GenericParamKind::Type),
hir::GenericParamKind::Lifetime { .. } => {
Target::GenericParam(GenericParamKind::Lifetime)
}
hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
}
}
}

View File

@ -814,6 +814,18 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
intravisit::walk_item(self, item)
}
fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
let target = Target::from_generic_param(generic_param);
self.check_attributes(
generic_param.hir_id,
generic_param.attrs,
&generic_param.span,
target,
None,
);
intravisit::walk_generic_param(self, generic_param)
}
fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
let target = Target::from_trait_item(trait_item);
self.check_attributes(trait_item.hir_id, &trait_item.attrs, &trait_item.span, target, None);

View File

@ -0,0 +1,30 @@
#![deny(unused_attributes)]
#![feature(min_const_generics)]
use std::marker::PhantomData;
pub struct Foo<#[inline] const N: usize>;
//~^ ERROR attribute should be applied to function or closure
pub struct Bar<#[cold] const N: usize>;
//~^ ERROR attribute should be applied to a function
//~| WARN this was previously accepted
pub struct Baz<#[repr(C)] const N: usize>;
//~^ ERROR attribute should be applied to a struct, enum, or union
//
pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
//~^ ERROR attribute should be applied to function or closure
pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
//~^ ERROR attribute should be applied to a function
//~| WARN this was previously accepted
pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
//~^ ERROR attribute should be applied to a struct, enum, or union
//
pub struct Foo3<#[inline] T>(PhantomData<T>);
//~^ ERROR attribute should be applied to function or closure
pub struct Bar3<#[cold] T>(PhantomData<T>);
//~^ ERROR attribute should be applied to a function
//~| WARN this was previously accepted
pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
//~^ ERROR attribute should be applied to a struct, enum, or union
fn main() {}

View File

@ -0,0 +1,69 @@
error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-78957.rs:6:16
|
LL | pub struct Foo<#[inline] const N: usize>;
| ^^^^^^^^^ - not a function or closure
error: attribute should be applied to a function
--> $DIR/issue-78957.rs:8:16
|
LL | pub struct Bar<#[cold] const N: usize>;
| ^^^^^^^ - not a function
|
note: the lint level is defined here
--> $DIR/issue-78957.rs:1:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-78957.rs:11:23
|
LL | pub struct Baz<#[repr(C)] const N: usize>;
| ^ - not a struct, enum, or union
error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-78957.rs:14:17
|
LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
| ^^^^^^^^^ -- not a function or closure
error: attribute should be applied to a function
--> $DIR/issue-78957.rs:16:17
|
LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
| ^^^^^^^ -- not a function
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-78957.rs:19:24
|
LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
| ^ -- not a struct, enum, or union
error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-78957.rs:22:17
|
LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
| ^^^^^^^^^ - not a function or closure
error: attribute should be applied to a function
--> $DIR/issue-78957.rs:24:17
|
LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
| ^^^^^^^ - not a function
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-78957.rs:27:24
|
LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
| ^ - not a struct, enum, or union
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0517, E0518.
For more information about an error, try `rustc --explain E0517`.

View File

@ -17,7 +17,9 @@ fn test() {}
#[bench] // OK, shadowed
fn bench() {}
fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
fn non_macro_expanded_location<#[repr(C)] T>() {
//~^ ERROR `repr` is ambiguous
//~| ERROR attribute should be applied to a struct, enum, or union
match 0u8 {
#[repr(C)] //~ ERROR `repr` is ambiguous
_ => {}

View File

@ -1,5 +1,5 @@
error[E0425]: cannot find value `NonExistent` in this scope
--> $DIR/ambiguous-builtin-attrs.rs:30:5
--> $DIR/ambiguous-builtin-attrs.rs:32:5
|
LL | NonExistent;
| ^^^^^^^^^^^ not found in this scope
@ -47,7 +47,7 @@ LL | use builtin_attrs::*;
= help: use `crate::repr` to refer to this attribute macro unambiguously
error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
--> $DIR/ambiguous-builtin-attrs.rs:22:11
--> $DIR/ambiguous-builtin-attrs.rs:24:11
|
LL | #[repr(C)]
| ^^^^ ambiguous name
@ -74,7 +74,13 @@ LL | use builtin_attrs::*;
| ^^^^^^^^^^^^^^^^
= help: use `crate::feature` to refer to this attribute macro unambiguously
error: aborting due to 6 previous errors
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/ambiguous-builtin-attrs.rs:20:39
|
LL | fn non_macro_expanded_location<#[repr(C)] T>() {
| ^ - not a struct, enum, or union
Some errors have detailed explanations: E0425, E0659.
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0425, E0517, E0659.
For more information about an error, try `rustc --explain E0425`.