{"id":"595d1ab25ad2f974","repo":"rust-lang/rust","slug":"non-is-byte-literal-paired-with-nonasciicharinbyte","errorCode":null,"errorMessage":"non-is_byte literal paired with NonAsciiCharInByte","messagePattern":"non-is_byte literal paired with NonAsciiCharInByte","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_parse/src/lexer/unescape_error_reporting.rs","lineNumber":195,"sourceCode":"\n                foreign_escape_suggestion(&mut diag, (&ec, span), err_span);\n            }\n            diag.emit()\n        }\n        EscapeError::TooShortHexEscape => dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)),\n        EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {\n            let (c, span) = last_char();\n            let is_hex = error == EscapeError::InvalidCharInHexEscape;\n            let ch = escaped_char(c);\n            dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch })\n        }\n        EscapeError::NonAsciiCharInByte => {\n            let (c, span) = last_char();\n            let desc = match mode {\n                Mode::Byte => \"byte literal\",\n                Mode::ByteStr => \"byte string literal\",\n                Mode::RawByteStr => \"raw byte string literal\",\n                _ => panic!(\"non-is_byte literal paired with NonAsciiCharInByte\"),\n            };\n            let mut err = dcx.struct_span_err(span, format!(\"non-ASCII character in {desc}\"));\n            let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {\n                format!(\" but is {c:?}\")\n            } else {\n                String::new()\n            };\n            err.span_label(span, format!(\"must be ASCII{postfix}\"));\n            // Note: the \\\\xHH suggestions are not given for raw byte string\n            // literals, because they are araw and so cannot use any escapes.\n            if (c as u32) <= 0xFF && mode != Mode::RawByteStr {\n                err.span_suggestion_verbose(\n                    span,\n                    format!(\n                        \"if you meant to use the unicode code point for {c:?}, use a \\\\xHH escape\"\n                    ),\n                    format!(\"\\\\x{:X}\", c as u32),\n                    Applicability::MaybeIncorrect,","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs#L177-L213","documentation":"Internal invariant in escape-error reporting. `EscapeError::NonAsciiCharInByte` can only originate from byte-mode literals (`b'…'`, `b\"…\"`, `br\"…\"`), so the `match mode` arm handling it asserts the mode is one of `Byte`/`ByteStr`/`RawByteStr`. If the literal mode is `Str`, `Char`, or `RawStr`, the (mode, error) pair is inconsistent and the compiler panics — non-ASCII chars are legal in unicode string/char literals.","triggerScenarios":"The internal escape-error reporting path is invoked with `EscapeError::NonAsciiCharInByte` while passing a non-byte `Mode` (`Str`/`Char`/`RawStr`). Not reachable through well-formed user source.","commonSituations":"A compiler-internal regression after refactoring literal-mode handling; proc-macro or lint code that re-runs unescape with the wrong mode. Not something end users cause by writing Rust.","solutions":["Report as a rustc ICE with the source literal and backtrace","Bisect toolchains to find the regressing commit","As a temporary workaround, change the byte literal to a regular string literal if you can isolate the trigger"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn literal_is_ascii_byte_candidate(lit: &str) -> bool {\n    // only single ASCII chars belong in b'...' / b\"...\" literals\n    lit.is_ascii() && (lit.len() == 1 || (lit.starts_with('\\\\') && lit.len() == 2))\n}\n// Only pair NonAsciiCharInByte diagnostic with literals where is_byte == true\nif kind == NonAsciiCharInByte && !literal_is_ascii_byte_candidate(text) { return Ok(()); }","typeGuard":"pub fn is_byte_literal_text(s: &str) -> bool {\n    s.is_ascii() && s.len() == 1\n}","tryCatchPattern":null,"preventionTips":["When reporting NonAsciiCharInByte, ensure the literal under the span is a byte literal (b'...'/b\"...\") — never a char or string literal.","Keep the 'is_byte' flag attached to the literal node when walking it, so you never mis-pair a non-byte literal with a byte-only diagnostic.","Pre-filter non-ASCII characters in source: byte literals can only contain ASCII or byte escapes.","Do not reuse a diagnostic enum value (NonAsciiCharInByte) across literal kinds; map per-kind."],"tags":["compiler-ice","lexer","escape-sequences","byte-literals"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}