From de5c5065fcf060bef155043db12b439fe605591b Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 7 Mar 2025 11:17:39 +0000 Subject: [PATCH 1/2] update to literal-escaper 0.0.4 for better API without `unreachable` and faster string parsing --- src/tools/rust-analyzer/Cargo.lock | 8 +- src/tools/rust-analyzer/Cargo.toml | 2 +- .../crates/hir-expand/src/attrs.rs | 25 ++-- .../crates/hir-expand/src/builtin/fn_macro.rs | 14 +- .../crates/parser/src/lexed_str.rs | 131 ++++++++---------- .../crates/syntax/src/ast/token_ext.rs | 94 ++++++------- .../crates/syntax/src/validation.rs | 28 ++-- 7 files changed, 137 insertions(+), 165 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c2b4e21483e7..195d2771b02c 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1467,7 +1467,7 @@ dependencies = [ "edition", "expect-test", "ra-ap-rustc_lexer", - "rustc-literal-escaper 0.0.3", + "rustc-literal-escaper 0.0.4", "stdx", "tracing", ] @@ -1936,9 +1936,9 @@ checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" [[package]] name = "rustc-literal-escaper" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78744cd17f5d01c75b709e49807d1363e02a940ccee2e9e72435843fdb0d076e" +checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b" [[package]] name = "rustc-stable-hash" @@ -2216,7 +2216,7 @@ dependencies = [ "rayon", "rowan", "rustc-hash 2.1.1", - "rustc-literal-escaper 0.0.3", + "rustc-literal-escaper 0.0.4", "rustc_apfloat", "smol_str", "stdx", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index c791d741b026..1b609c8ad82c 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -143,7 +143,7 @@ serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } serde_json = "1.0.140" rustc-hash = "2.1.1" -rustc-literal-escaper = "0.0.3" +rustc-literal-escaper = "0.0.4" smallvec = { version = "1.15.1", features = [ "const_new", "union", diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 94c97713f065..986f8764f5c9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -433,20 +433,19 @@ fn unescape(s: &str) -> Option> { let mut buf = String::new(); let mut prev_end = 0; let mut has_error = false; - unescape::unescape_unicode(s, unescape::Mode::Str, &mut |char_range, unescaped_char| match ( - unescaped_char, - buf.capacity() == 0, - ) { - (Ok(c), false) => buf.push(c), - (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { - prev_end = char_range.end + unescape::unescape_str(s, |char_range, unescaped_char| { + match (unescaped_char, buf.capacity() == 0) { + (Ok(c), false) => buf.push(c), + (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { + prev_end = char_range.end + } + (Ok(c), true) => { + buf.reserve_exact(s.len()); + buf.push_str(&s[..prev_end]); + buf.push(c); + } + (Err(_), _) => has_error = true, } - (Ok(c), true) => { - buf.reserve_exact(s.len()); - buf.push_str(&s[..prev_end]); - buf.push(c); - } - (Err(_), _) => has_error = true, }); match (has_error, buf.capacity() == 0) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 3180b8dae10e..f9abe4f5566e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -12,7 +12,7 @@ use span::{Edition, FileId, Span}; use stdx::format_to; use syntax::{ format_smolstr, - unescape::{Mode, unescape_byte, unescape_char, unescape_unicode}, + unescape::{unescape_byte, unescape_char, unescape_str}, }; use syntax_bridge::syntax_node_to_token_tree; @@ -430,7 +430,7 @@ fn compile_error_expand( kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), suffix: _, })), - ] => ExpandError::other(span, Box::from(unescape_str(text).as_str())), + ] => ExpandError::other(span, Box::from(unescape_symbol(text).as_str())), _ => ExpandError::other(span, "`compile_error!` argument must be a string"), }; @@ -481,7 +481,7 @@ fn concat_expand( format_to!(text, "{}", it.symbol.as_str()) } tt::LitKind::Str => { - text.push_str(unescape_str(&it.symbol).as_str()); + text.push_str(unescape_symbol(&it.symbol).as_str()); record_span(it.span); } tt::LitKind::StrRaw(_) => { @@ -691,7 +691,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> { span, kind: tt::LitKind::Str, suffix: _, - })) => Ok((unescape_str(text), *span)), + })) => Ok((unescape_symbol(text), *span)), TtElement::Leaf(tt::Leaf::Literal(tt::Literal { symbol: text, span, @@ -712,7 +712,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> { span, kind: tt::LitKind::Str, suffix: _, - })) => Some((unescape_str(text), *span)), + })) => Some((unescape_symbol(text), *span)), TtElement::Leaf(tt::Leaf::Literal(tt::Literal { symbol: text, span, @@ -897,11 +897,11 @@ fn quote_expand( ) } -fn unescape_str(s: &Symbol) -> Symbol { +fn unescape_symbol(s: &Symbol) -> Symbol { if s.as_str().contains('\\') { let s = s.as_str(); let mut buf = String::with_capacity(s.len()); - unescape_unicode(s, Mode::Str, &mut |_, c| { + unescape_str(s, |_, c| { if let Ok(c) = c { buf.push(c) } diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index 0fa9a264545d..e6c92dec6810 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -11,7 +11,8 @@ use std::ops; use rustc_literal_escaper::{ - EscapeError, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, + EscapeError, Mode, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, + unescape_str, }; use crate::{ @@ -151,14 +152,14 @@ impl<'a> Converter<'a> { self.res } - fn push(&mut self, kind: SyntaxKind, len: usize, err: Option<&str>) { + fn push(&mut self, kind: SyntaxKind, len: usize, errors: Vec) { self.res.push(kind, self.offset); self.offset += len; - if let Some(err) = err { - let token = self.res.len() as u32; - let msg = err.to_owned(); - self.res.error.push(LexError { msg, token }); + for msg in errors { + if !msg.is_empty() { + self.res.error.push(LexError { msg, token: self.res.len() as u32 }); + } } } @@ -167,14 +168,16 @@ impl<'a> Converter<'a> { // We drop some useful information here (see patterns with double dots `..`) // Storing that info in `SyntaxKind` is not possible due to its layout requirements of // being `u16` that come from `rowan::SyntaxKind`. - let mut err = ""; + let mut errors: Vec = vec![]; let syntax_kind = { match kind { rustc_lexer::TokenKind::LineComment { doc_style: _ } => COMMENT, rustc_lexer::TokenKind::BlockComment { doc_style: _, terminated } => { if !terminated { - err = "Missing trailing `*/` symbols to terminate the block comment"; + errors.push( + "Missing trailing `*/` symbols to terminate the block comment".into(), + ); } COMMENT } @@ -184,9 +187,9 @@ impl<'a> Converter<'a> { invalid_infostring, } => { if *has_invalid_preceding_whitespace { - err = "invalid preceding whitespace for frontmatter opening" + errors.push("invalid preceding whitespace for frontmatter opening".into()); } else if *invalid_infostring { - err = "invalid infostring for frontmatter" + errors.push("invalid infostring for frontmatter".into()); } FRONTMATTER } @@ -198,7 +201,7 @@ impl<'a> Converter<'a> { SyntaxKind::from_keyword(token_text, self.edition).unwrap_or(IDENT) } rustc_lexer::TokenKind::InvalidIdent => { - err = "Ident contains invalid characters"; + errors.push("Ident contains invalid characters".into()); IDENT } @@ -206,7 +209,7 @@ impl<'a> Converter<'a> { rustc_lexer::TokenKind::GuardedStrPrefix if self.edition.at_least_2024() => { // FIXME: rustc does something better for recovery. - err = "Invalid string literal (reserved syntax)"; + errors.push("Invalid string literal (reserved syntax)".into()); ERROR } rustc_lexer::TokenKind::GuardedStrPrefix => { @@ -222,12 +225,12 @@ impl<'a> Converter<'a> { rustc_lexer::TokenKind::Lifetime { starts_with_number } => { if *starts_with_number { - err = "Lifetime name cannot start with a number"; + errors.push("Lifetime name cannot start with a number".into()); } LIFETIME_IDENT } rustc_lexer::TokenKind::UnknownPrefixLifetime => { - err = "Unknown lifetime prefix"; + errors.push("Unknown lifetime prefix".into()); LIFETIME_IDENT } rustc_lexer::TokenKind::RawLifetime => LIFETIME_IDENT, @@ -262,119 +265,128 @@ impl<'a> Converter<'a> { rustc_lexer::TokenKind::Unknown => ERROR, rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT, rustc_lexer::TokenKind::UnknownPrefix => { - err = "unknown literal prefix"; + errors.push("unknown literal prefix".into()); IDENT } rustc_lexer::TokenKind::Eof => EOF, } }; - let err = if err.is_empty() { None } else { Some(err) }; - self.push(syntax_kind, token_text.len(), err); + self.push(syntax_kind, token_text.len(), errors); } fn extend_literal(&mut self, len: usize, kind: &rustc_lexer::LiteralKind) { - let mut err = ""; + let invalid_raw_msg = String::from("Invalid raw string literal"); + + let mut errors = vec![]; + let mut no_end_quote = |c: char, kind: &str| { + errors.push(format!("Missing trailing `{c}` symbol to terminate the {kind} literal")); + }; let syntax_kind = match *kind { rustc_lexer::LiteralKind::Int { empty_int, base: _ } => { if empty_int { - err = "Missing digits after the integer base prefix"; + errors.push("Missing digits after the integer base prefix".into()); } INT_NUMBER } rustc_lexer::LiteralKind::Float { empty_exponent, base: _ } => { if empty_exponent { - err = "Missing digits after the exponent symbol"; + errors.push("Missing digits after the exponent symbol".into()); } FLOAT_NUMBER } rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { - err = "Missing trailing `'` symbol to terminate the character literal"; + no_end_quote('\'', "character"); } else { let text = &self.res.text[self.offset + 1..][..len - 1]; - let i = text.rfind('\'').unwrap(); - let text = &text[..i]; + let text = &text[..text.rfind('\'').unwrap()]; if let Err(e) = unescape_char(text) { - err = error_to_diagnostic_message(e, Mode::Char); + errors.push(err_to_msg(e, Mode::Char)); } } CHAR } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { - err = "Missing trailing `'` symbol to terminate the byte literal"; + no_end_quote('\'', "byte"); } else { let text = &self.res.text[self.offset + 2..][..len - 2]; - let i = text.rfind('\'').unwrap(); - let text = &text[..i]; + let text = &text[..text.rfind('\'').unwrap()]; if let Err(e) = unescape_byte(text) { - err = error_to_diagnostic_message(e, Mode::Byte); + errors.push(err_to_msg(e, Mode::Byte)); } } - BYTE } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - err = "Missing trailing `\"` symbol to terminate the string literal"; + no_end_quote('"', "string"); } else { let text = &self.res.text[self.offset + 1..][..len - 1]; - let i = text.rfind('"').unwrap(); - let text = &text[..i]; - err = unescape_string_error_message(text, Mode::Str); + let text = &text[..text.rfind('"').unwrap()]; + unescape_str(text, |_, res| { + if let Err(e) = res { + errors.push(err_to_msg(e, Mode::Str)); + } + }); } STRING } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { - err = "Missing trailing `\"` symbol to terminate the byte string literal"; + no_end_quote('"', "byte string"); } else { let text = &self.res.text[self.offset + 2..][..len - 2]; - let i = text.rfind('"').unwrap(); - let text = &text[..i]; - err = unescape_string_error_message(text, Mode::ByteStr); + let text = &text[..text.rfind('"').unwrap()]; + unescape_byte_str(text, |_, res| { + if let Err(e) = res { + errors.push(err_to_msg(e, Mode::ByteStr)); + } + }); } BYTE_STRING } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { - err = "Missing trailing `\"` symbol to terminate the string literal"; + no_end_quote('"', "C string") } else { let text = &self.res.text[self.offset + 2..][..len - 2]; - let i = text.rfind('"').unwrap(); - let text = &text[..i]; - err = unescape_string_error_message(text, Mode::CStr); + let text = &text[..text.rfind('"').unwrap()]; + unescape_c_str(text, |_, res| { + if let Err(e) = res { + errors.push(err_to_msg(e, Mode::CStr)); + } + }); } C_STRING } rustc_lexer::LiteralKind::RawStr { n_hashes } => { if n_hashes.is_none() { - err = "Invalid raw string literal"; + errors.push(invalid_raw_msg); } STRING } rustc_lexer::LiteralKind::RawByteStr { n_hashes } => { if n_hashes.is_none() { - err = "Invalid raw string literal"; + errors.push(invalid_raw_msg); } BYTE_STRING } rustc_lexer::LiteralKind::RawCStr { n_hashes } => { if n_hashes.is_none() { - err = "Invalid raw string literal"; + errors.push(invalid_raw_msg); } C_STRING } }; - let err = if err.is_empty() { None } else { Some(err) }; - self.push(syntax_kind, len, err); + self.push(syntax_kind, len, errors); } } -fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { +fn err_to_msg(error: EscapeError, mode: Mode) -> String { match error { EscapeError::ZeroChars => "empty character literal", EscapeError::MoreThanOneChar => "character literal may only contain one codepoint", @@ -410,28 +422,5 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { EscapeError::UnskippedWhitespaceWarning => "", EscapeError::MultipleSkippedLinesWarning => "", } -} - -fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { - let mut error_message = ""; - match mode { - Mode::CStr => { - unescape_mixed(text, mode, &mut |_, res| { - if let Err(e) = res { - error_message = error_to_diagnostic_message(e, mode); - } - }); - } - Mode::ByteStr | Mode::Str => { - unescape_unicode(text, mode, &mut |_, res| { - if let Err(e) = res { - error_message = error_to_diagnostic_message(e, mode); - } - }); - } - _ => { - // Other Modes are not supported yet or do not apply - } - } - error_message + .into() } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index ced3b713d8d5..4afdda78a0e7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -1,9 +1,11 @@ //! There are many AstNodes, but only a few tokens, so we hand-write them here. +use std::ops::Range; use std::{borrow::Cow, num::ParseIntError}; use rustc_literal_escaper::{ - EscapeError, MixedUnit, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, + EscapeError, MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, + unescape_str, }; use stdx::always; @@ -150,7 +152,7 @@ impl QuoteOffsets { pub trait IsString: AstToken { const RAW_PREFIX: &'static str; - const MODE: Mode; + fn unescape(s: &str, callback: impl FnMut(Range, Result)); fn is_raw(&self) -> bool { self.text().starts_with(Self::RAW_PREFIX) } @@ -185,7 +187,7 @@ pub trait IsString: AstToken { let text = &self.text()[text_range_no_quotes - start]; let offset = text_range_no_quotes.start() - start; - unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| { + Self::unescape(text, &mut |range: Range, unescaped_char| { if let Some((s, e)) = range.start.try_into().ok().zip(range.end.try_into().ok()) { cb(TextRange::new(s, e) + offset, unescaped_char); } @@ -203,7 +205,9 @@ pub trait IsString: AstToken { impl IsString for ast::String { const RAW_PREFIX: &'static str = "r"; - const MODE: Mode = Mode::Str; + fn unescape(s: &str, cb: impl FnMut(Range, Result)) { + unescape_str(s, cb) + } } impl ast::String { @@ -218,20 +222,19 @@ impl ast::String { let mut buf = String::new(); let mut prev_end = 0; let mut has_error = None; - unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( - unescaped_char, - buf.capacity() == 0, - ) { - (Ok(c), false) => buf.push(c), - (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { - prev_end = char_range.end + unescape_str(text, |char_range, unescaped_char| { + match (unescaped_char, buf.capacity() == 0) { + (Ok(c), false) => buf.push(c), + (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { + prev_end = char_range.end + } + (Ok(c), true) => { + buf.reserve_exact(text.len()); + buf.push_str(&text[..prev_end]); + buf.push(c); + } + (Err(e), _) => has_error = Some(e), } - (Ok(c), true) => { - buf.reserve_exact(text.len()); - buf.push_str(&text[..prev_end]); - buf.push(c); - } - (Err(e), _) => has_error = Some(e), }); match (has_error, buf.capacity() == 0) { @@ -244,7 +247,9 @@ impl ast::String { impl IsString for ast::ByteString { const RAW_PREFIX: &'static str = "br"; - const MODE: Mode = Mode::ByteStr; + fn unescape(s: &str, mut callback: impl FnMut(Range, Result)) { + unescape_byte_str(s, |range, res| callback(range, res.map(char::from))) + } } impl ast::ByteString { @@ -259,20 +264,19 @@ impl ast::ByteString { let mut buf: Vec = Vec::new(); let mut prev_end = 0; let mut has_error = None; - unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( - unescaped_char, - buf.capacity() == 0, - ) { - (Ok(c), false) => buf.push(c as u8), - (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { - prev_end = char_range.end + unescape_byte_str(text, |char_range, unescaped_byte| { + match (unescaped_byte, buf.capacity() == 0) { + (Ok(b), false) => buf.push(b), + (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { + prev_end = char_range.end + } + (Ok(b), true) => { + buf.reserve_exact(text.len()); + buf.extend_from_slice(&text.as_bytes()[..prev_end]); + buf.push(b); + } + (Err(e), _) => has_error = Some(e), } - (Ok(c), true) => { - buf.reserve_exact(text.len()); - buf.extend_from_slice(&text.as_bytes()[..prev_end]); - buf.push(c as u8); - } - (Err(e), _) => has_error = Some(e), }); match (has_error, buf.capacity() == 0) { @@ -285,25 +289,10 @@ impl ast::ByteString { impl IsString for ast::CString { const RAW_PREFIX: &'static str = "cr"; - const MODE: Mode = Mode::CStr; - - fn escaped_char_ranges(&self, cb: &mut dyn FnMut(TextRange, Result)) { - let text_range_no_quotes = match self.text_range_between_quotes() { - Some(it) => it, - None => return, - }; - - let start = self.syntax().text_range().start(); - let text = &self.text()[text_range_no_quotes - start]; - let offset = text_range_no_quotes.start() - start; - - unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| { - let text_range = - TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); - // XXX: This method should only be used for highlighting ranges. The unescaped - // char/byte is not used. For simplicity, we return an arbitrary placeholder char. - cb(text_range + offset, unescaped_char.map(|_| ' ')); - }); + // NOTE: This method should only be used for highlighting ranges. The unescaped + // char/byte is not used. For simplicity, we return an arbitrary placeholder char. + fn unescape(s: &str, mut callback: impl FnMut(Range, Result)) { + unescape_c_str(s, |range, _res| callback(range, Ok('_'))) } } @@ -323,10 +312,7 @@ impl ast::CString { MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), MixedUnit::HighByte(b) => buf.push(b), }; - unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match ( - unescaped, - buf.capacity() == 0, - ) { + unescape_c_str(text, |char_range, unescaped| match (unescaped, buf.capacity() == 0) { (Ok(u), false) => extend_unit(&mut buf, u), (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => { prev_end = char_range.end diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 5bfeb3bff87a..4180f9cd1855 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -6,7 +6,9 @@ mod block; use itertools::Itertools; use rowan::Direction; -use rustc_literal_escaper::{self, EscapeError, Mode, unescape_mixed, unescape_unicode}; +use rustc_literal_escaper::{ + EscapeError, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, +}; use crate::{ AstNode, SyntaxError, @@ -47,7 +49,7 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { } fn rustc_unescape_error_to_string(err: EscapeError) -> (&'static str, bool) { - use rustc_literal_escaper::EscapeError as EE; + use EscapeError as EE; #[rustfmt::skip] let err_message = match err { @@ -142,7 +144,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::String(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 1, '"') { - unescape_unicode(without_quotes, Mode::Str, &mut |range, char| { + unescape_str(without_quotes, |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -153,7 +155,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::ByteString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_byte_str(without_quotes, |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -164,7 +166,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::CString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| { + unescape_c_str(without_quotes, |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -174,20 +176,16 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { } ast::LiteralKind::Char(_) => { if let Some(without_quotes) = unquote(text, 1, '\'') { - unescape_unicode(without_quotes, Mode::Char, &mut |range, char| { - if let Err(err) = char { - push_err(1, range.start, err); - } - }); + if let Err(err) = unescape_char(without_quotes) { + push_err(1, 0, err); + } } } ast::LiteralKind::Byte(_) => { if let Some(without_quotes) = unquote(text, 2, '\'') { - unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| { - if let Err(err) = char { - push_err(2, range.start, err); - } - }); + if let Err(err) = unescape_byte(without_quotes) { + push_err(2, 0, err); + } } } ast::LiteralKind::IntNumber(_) From 74e92a88013c2174af4a2ff38b128c9c6a18bce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 16 Jun 2025 15:33:48 +0300 Subject: [PATCH 2/2] Format goto_type_definition --- .../rust-analyzer/crates/ide/src/goto_type_definition.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index 9781e7116dec..c58e51487b72 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -70,11 +70,10 @@ pub(crate) fn goto_type_definition( } let range = token.text_range(); - sema.descend_into_macros_no_opaque(token,false) + sema.descend_into_macros_no_opaque(token, false) .into_iter() .filter_map(|token| { - sema - .token_ancestors_with_macros(token.value) + sema.token_ancestors_with_macros(token.value) // When `token` is within a macro call, we can't determine its type. Don't continue // this traversal because otherwise we'll end up returning the type of *that* macro // call, which is not what we want in general. @@ -103,7 +102,6 @@ pub(crate) fn goto_type_definition( _ => return None, } }; - Some(ty) }) })