From 50c6fd6dd52b97334d8b3628cf2f66985b25acc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 6 Dec 2020 00:00:00 +0000 Subject: [PATCH] Don't ICE on malformed `rustc_args_required_const` attribute --- compiler/rustc_passes/src/check_attr.rs | 104 ++++++++++-------- ...lid-rustc_args_required_const-arguments.rs | 6 + ...rustc_args_required_const-arguments.stderr | 14 ++- 3 files changed, 75 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fc97ca035b9..73fb28e5c9a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -545,60 +545,68 @@ fn check_rustc_args_required_const( target: Target, item: Option>, ) -> bool { - if let Target::Fn | Target::Method(..) | Target::ForeignFn = target { - let mut invalid_args = vec![]; - for meta in attr.meta_item_list().expect("no meta item list") { - if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { - if let Some(ItemLike::Item(Item { - kind: ItemKind::Fn(FnSig { decl, .. }, ..), - .. - })) - | Some(ItemLike::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(decl, ..), - .. - })) = item - { - let arg_count = decl.inputs.len() as u128; - 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 { - invalid_args.push(meta.span()); - } - } - if !invalid_args.is_empty() { - self.tcx - .sess - .struct_span_err(invalid_args, "arguments should be non-negative integers") - .emit(); - false - } else { - true - } - } else { + let is_function = matches!(target, Target::Fn | Target::Method(..) | Target::ForeignFn); + if !is_function { self.tcx .sess .struct_span_err(attr.span, "attribute should be applied to a function") .span_label(*span, "not a function") .emit(); + return false; + } + + let list = match attr.meta_item_list() { + // The attribute form is validated on AST. + None => return false, + Some(it) => it, + }; + + let mut invalid_args = vec![]; + for meta in list { + if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { + if let Some(ItemLike::Item(Item { + kind: ItemKind::Fn(FnSig { decl, .. }, ..), + .. + })) + | Some(ItemLike::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(decl, ..), + .. + })) = item + { + let arg_count = decl.inputs.len() as u128; + 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 { + invalid_args.push(meta.span()); + } + } + + if !invalid_args.is_empty() { + self.tcx + .sess + .struct_span_err(invalid_args, "arguments should be non-negative integers") + .emit(); false + } else { + true } } diff --git a/src/test/ui/invalid-rustc_args_required_const-arguments.rs b/src/test/ui/invalid-rustc_args_required_const-arguments.rs index 76c01c21301..99508baeb00 100644 --- a/src/test/ui/invalid-rustc_args_required_const-arguments.rs +++ b/src/test/ui/invalid-rustc_args_required_const-arguments.rs @@ -23,4 +23,10 @@ fn foo6(_: u8) {} fn foo7(_: u8); } +#[rustc_args_required_const] //~ ERROR malformed `rustc_args_required_const` attribute +fn bar1() {} + +#[rustc_args_required_const = 1] //~ ERROR malformed `rustc_args_required_const` attribute +fn bar2() {} + fn main() {} diff --git a/src/test/ui/invalid-rustc_args_required_const-arguments.stderr b/src/test/ui/invalid-rustc_args_required_const-arguments.stderr index 39d04626168..932344f0a33 100644 --- a/src/test/ui/invalid-rustc_args_required_const-arguments.stderr +++ b/src/test/ui/invalid-rustc_args_required_const-arguments.stderr @@ -6,6 +6,18 @@ LL | #[rustc_args_required_const(0usize)] | = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) +error: malformed `rustc_args_required_const` attribute input + --> $DIR/invalid-rustc_args_required_const-arguments.rs:26:1 + | +LL | #[rustc_args_required_const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_args_required_const(N)]` + +error: malformed `rustc_args_required_const` attribute input + --> $DIR/invalid-rustc_args_required_const-arguments.rs:29:1 + | +LL | #[rustc_args_required_const = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_args_required_const(N)]` + error: index exceeds number of arguments --> $DIR/invalid-rustc_args_required_const-arguments.rs:3:29 | @@ -44,5 +56,5 @@ error: index exceeds number of arguments LL | #[rustc_args_required_const(1)] | ^ there is only 1 argument -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors