diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 7da9bdc38a2a8..36682bbe0708f 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -42,6 +42,18 @@ pub fn expand_concat( has_errors = true; } }, + // We also want to allow negative numeric literals. + ast::ExprKind::Unary(ast::UnOp::Neg, ref expr) if let ast::ExprKind::Lit(token_lit) = expr.kind => { + match ast::LitKind::from_token_lit(token_lit) { + Ok(ast::LitKind::Int(i, _)) => accumulator.push_str(&format!("-{i}")), + Ok(ast::LitKind::Float(f, _)) => accumulator.push_str(&format!("-{f}")), + Err(err) => { + report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span); + has_errors = true; + } + _ => missing_literal.push(e.span), + } + } ast::ExprKind::IncludedBytes(..) => { cx.span_err(e.span, "cannot concatenate a byte string literal") } @@ -53,9 +65,10 @@ pub fn expand_concat( } } } + if !missing_literal.is_empty() { let mut err = cx.struct_span_err(missing_literal, "expected a literal"); - err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); + err.note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`"); err.emit(); return DummyResult::any(sp); } else if has_errors { diff --git a/tests/ui/macros/bad-concat.stderr b/tests/ui/macros/bad-concat.stderr index 4316fd312c739..d67f3c33d36e3 100644 --- a/tests/ui/macros/bad-concat.stderr +++ b/tests/ui/macros/bad-concat.stderr @@ -4,7 +4,7 @@ error: expected a literal LL | let _ = concat!(x, y, z, "bar"); | ^ ^ ^ | - = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` error: aborting due to previous error diff --git a/tests/ui/macros/concat.stderr b/tests/ui/macros/concat.stderr index 61fb9de1ef96c..d65d9354454c3 100644 --- a/tests/ui/macros/concat.stderr +++ b/tests/ui/macros/concat.stderr @@ -16,7 +16,7 @@ error: expected a literal LL | concat!(foo); | ^^^ | - = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` error: expected a literal --> $DIR/concat.rs:5:13 @@ -24,7 +24,7 @@ error: expected a literal LL | concat!(foo()); | ^^^^^ | - = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` error: aborting due to 4 previous errors diff --git a/tests/ui/macros/issue-106837.rs b/tests/ui/macros/issue-106837.rs new file mode 100644 index 0000000000000..7bbd3d68a900e --- /dev/null +++ b/tests/ui/macros/issue-106837.rs @@ -0,0 +1,10 @@ +fn main() { + concat!(-42); + concat!(-3.14); + + concat!(-"hello"); + //~^ ERROR expected a literal + + concat!(--1); + //~^ ERROR expected a literal +} diff --git a/tests/ui/macros/issue-106837.stderr b/tests/ui/macros/issue-106837.stderr new file mode 100644 index 0000000000000..998d6c5eb6f2b --- /dev/null +++ b/tests/ui/macros/issue-106837.stderr @@ -0,0 +1,18 @@ +error: expected a literal + --> $DIR/issue-106837.rs:5:13 + | +LL | concat!(-"hello"); + | ^^^^^^^^ + | + = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` + +error: expected a literal + --> $DIR/issue-106837.rs:8:13 + | +LL | concat!(--1); + | ^^^ + | + = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` + +error: aborting due to 2 previous errors +