diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2021-02-23 15:12:28 +0000 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2021-02-23 17:25:55 +0000 |
| commit | d87eec1bf67959977c8ebaadc2ddcf4bdc14658a (patch) | |
| tree | 1f777c2c1702ec27d57c346a8c9f7c1b876df372 /compiler/rustc_passes | |
| parent | 9b471a3f5fe57e5c6e08acf665f2094422415a3d (diff) | |
| download | rust-d87eec1bf67959977c8ebaadc2ddcf4bdc14658a.tar.gz rust-d87eec1bf67959977c8ebaadc2ddcf4bdc14658a.zip | |
Add #[rustc_legacy_const_generics]
Diffstat (limited to 'compiler/rustc_passes')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bf9b7e588bd..947cca3c725 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -91,6 +91,8 @@ impl CheckAttrVisitor<'tcx> { self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) } else if self.tcx.sess.check_name(attr, sym::naked) { self.check_naked(hir_id, attr, span, target) + } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) { + self.check_rustc_legacy_const_generics(&attr, span, target, item) } else { // lint-only checks if self.tcx.sess.check_name(attr, sym::cold) { @@ -750,6 +752,79 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. + fn check_rustc_legacy_const_generics( + &self, + attr: &Attribute, + span: &Span, + target: Target, + item: Option<ItemLike<'_>>, + ) -> bool { + 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, .. }, generics, _), + .. + })) + | Some(ItemLike::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(decl, _, generics), + .. + })) = item + { + let arg_count = decl.inputs.len() as u128 + generics.params.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 + } + } + /// Checks if `#[link_section]` is applied to a function or static. fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { |
