rust/compiler/rustc_builtin_macros/src/concat_bytes.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

189 lines
7.2 KiB
Rust
Raw Normal View History

use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{ExprKind, LitIntType, LitKind, UintTy, token};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_session::errors::report_lit_error;
use rustc_span::{ErrorGuaranteed, Span};
use crate::errors;
use crate::util::get_exprs_from_tts;
/// Emits errors for literal expressions that are invalid inside and outside of an array.
fn invalid_type_err(
compiler: fix few needless_pass_by_ref_mut clippy lints warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:306:28 | 306 | fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) { | ^^^^^^^^^^^^^^^ help: consider changing to: `&Parser<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:318:8 | 318 | p: &mut Parser<'a>, | ^^^^^^^^^^^^^^^ help: consider changing to: `&Parser<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\assert.rs:114:25 | 114 | fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:32:10 | 32 | ecx: &mut ExtCtxt<'a>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\test.rs:99:9 | 99 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\source_util.rs:237:9 | 237 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:809:10 | 809 | ecx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:737:10 | 737 | ecx: &mut ExtCtxt<'a>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:68:24 | 68 | fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:607:10 | 607 | ecx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\edition_panic.rs:43:9 | 43 | cx: &'cx mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\concat_bytes.rs:11:9 | 11 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\cfg.rs:38:22 | 38 | fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\cfg_accessible.rs:13:28 | 13 | fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:04:00 +00:00
cx: &ExtCtxt<'_>,
token_lit: token::Lit,
span: Span,
is_nested: bool,
) -> ErrorGuaranteed {
use errors::{
ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
};
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
let dcx = cx.dcx();
match LitKind::from_token_lit(token_lit) {
Ok(LitKind::CStr(_, _)) => {
2023-11-01 00:16:34 +00:00
// Avoid ambiguity in handling of terminal `NUL` by refusing to
// concatenate C string literals as bytes.
dcx.emit_err(errors::ConcatCStrLit { span })
}
Ok(LitKind::Char(_)) => {
let sugg =
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg })
}
Ok(LitKind::Str(_, _)) => {
// suggestion would be invalid if we are nested
let sugg = if !is_nested {
snippet.map(|snippet| ConcatBytesInvalidSuggestion::StrLit { span, snippet })
} else {
None
};
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg })
}
Ok(LitKind::Float(_, _)) => {
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None })
}
Ok(LitKind::Bool(_)) => {
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None })
}
Ok(LitKind::Int(_, _)) if !is_nested => {
let sugg =
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span, snippet });
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg })
}
Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => {
2024-01-17 23:40:30 +00:00
assert!(val.get() > u8::MAX.into()); // must be an error
dcx.emit_err(ConcatBytesOob { span })
}
Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }),
Ok(LitKind::ByteStr(..) | LitKind::Byte(_)) => unreachable!(),
Ok(LitKind::Err(guar)) => guar,
Err(err) => report_lit_error(&cx.sess.psess, err, token_lit, span),
}
}
/// Returns `expr` as a *single* byte literal if applicable.
///
/// Otherwise, returns `None`, and either pushes the `expr`'s span to `missing_literals` or
/// updates `guar` accordingly.
fn handle_array_element(
compiler: fix few needless_pass_by_ref_mut clippy lints warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:306:28 | 306 | fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) { | ^^^^^^^^^^^^^^^ help: consider changing to: `&Parser<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:318:8 | 318 | p: &mut Parser<'a>, | ^^^^^^^^^^^^^^^ help: consider changing to: `&Parser<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\assert.rs:114:25 | 114 | fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\asm.rs:32:10 | 32 | ecx: &mut ExtCtxt<'a>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\test.rs:99:9 | 99 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\source_util.rs:237:9 | 237 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:809:10 | 809 | ecx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:737:10 | 737 | ecx: &mut ExtCtxt<'a>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:68:24 | 68 | fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\format.rs:607:10 | 607 | ecx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\edition_panic.rs:43:9 | 43 | cx: &'cx mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\concat_bytes.rs:11:9 | 11 | cx: &mut ExtCtxt<'_>, | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\cfg.rs:38:22 | 38 | fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'a>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut warning: this argument is a mutable reference, but not used mutably --> compiler\rustc_builtin_macros\src\cfg_accessible.rs:13:28 | 13 | fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> { | ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:04:00 +00:00
cx: &ExtCtxt<'_>,
guar: &mut Option<ErrorGuaranteed>,
missing_literals: &mut Vec<rustc_span::Span>,
expr: &P<rustc_ast::Expr>,
) -> Option<u8> {
let dcx = cx.dcx();
match expr.kind {
ExprKind::Lit(token_lit) => {
match LitKind::from_token_lit(token_lit) {
Ok(LitKind::Int(
val,
LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8),
)) if let Ok(val) = u8::try_from(val.get()) => {
return Some(val);
}
Ok(LitKind::Byte(val)) => return Some(val),
Ok(LitKind::ByteStr(..)) => {
guar.get_or_insert_with(|| {
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true })
});
}
_ => {
guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, expr.span, true));
}
};
2022-10-31 18:30:09 +00:00
}
ExprKind::Array(_) | ExprKind::Repeat(_, _) => {
guar.get_or_insert_with(|| {
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
});
}
ExprKind::IncludedBytes(..) => {
guar.get_or_insert_with(|| {
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
});
}
_ => missing_literals.push(expr.span),
}
None
}
2024-04-25 21:56:48 +00:00
pub(crate) fn expand_concat_bytes(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'static> {
let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else {
return ExpandResult::Retry(());
};
let es = match mac {
Ok(es) => es,
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
};
let mut accumulator = Vec::new();
let mut missing_literals = vec![];
let mut guar = None;
for e in es {
match &e.kind {
ExprKind::Array(exprs) => {
for expr in exprs {
if let Some(elem) =
handle_array_element(cx, &mut guar, &mut missing_literals, expr)
{
accumulator.push(elem);
}
}
}
ExprKind::Repeat(expr, count) => {
if let ExprKind::Lit(token_lit) = count.value.kind
&& let Ok(LitKind::Int(count_val, _)) = LitKind::from_token_lit(token_lit)
{
if let Some(elem) =
handle_array_element(cx, &mut guar, &mut missing_literals, expr)
{
2024-01-17 23:40:30 +00:00
for _ in 0..count_val.get() {
accumulator.push(elem);
}
}
} else {
guar = Some(
cx.dcx().emit_err(errors::ConcatBytesBadRepeat { span: count.value.span }),
);
}
}
&ExprKind::Lit(token_lit) => match LitKind::from_token_lit(token_lit) {
Ok(LitKind::Byte(val)) => {
accumulator.push(val);
}
Ok(LitKind::ByteStr(ref bytes, _)) => {
accumulator.extend_from_slice(bytes);
}
_ => {
guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, e.span, false));
}
},
ExprKind::IncludedBytes(bytes) => {
2022-10-31 18:30:09 +00:00
accumulator.extend_from_slice(bytes);
}
ExprKind::Err(guarantee) => {
guar = Some(*guarantee);
}
ExprKind::Dummy => cx.dcx().span_bug(e.span, "concatenating `ExprKind::Dummy`"),
_ => {
missing_literals.push(e.span);
}
}
}
ExpandResult::Ready(if !missing_literals.is_empty() {
let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
} else if let Some(guar) = guar {
MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
} else {
let sp = cx.with_def_site_ctxt(sp);
MacEager::expr(cx.expr_byte_str(sp, accumulator))
})
}