2 use rustc_ast::tokenstream::TokenStream;
3 use rustc_expand::base::{self, DummyResult};
4 use rustc_session::errors::report_lit_error;
5 use rustc_span::symbol::Symbol;
8 cx: &mut base::ExtCtxt<'_>,
11 ) -> Box<dyn base::MacResult + 'static> {
12 let Some(es) = base::get_exprs_from_tts(cx, tts) else {
13 return DummyResult::any(sp);
15 let mut accumulator = String::new();
16 let mut missing_literal = vec![];
17 let mut has_errors = false;
20 ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
21 Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
22 accumulator.push_str(s.as_str());
24 Ok(ast::LitKind::Char(c)) => {
27 Ok(ast::LitKind::Int(i, _)) => {
28 accumulator.push_str(&i.to_string());
30 Ok(ast::LitKind::Bool(b)) => {
31 accumulator.push_str(&b.to_string());
33 Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
34 cx.span_err(e.span, "cannot concatenate a byte string literal");
37 Ok(ast::LitKind::Err) => {
41 report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span);
45 ast::ExprKind::IncludedBytes(..) => {
46 cx.span_err(e.span, "cannot concatenate a byte string literal")
48 ast::ExprKind::Err => {
52 missing_literal.push(e.span);
56 if !missing_literal.is_empty() {
57 let mut err = cx.struct_span_err(missing_literal, "expected a literal");
58 err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
60 return DummyResult::any(sp);
61 } else if has_errors {
62 return DummyResult::any(sp);
64 let sp = cx.with_def_site_ctxt(sp);
65 base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))