From 8ecd931a8eb0bb9bde2e7d35e72553b512d01c80 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 25 Mar 2021 15:40:50 -0400 Subject: [PATCH] Don't ICE when using `#[global_alloc]` on a non-item statement Fixes #83469 We need to return an `Annotatable::Stmt` if we were passed an `Annotatable::Stmt` --- .../src/global_allocator.rs | 34 +++++++++---------- .../issue-83469-global-alloc-invalid-stmt.rs | 10 ++++++ ...sue-83469-global-alloc-invalid-stmt.stderr | 8 +++++ 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs create mode 100644 src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 9b43c11f0f3..a97cac7e514 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -14,31 +14,31 @@ pub fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, - mut item: Annotatable, + item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator); - let not_static = |item: Annotatable| { - ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); - vec![item] - }; let orig_item = item.clone(); - let mut is_stmt = false; + let not_static = || { + ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); + vec![orig_item.clone()] + }; // Allow using `#[global_allocator]` on an item statement - if let Annotatable::Stmt(stmt) = &item { - if let StmtKind::Item(item_) = &stmt.kind { - item = Annotatable::Item(item_.clone()); - is_stmt = true; - } - } - - let item = match item { + // FIXME - if we get deref patterns, use them to reduce duplication here + let (item, is_stmt) = match &item { Annotatable::Item(item) => match item.kind { - ItemKind::Static(..) => item, - _ => return not_static(Annotatable::Item(item)), + ItemKind::Static(..) => (item, false), + _ => return not_static(), }, - _ => return not_static(item), + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item_) => match item_.kind { + ItemKind::Static(..) => (item_, true), + _ => return not_static(), + }, + _ => return not_static(), + }, + _ => return not_static(), }; // Generate a bunch of new items using the AllocFnFactory diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs new file mode 100644 index 00000000000..25adc5d2578 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs @@ -0,0 +1,10 @@ +// Regression test for issue #83469 +// Ensures that we recover from `#[global_alloc]` on an invalid +// stmt without an ICE + +fn outer() { + #[global_allocator] + fn inner() {} //~ ERROR allocators must be statics +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr new file mode 100644 index 00000000000..ec0e3c4c754 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5 + | +LL | fn inner() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error +