Skip to content

Commit 00afbe7

Browse files
committed
Improve checking for attribute
1 parent 22184a0 commit 00afbe7

File tree

3 files changed

+85
-63
lines changed

3 files changed

+85
-63
lines changed

compiler/rustc_passes/src/check_attr.rs

+56-47
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ impl CheckAttrVisitor<'tcx> {
760760
target: Target,
761761
item: Option<ItemLike<'_>>,
762762
) -> bool {
763-
let is_function = matches!(target, Target::Fn | Target::Method(..) | Target::ForeignFn);
763+
let is_function = matches!(target, Target::Fn | Target::Method(..));
764764
if !is_function {
765765
self.tcx
766766
.sess
@@ -776,55 +776,64 @@ impl CheckAttrVisitor<'tcx> {
776776
Some(it) => it,
777777
};
778778

779+
let (decl, generics) = match item {
780+
Some(ItemLike::Item(Item {
781+
kind: ItemKind::Fn(FnSig { decl, .. }, generics, _),
782+
..
783+
})) => (decl, generics),
784+
_ => bug!("should be a function item"),
785+
};
786+
787+
for param in generics.params {
788+
match param.kind {
789+
hir::GenericParamKind::Const { .. } => {}
790+
_ => {
791+
self.tcx
792+
.sess
793+
.struct_span_err(
794+
attr.span,
795+
"#[rustc_legacy_const_generics] functions must \
796+
only have const generics",
797+
)
798+
.span_label(param.span, "non-const generic parameter")
799+
.emit();
800+
return false;
801+
}
802+
}
803+
}
804+
805+
if list.len() != generics.params.len() {
806+
self.tcx
807+
.sess
808+
.struct_span_err(
809+
attr.span,
810+
"#[rustc_legacy_const_generics] must have one index for each generic parameter",
811+
)
812+
.span_label(generics.span, "generic parameters")
813+
.emit();
814+
return false;
815+
}
816+
817+
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
779818
let mut invalid_args = vec![];
780819
for meta in list {
781820
if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) {
782-
if let Some(ItemLike::Item(Item {
783-
kind: ItemKind::Fn(FnSig { decl, .. }, generics, _),
784-
..
785-
}))
786-
| Some(ItemLike::ForeignItem(ForeignItem {
787-
kind: ForeignItemKind::Fn(decl, _, generics),
788-
..
789-
})) = item
790-
{
791-
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
792-
for param in generics.params {
793-
match param.kind {
794-
hir::GenericParamKind::Const { .. } => {}
795-
_ => {
796-
self.tcx
797-
.sess
798-
.struct_span_err(
799-
meta.span(),
800-
"#[rustc_legacy_const_generics] functions must \
801-
only have const generics",
802-
)
803-
.span_label(param.span, "non-const generic parameter")
804-
.emit();
805-
break;
806-
}
807-
}
808-
}
809-
if *val >= arg_count {
810-
let span = meta.span();
811-
self.tcx
812-
.sess
813-
.struct_span_err(span, "index exceeds number of arguments")
814-
.span_label(
815-
span,
816-
format!(
817-
"there {} only {} argument{}",
818-
if arg_count != 1 { "are" } else { "is" },
819-
arg_count,
820-
pluralize!(arg_count)
821-
),
822-
)
823-
.emit();
824-
return false;
825-
}
826-
} else {
827-
bug!("should be a function item");
821+
if *val >= arg_count {
822+
let span = meta.span();
823+
self.tcx
824+
.sess
825+
.struct_span_err(span, "index exceeds number of arguments")
826+
.span_label(
827+
span,
828+
format!(
829+
"there {} only {} argument{}",
830+
if arg_count != 1 { "are" } else { "is" },
831+
arg_count,
832+
pluralize!(arg_count)
833+
),
834+
)
835+
.emit();
836+
return false;
828837
}
829838
} else {
830839
invalid_args.push(meta.span());

src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
#![feature(rustc_attrs)]
22

3-
#[rustc_legacy_const_generics(0)] //~ ERROR index exceeds number of arguments
3+
#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] must have one index for
44
fn foo1() {}
55

66
#[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments
7-
fn foo2(_: u8) {}
7+
fn foo2<const X: usize>() {}
88

99
#[rustc_legacy_const_generics(2)] //~ ERROR index exceeds number of arguments
1010
fn foo3<const X: usize>(_: u8) {}
1111

1212
#[rustc_legacy_const_generics(a)] //~ ERROR arguments should be non-negative integers
13-
fn foo4() {}
13+
fn foo4<const X: usize>() {}
1414

1515
#[rustc_legacy_const_generics(1, a, 2, b)] //~ ERROR arguments should be non-negative integers
16-
fn foo5(_: u8, _: u8, _: u8) {}
16+
fn foo5<const X: usize, const Y: usize, const Z: usize, const W: usize>() {}
1717

1818
#[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function
1919
struct S;
2020

2121
#[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes
22-
fn foo6(_: u8) {}
22+
fn foo6<const X: usize>() {}
2323

2424
extern {
25-
#[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments
26-
fn foo7(_: u8);
25+
#[rustc_legacy_const_generics(1)] //~ ERROR attribute should be applied to a function
26+
fn foo7<const X: usize>(); //~ ERROR foreign items may not have const parameters
2727
}
2828

2929
#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have

src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr

+22-9
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ error: malformed `rustc_legacy_const_generics` attribute input
1818
LL | #[rustc_legacy_const_generics = 1]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]`
2020

21-
error: index exceeds number of arguments
22-
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:31
21+
error: #[rustc_legacy_const_generics] must have one index for each generic parameter
22+
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1
2323
|
2424
LL | #[rustc_legacy_const_generics(0)]
25-
| ^ there are only 0 arguments
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
LL | fn foo1() {}
27+
| - generic parameters
2628

2729
error: index exceeds number of arguments
2830
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31
@@ -57,18 +59,29 @@ LL | struct S;
5759
| --------- not a function
5860

5961
error: #[rustc_legacy_const_generics] functions must only have const generics
60-
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:31
62+
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:1
6163
|
6264
LL | #[rustc_legacy_const_generics(0)]
63-
| ^
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6466
LL | fn foo8<X>() {}
6567
| - non-const generic parameter
6668

67-
error: index exceeds number of arguments
68-
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:35
69+
error: attribute should be applied to a function
70+
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5
6971
|
7072
LL | #[rustc_legacy_const_generics(1)]
71-
| ^ there is only 1 argument
73+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
74+
LL | fn foo7<const X: usize>();
75+
| -------------------------- not a function
76+
77+
error[E0044]: foreign items may not have const parameters
78+
--> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:26:5
79+
|
80+
LL | fn foo7<const X: usize>();
81+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
82+
|
83+
= help: replace the const parameters with concrete consts
7284

73-
error: aborting due to 11 previous errors
85+
error: aborting due to 12 previous errors
7486

87+
For more information about this error, try `rustc --explain E0044`.

0 commit comments

Comments
 (0)