diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 6f93f8ac943..1d8c984d116 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -102,7 +102,7 @@ use stdx::impl_from; use syntax::{ ast::{self, HasName}, - match_ast, AstNode, SyntaxNode, + AstNode, SyntaxNode, }; use crate::{db::HirDatabase, InFile}; @@ -132,13 +132,10 @@ impl SourceToDefCtx<'_, '_> { pub(super) fn module_to_def(&mut self, src: InFile) -> Option { let _p = profile::span("module_to_def"); - let parent_declaration = - src.syntax().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1).find_map( - |it| { - let m = ast::Module::cast(it.value.clone())?; - Some(it.with_value(m)) - }, - ); + let parent_declaration = src + .syntax() + .ancestors_with_macros_skip_attr_item(self.db.upcast()) + .find_map(|it| it.map(ast::Module::cast).transpose()); let parent_module = match parent_declaration { Some(parent_declaration) => self.module_to_def(parent_declaration), @@ -150,7 +147,7 @@ pub(super) fn module_to_def(&mut self, src: InFile) -> Option) -> Option) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { + for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) { if let Some(res) = self.container_to_def(container) { return Some(res); } @@ -348,70 +345,62 @@ pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option) -> Option { - let cont = match_ast! { - match (container.value) { - ast::Module(it) => { - let def = self.module_to_def(container.with_value(it))?; - def.into() - }, - ast::Trait(it) => { - let def = self.trait_to_def(container.with_value(it))?; - def.into() - }, - ast::Impl(it) => { - let def = self.impl_to_def(container.with_value(it))?; - def.into() - }, - ast::Fn(it) => { - let def = self.fn_to_def(container.with_value(it))?; - DefWithBodyId::from(def).into() - }, - ast::Struct(it) => { + let cont = if let Some(item) = ast::Item::cast(container.value.clone()) { + match item { + ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(), + ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), + ast::Item::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), + ast::Item::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), + ast::Item::TypeAlias(it) => { + self.type_alias_to_def(container.with_value(it))?.into() + } + ast::Item::Struct(it) => { let def = self.struct_to_def(container.with_value(it))?; VariantId::from(def).into() - }, - ast::Enum(it) => { - let def = self.enum_to_def(container.with_value(it))?; - def.into() - }, - ast::Union(it) => { + } + ast::Item::Union(it) => { let def = self.union_to_def(container.with_value(it))?; VariantId::from(def).into() - }, - ast::Static(it) => { + } + ast::Item::Fn(it) => { + let def = self.fn_to_def(container.with_value(it))?; + DefWithBodyId::from(def).into() + } + ast::Item::Static(it) => { let def = self.static_to_def(container.with_value(it))?; DefWithBodyId::from(def).into() - }, - ast::Const(it) => { + } + ast::Item::Const(it) => { let def = self.const_to_def(container.with_value(it))?; DefWithBodyId::from(def).into() - }, - ast::TypeAlias(it) => { - let def = self.type_alias_to_def(container.with_value(it))?; - def.into() - }, - ast::Variant(it) => { - let def = self.enum_variant_to_def(container.with_value(it))?; - VariantId::from(def).into() - }, + } _ => return None, } + } else { + let it = ast::Variant::cast(container.value)?; + let def = self.enum_variant_to_def(InFile::new(container.file_id, it))?; + VariantId::from(def).into() }; Some(cont) } fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { - let res: GenericDefId = match_ast! { - match (container.value) { - ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), - ast::Struct(it) => self.struct_to_def(container.with_value(it))?.into(), - ast::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), - ast::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), - ast::TypeAlias(it) => self.type_alias_to_def(container.with_value(it))?.into(), - ast::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), - _ => continue, + let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + for InFile { file_id, value } in ancestors { + let item = match ast::Item::cast(value) { + Some(it) => it, + None => continue, + }; + let res: GenericDefId = match item { + ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(), + ast::Item::TypeAlias(it) => { + self.type_alias_to_def(InFile::new(file_id, it))?.into() } + ast::Item::Impl(it) => self.impl_to_def(InFile::new(file_id, it))?.into(), + _ => continue, }; return Some(res); } @@ -419,14 +408,17 @@ fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { - let res: DefWithBodyId = match_ast! { - match (container.value) { - ast::Const(it) => self.const_to_def(container.with_value(it))?.into(), - ast::Static(it) => self.static_to_def(container.with_value(it))?.into(), - ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), - _ => continue, - } + let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + for InFile { file_id, value } in ancestors { + let item = match ast::Item::cast(value) { + Some(it) => it, + None => continue, + }; + let res: DefWithBodyId = match item { + ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Static(it) => self.static_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), + _ => continue, }; return Some(res); } diff --git a/crates/hir_expand/src/builtin_fn_macro.rs b/crates/hir_expand/src/builtin_fn_macro.rs index da76b6b0804..f69742971e3 100644 --- a/crates/hir_expand/src/builtin_fn_macro.rs +++ b/crates/hir_expand/src/builtin_fn_macro.rs @@ -4,7 +4,10 @@ use cfg::CfgExpr; use either::Either; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; -use syntax::ast::{self, AstToken}; +use syntax::{ + ast::{self, AstToken}, + SmolStr, +}; use crate::{ db::AstDatabase, name, quote, AstId, CrateId, ExpandError, ExpandResult, MacroCallId, @@ -130,6 +133,9 @@ pub fn find_builtin_macro( (option_env, OptionEnv) => option_env_expand } +const DOLLAR_CRATE: tt::Ident = + tt::Ident { text: SmolStr::new_inline("$crate"), id: tt::TokenId::unspecified() }; + fn module_path_expand( _db: &dyn AstDatabase, _id: MacroCallId, @@ -202,7 +208,6 @@ fn assert_expand( _id: MacroCallId, tt: &tt::Subtree, ) -> ExpandResult { - let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; let args = parse_exprs_with_sep(tt, ','); let expanded = match &*args { [cond, panic_args @ ..] => { @@ -218,7 +223,7 @@ fn assert_expand( let panic_args = itertools::Itertools::intersperse(panic_args.iter().cloned(), comma); quote! {{ if !#cond { - #krate::panic!(##panic_args); + #DOLLAR_CRATE::panic!(##panic_args); } }} } @@ -293,15 +298,13 @@ fn asm_expand( // We expand all assembly snippets to `format_args!` invocations to get format syntax // highlighting for them. - let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; - let mut literals = Vec::new(); for tt in tt.token_trees.chunks(2) { match tt { [tt::TokenTree::Leaf(tt::Leaf::Literal(lit))] | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', id: _, spacing: _ }))] => { - let krate = krate.clone(); + let krate = DOLLAR_CRATE.clone(); literals.push(quote!(#krate::format_args!(#lit);)); } _ => break, @@ -343,11 +346,10 @@ fn panic_expand( ) -> ExpandResult { let loc: MacroCallLoc = db.lookup_intern_macro_call(id); // Expand to a macro call `$crate::panic::panic_{edition}` - let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; let mut call = if db.crate_graph()[loc.krate].edition >= Edition::Edition2021 { - quote!(#krate::panic::panic_2021!) + quote!(#DOLLAR_CRATE::panic::panic_2021!) } else { - quote!(#krate::panic::panic_2015!) + quote!(#DOLLAR_CRATE::panic::panic_2015!) }; // Pass the original arguments @@ -362,11 +364,10 @@ fn unreachable_expand( ) -> ExpandResult { let loc: MacroCallLoc = db.lookup_intern_macro_call(id); // Expand to a macro call `$crate::panic::unreachable_{edition}` - let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; let mut call = if db.crate_graph()[loc.krate].edition >= Edition::Edition2021 { - quote!(#krate::panic::unreachable_2021!) + quote!(#DOLLAR_CRATE::panic::unreachable_2021!) } else { - quote!(#krate::panic::unreachable_2015!) + quote!(#DOLLAR_CRATE::panic::unreachable_2015!) }; // Pass the original arguments diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index bdb01ca1701..99cb493f327 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs @@ -712,7 +712,7 @@ pub fn ancestors_with_macros_skip_attr_item( self, db: &dyn db::AstDatabase, ) -> impl Iterator> + '_ { - iter::successors(Some(self.cloned()), move |node| match node.value.parent() { + let succ = move |node: &InFile| match node.value.parent() { Some(parent) => Some(node.with_value(parent)), None => { let parent_node = node.file_id.call_node(db)?; @@ -724,7 +724,8 @@ pub fn ancestors_with_macros_skip_attr_item( Some(parent_node) } } - }) + }; + iter::successors(succ(&self.cloned()), succ) } /// Falls back to the macro call range if the node cannot be mapped up fully. diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 9d05db4a77c..c83193580fb 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -150,9 +150,9 @@ pub fn classify_lifetime( sema: &Semantics, lifetime: &ast::Lifetime, ) -> Option { - NameClass::classify_lifetime(sema, &lifetime).map(IdentClass::NameClass).or_else(|| { - NameRefClass::classify_lifetime(sema, &lifetime).map(IdentClass::NameRefClass) - }) + NameRefClass::classify_lifetime(sema, &lifetime) + .map(IdentClass::NameRefClass) + .or_else(|| NameClass::classify_lifetime(sema, &lifetime).map(IdentClass::NameClass)) } pub fn definitions(self) -> ArrayVec {