diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /src/tools/rust-analyzer/crates/hir-expand | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-expand')
5 files changed, 47 insertions, 178 deletions
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 4c918e55b..0ec2422b3 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -342,14 +342,7 @@ fn inner_attributes( ast::Impl(it) => it.assoc_item_list()?.syntax().clone(), ast::Module(it) => it.item_list()?.syntax().clone(), ast::BlockExpr(it) => { - use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT}; - // Block expressions accept outer and inner attributes, but only when they are the outer - // expression of an expression statement or the final expression of another block expression. - let may_carry_attributes = matches!( - it.syntax().parent().map(|it| it.kind()), - Some(BLOCK_EXPR | EXPR_STMT) - ); - if !may_carry_attributes { + if !it.may_carry_attributes() { return None } syntax.clone() 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 95c6baf42..30b19b6e5 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 @@ -1,13 +1,9 @@ //! Builtin macro -use std::mem; - -use ::tt::Ident; use base_db::{AnchoredPath, Edition, FileId}; use cfg::CfgExpr; use either::Either; use mbe::{parse_exprs_with_sep, parse_to_token_tree, TokenMap}; -use rustc_hash::FxHashMap; use syntax::{ ast::{self, AstToken}, SmolStr, @@ -97,11 +93,11 @@ register_builtin! { (unreachable, Unreachable) => unreachable_expand, (log_syntax, LogSyntax) => log_syntax_expand, (trace_macros, TraceMacros) => trace_macros_expand, - - EAGER: (format_args, FormatArgs) => format_args_expand, (const_format_args, ConstFormatArgs) => format_args_expand, (format_args_nl, FormatArgsNl) => format_args_nl_expand, + + EAGER: (compile_error, CompileError) => compile_error_expand, (concat, Concat) => concat_expand, (concat_idents, ConcatIdents) => concat_idents_expand, @@ -247,151 +243,15 @@ fn format_args_expand_general( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - end_string: &str, + // FIXME: Make use of this so that mir interpretation works properly + _end_string: &str, ) -> ExpandResult<tt::Subtree> { - let args = parse_exprs_with_sep(tt, ','); - - let expand_error = - ExpandResult::new(tt::Subtree::empty(), mbe::ExpandError::NoMatchingRule.into()); - - let mut key_args = FxHashMap::default(); - let mut args = args.into_iter().filter_map(|mut arg| { - // Remove `key =`. - if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=') - { - // but not with `==` - if !matches!(arg.token_trees.get(2), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=') - { - let key = arg.token_trees.drain(..2).next().unwrap(); - key_args.insert(key.to_string(), arg); - return None; - } - } - Some(arg) - }).collect::<Vec<_>>().into_iter(); - // ^^^^^^^ we need this collect, to enforce the side effect of the filter_map closure (building the `key_args`) - let Some(format_subtree) = args.next() else { - return expand_error; - }; - let format_string = (|| { - let token_tree = format_subtree.token_trees.get(0)?; - match token_tree { - tt::TokenTree::Leaf(l) => match l { - tt::Leaf::Literal(l) => { - if let Some(mut text) = l.text.strip_prefix('r') { - let mut raw_sharps = String::new(); - while let Some(t) = text.strip_prefix('#') { - text = t; - raw_sharps.push('#'); - } - text = - text.strip_suffix(&raw_sharps)?.strip_prefix('"')?.strip_suffix('"')?; - Some((text, l.span, Some(raw_sharps))) - } else { - let text = l.text.strip_prefix('"')?.strip_suffix('"')?; - let span = l.span; - Some((text, span, None)) - } - } - _ => None, - }, - tt::TokenTree::Subtree(_) => None, - } - })(); - let Some((format_string, _format_string_span, raw_sharps)) = format_string else { - return expand_error; - }; - let mut format_iter = format_string.chars().peekable(); - let mut parts = vec![]; - let mut last_part = String::new(); - let mut arg_tts = vec![]; - let mut err = None; - while let Some(c) = format_iter.next() { - // Parsing the format string. See https://doc.rust-lang.org/std/fmt/index.html#syntax for the grammar and more info - match c { - '{' => { - if format_iter.peek() == Some(&'{') { - format_iter.next(); - last_part.push('{'); - continue; - } - let mut argument = String::new(); - while ![Some(&'}'), Some(&':')].contains(&format_iter.peek()) { - argument.push(match format_iter.next() { - Some(c) => c, - None => return expand_error, - }); - } - let format_spec = match format_iter.next().unwrap() { - '}' => "".to_owned(), - ':' => { - let mut s = String::new(); - while let Some(c) = format_iter.next() { - if c == '}' { - break; - } - s.push(c); - } - s - } - _ => unreachable!(), - }; - parts.push(mem::take(&mut last_part)); - let arg_tree = if argument.is_empty() { - match args.next() { - Some(it) => it, - None => { - err = Some(mbe::ExpandError::NoMatchingRule.into()); - tt::Subtree::empty() - } - } - } else if let Some(tree) = key_args.get(&argument) { - tree.clone() - } else { - // FIXME: we should pick the related substring of the `_format_string_span` as the span. You - // can use `.char_indices()` instead of `.char()` for `format_iter` to find the substring interval. - let ident = Ident::new(argument, tt::TokenId::unspecified()); - quote!(#ident) - }; - let formatter = match &*format_spec { - "?" => quote!(::core::fmt::Debug::fmt), - "" => quote!(::core::fmt::Display::fmt), - _ => { - // FIXME: implement the rest and return expand error here - quote!(::core::fmt::Display::fmt) - } - }; - arg_tts.push(quote! { ::core::fmt::ArgumentV1::new(&(#arg_tree), #formatter), }); - } - '}' => { - if format_iter.peek() == Some(&'}') { - format_iter.next(); - last_part.push('}'); - } else { - return expand_error; - } - } - _ => last_part.push(c), - } - } - last_part += end_string; - if !last_part.is_empty() { - parts.push(last_part); - } - let part_tts = parts.into_iter().map(|it| { - let text = if let Some(raw) = &raw_sharps { - format!("r{raw}\"{}\"{raw}", it).into() - } else { - format!("\"{}\"", it).into() - }; - let l = tt::Literal { span: tt::TokenId::unspecified(), text }; - quote!(#l ,) + let pound = quote! {@PUNCT '#'}; + let mut tt = tt.clone(); + tt.delimiter.kind = tt::DelimiterKind::Parenthesis; + return ExpandResult::ok(quote! { + builtin #pound format_args #tt }); - let arg_tts = arg_tts.into_iter().flat_map(|arg| arg.token_trees); - let expanded = quote! { - ::core::fmt::Arguments::new_v1(&[##part_tts], &[##arg_tts]) - }; - ExpandResult { value: expanded, err } } fn asm_expand( @@ -415,10 +275,12 @@ fn asm_expand( } } - let expanded = quote! {{ - ##literals - loop {} - }}; + let pound = quote! {@PUNCT '#'}; + let expanded = quote! { + builtin #pound asm ( + {##literals} + ) + }; ExpandResult::ok(expanded) } @@ -692,7 +554,7 @@ pub(crate) fn include_arg_to_tt( arg_id: MacroCallId, ) -> Result<(triomphe::Arc<(::tt::Subtree<::tt::TokenId>, TokenMap)>, FileId), ExpandError> { let loc = db.lookup_intern_macro_call(arg_id); - let Some(EagerCallInfo { arg,arg_id, .. }) = loc.eager.as_deref() else { + let Some(EagerCallInfo { arg, arg_id, .. }) = loc.eager.as_deref() else { panic!("include_arg_to_tt called on non include macro call: {:?}", &loc.eager); }; let path = parse_string(&arg.0)?; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index ade4a5928..ca65db113 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -242,7 +242,7 @@ impl HygieneFrame { krate, call_site: None, def_site: None, - } + }; }; let def_site = info.attr_input_or_mac_def_start.map(|it| db.hygiene_frame(it.file_id)); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 1f1e20f49..4be55126b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -37,7 +37,7 @@ use either::Either; use syntax::{ algo::{self, skip_trivia_token}, ast::{self, AstNode, HasDocComments}, - AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, + AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize, }; use crate::{ @@ -544,7 +544,7 @@ impl MacroCallKind { }; let range = match kind { - MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(), + MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(), MacroCallKind::Derive { ast_id, derive_attr_index, .. } => { // FIXME: should be the range of the macro name, not the whole derive // FIXME: handle `cfg_attr` @@ -642,6 +642,8 @@ impl ExpansionInfo { db: &dyn db::ExpandDatabase, item: Option<ast::Item>, token: InFile<&SyntaxToken>, + // FIXME: use this for range mapping, so that we can resolve inline format args + _relative_token_offset: Option<TextSize>, ) -> Option<impl Iterator<Item = InFile<SyntaxToken>> + '_> { assert_eq!(token.file_id, self.arg.file_id); let token_id_in_attr_input = if let Some(item) = item { @@ -840,9 +842,6 @@ impl<N: AstIdNode> AstId<N> { pub type ErasedAstId = InFile<ErasedFileAstId>; impl ErasedAstId { - pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode { - self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) - } pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> SyntaxNodePtr { db.ast_id_map(self.file_id).get_raw(self.value) } @@ -1054,16 +1053,6 @@ impl InFile<SyntaxToken> { } } } - - pub fn ancestors_with_macros( - self, - db: &dyn db::ExpandDatabase, - ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ { - self.value.parent().into_iter().flat_map({ - let file_id = self.file_id; - move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db) - }) - } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 7c179c0cf..a876f48bd 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -54,6 +54,12 @@ impl Name { Name(Repr::Text(text)) } + // FIXME: See above, unfortunately some places really need this right now + #[doc(hidden)] + pub const fn new_text_dont_use(text: SmolStr) -> Name { + Name(Repr::Text(text)) + } + pub fn new_tuple_field(idx: usize) -> Name { Name(Repr::TupleField(idx)) } @@ -302,6 +308,16 @@ pub mod known { rust_2018, rust_2021, v1, + new_display, + new_debug, + new_lower_exp, + new_upper_exp, + new_octal, + new_pointer, + new_binary, + new_lower_hex, + new_upper_hex, + from_usize, // Components of known path (type name) Iterator, IntoIterator, @@ -327,6 +343,13 @@ pub mod known { Not, None, Index, + Left, + Right, + Center, + Unknown, + Is, + Param, + Implied, // Components of known path (function name) filter_map, next, @@ -335,6 +358,8 @@ pub mod known { is_empty, as_str, new, + new_v1_formatted, + none, // Builtin macros asm, assert, |