1
Fork 0

Improve checking for attribute

This commit is contained in:
Amanieu d'Antras 2021-02-25 09:04:43 +00:00
parent 22184a0f5d
commit 00afbe70f2
3 changed files with 85 additions and 63 deletions

View file

@ -760,7 +760,7 @@ impl CheckAttrVisitor<'tcx> {
target: Target, target: Target,
item: Option<ItemLike<'_>>, item: Option<ItemLike<'_>>,
) -> bool { ) -> bool {
let is_function = matches!(target, Target::Fn | Target::Method(..) | Target::ForeignFn); let is_function = matches!(target, Target::Fn | Target::Method(..));
if !is_function { if !is_function {
self.tcx self.tcx
.sess .sess
@ -776,55 +776,64 @@ impl CheckAttrVisitor<'tcx> {
Some(it) => it, Some(it) => it,
}; };
let (decl, generics) = match item {
Some(ItemLike::Item(Item {
kind: ItemKind::Fn(FnSig { decl, .. }, generics, _),
..
})) => (decl, generics),
_ => bug!("should be a function item"),
};
for param in generics.params {
match param.kind {
hir::GenericParamKind::Const { .. } => {}
_ => {
self.tcx
.sess
.struct_span_err(
attr.span,
"#[rustc_legacy_const_generics] functions must \
only have const generics",
)
.span_label(param.span, "non-const generic parameter")
.emit();
return false;
}
}
}
if list.len() != generics.params.len() {
self.tcx
.sess
.struct_span_err(
attr.span,
"#[rustc_legacy_const_generics] must have one index for each generic parameter",
)
.span_label(generics.span, "generic parameters")
.emit();
return false;
}
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
let mut invalid_args = vec![]; let mut invalid_args = vec![];
for meta in list { for meta in list {
if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) {
if let Some(ItemLike::Item(Item { if *val >= arg_count {
kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), let span = meta.span();
.. self.tcx
})) .sess
| Some(ItemLike::ForeignItem(ForeignItem { .struct_span_err(span, "index exceeds number of arguments")
kind: ForeignItemKind::Fn(decl, _, generics), .span_label(
.. span,
})) = item format!(
{ "there {} only {} argument{}",
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128; if arg_count != 1 { "are" } else { "is" },
for param in generics.params { arg_count,
match param.kind { pluralize!(arg_count)
hir::GenericParamKind::Const { .. } => {} ),
_ => { )
self.tcx .emit();
.sess return false;
.struct_span_err(
meta.span(),
"#[rustc_legacy_const_generics] functions must \
only have const generics",
)
.span_label(param.span, "non-const generic parameter")
.emit();
break;
}
}
}
if *val >= arg_count {
let span = meta.span();
self.tcx
.sess
.struct_span_err(span, "index exceeds number of arguments")
.span_label(
span,
format!(
"there {} only {} argument{}",
if arg_count != 1 { "are" } else { "is" },
arg_count,
pluralize!(arg_count)
),
)
.emit();
return false;
}
} else {
bug!("should be a function item");
} }
} else { } else {
invalid_args.push(meta.span()); invalid_args.push(meta.span());

View file

@ -1,29 +1,29 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#[rustc_legacy_const_generics(0)] //~ ERROR index exceeds number of arguments #[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] must have one index for
fn foo1() {} fn foo1() {}
#[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments #[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments
fn foo2(_: u8) {} fn foo2<const X: usize>() {}
#[rustc_legacy_const_generics(2)] //~ ERROR index exceeds number of arguments #[rustc_legacy_const_generics(2)] //~ ERROR index exceeds number of arguments
fn foo3<const X: usize>(_: u8) {} fn foo3<const X: usize>(_: u8) {}
#[rustc_legacy_const_generics(a)] //~ ERROR arguments should be non-negative integers #[rustc_legacy_const_generics(a)] //~ ERROR arguments should be non-negative integers
fn foo4() {} fn foo4<const X: usize>() {}
#[rustc_legacy_const_generics(1, a, 2, b)] //~ ERROR arguments should be non-negative integers #[rustc_legacy_const_generics(1, a, 2, b)] //~ ERROR arguments should be non-negative integers
fn foo5(_: u8, _: u8, _: u8) {} fn foo5<const X: usize, const Y: usize, const Z: usize, const W: usize>() {}
#[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function #[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function
struct S; struct S;
#[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes #[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes
fn foo6(_: u8) {} fn foo6<const X: usize>() {}
extern { extern {
#[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments #[rustc_legacy_const_generics(1)] //~ ERROR attribute should be applied to a function
fn foo7(_: u8); fn foo7<const X: usize>(); //~ ERROR foreign items may not have const parameters
} }
#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have #[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have

View file

@ -18,11 +18,13 @@ error: malformed `rustc_legacy_const_generics` attribute input
LL | #[rustc_legacy_const_generics = 1] LL | #[rustc_legacy_const_generics = 1]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]`
error: index exceeds number of arguments error: #[rustc_legacy_const_generics] must have one index for each generic parameter
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:31 --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1
| |
LL | #[rustc_legacy_const_generics(0)] LL | #[rustc_legacy_const_generics(0)]
| ^ there are only 0 arguments | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | fn foo1() {}
| - generic parameters
error: index exceeds number of arguments error: index exceeds number of arguments
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31 --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31
@ -57,18 +59,29 @@ LL | struct S;
| --------- not a function | --------- not a function
error: #[rustc_legacy_const_generics] functions must only have const generics error: #[rustc_legacy_const_generics] functions must only have const generics
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:31 --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:1
| |
LL | #[rustc_legacy_const_generics(0)] LL | #[rustc_legacy_const_generics(0)]
| ^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | fn foo8<X>() {} LL | fn foo8<X>() {}
| - non-const generic parameter | - non-const generic parameter
error: index exceeds number of arguments error: attribute should be applied to a function
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:35 --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5
| |
LL | #[rustc_legacy_const_generics(1)] LL | #[rustc_legacy_const_generics(1)]
| ^ there is only 1 argument | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | fn foo7<const X: usize>();
| -------------------------- not a function
error: aborting due to 11 previous errors error[E0044]: foreign items may not have const parameters
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:26:5
|
LL | fn foo7<const X: usize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
|
= help: replace the const parameters with concrete consts
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0044`.