Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/semantics.rs')
| -rw-r--r-- | crates/hir/src/semantics.rs | 107 |
1 files changed, 80 insertions, 27 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1cf22b05e7..34d169cd76 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -30,7 +30,7 @@ use hir_expand::{ name::AsName, ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; -use intern::Symbol; +use intern::{sym, Symbol}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; @@ -49,10 +49,10 @@ use crate::{ semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{name_hygiene, resolve_hir_path, SourceAnalyzer}, Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, - ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile, - InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, - OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, - Type, TypeAlias, TypeParam, Union, Variant, VariantDef, + ConstParam, Crate, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, + HirFileId, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, + Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, + TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, }; const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(()); @@ -246,59 +246,59 @@ impl<DB: HirDatabase> Semantics<'_, DB> { } pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> { - self.imp.to_def(a).map(Adt::from) + self.imp.to_def(a) } pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> { - self.imp.to_def(c).map(Const::from) + self.imp.to_def(c) } pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> { - self.imp.to_def(e).map(Enum::from) + self.imp.to_def(e) } pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> { - self.imp.to_def(v).map(Variant::from) + self.imp.to_def(v) } pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> { - self.imp.to_def(f).map(Function::from) + self.imp.to_def(f) } pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> { - self.imp.to_def(i).map(Impl::from) + self.imp.to_def(i) } pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> { - self.imp.to_def(m).map(Macro::from) + self.imp.to_def(m) } pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> { - self.imp.to_def(m).map(Module::from) + self.imp.to_def(m) } pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> { - self.imp.to_def(s).map(Static::from) + self.imp.to_def(s) } pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> { - self.imp.to_def(s).map(Struct::from) + self.imp.to_def(s) } pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option<TraitAlias> { - self.imp.to_def(t).map(TraitAlias::from) + self.imp.to_def(t) } pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> { - self.imp.to_def(t).map(Trait::from) + self.imp.to_def(t) } pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> { - self.imp.to_def(t).map(TypeAlias::from) + self.imp.to_def(t) } pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> { - self.imp.to_def(u).map(Union::from) + self.imp.to_def(u) } } @@ -811,10 +811,37 @@ impl<'db> SemanticsImpl<'db> { item.attrs().any(|attr| { let Some(meta) = attr.meta() else { return false }; let Some(path) = meta.path() else { return false }; - let Some(attr_name) = path.as_single_name_ref() else { return true }; - let attr_name = attr_name.text(); - let attr_name = attr_name.as_str(); - attr_name == "derive" || find_builtin_attr_idx(&Symbol::intern(attr_name)).is_none() + if let Some(attr_name) = path.as_single_name_ref() { + let attr_name = attr_name.text(); + let attr_name = Symbol::intern(attr_name.as_str()); + if attr_name == sym::derive { + return true; + } + // We ignore `#[test]` and friends in the def map, so we cannot expand them. + // FIXME: We match by text. This is both hacky and incorrect (people can, and do, create + // other macros named `test`). We cannot fix that unfortunately because we use this method + // for speculative expansion in completion, which we cannot analyze. Fortunately, most macros + // named `test` are test-like, meaning their expansion is not terribly important for IDE. + if attr_name == sym::test + || attr_name == sym::bench + || attr_name == sym::test_case + || find_builtin_attr_idx(&attr_name).is_some() + { + return false; + } + } + let mut segments = path.segments(); + let mut next_segment_text = || segments.next().and_then(|it| it.name_ref()); + // `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`. + if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std")) + && next_segment_text().is_some_and(|it| it.text() == "prelude") + && next_segment_text().is_some() + && next_segment_text() + .is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case")) + { + return false; + } + true }) }) } @@ -1206,7 +1233,6 @@ impl<'db> SemanticsImpl<'db> { node.original_file_range_opt(self.db.upcast()) .filter(|(_, ctx)| ctx.is_root()) .map(TupleExt::head) - .map(Into::into) } /// Attempts to map the node out of macro expanded files. @@ -1413,7 +1439,7 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_method_call_fallback( &self, call: &ast::MethodCallExpr, - ) -> Option<Either<Function, Field>> { + ) -> Option<(Either<Function, Field>, Option<GenericSubstitution>)> { self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call) } @@ -1456,7 +1482,7 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_field_fallback( &self, field: &ast::FieldExpr, - ) -> Option<Either<Either<Field, TupleField>, Function>> { + ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution>)> { self.analyze(field.syntax())?.resolve_field_fallback(self.db, field) } @@ -1464,10 +1490,25 @@ impl<'db> SemanticsImpl<'db> { &self, field: &ast::RecordExprField, ) -> Option<(Field, Option<Local>, Type)> { + self.resolve_record_field_with_substitution(field) + .map(|(field, local, ty, _)| (field, local, ty)) + } + + pub fn resolve_record_field_with_substitution( + &self, + field: &ast::RecordExprField, + ) -> Option<(Field, Option<Local>, Type, GenericSubstitution)> { self.analyze(field.syntax())?.resolve_record_field(self.db, field) } pub fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<(Field, Type)> { + self.resolve_record_pat_field_with_subst(field).map(|(field, ty, _)| (field, ty)) + } + + pub fn resolve_record_pat_field_with_subst( + &self, + field: &ast::RecordPatField, + ) -> Option<(Field, Type, GenericSubstitution)> { self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field) } @@ -1485,7 +1526,7 @@ impl<'db> SemanticsImpl<'db> { pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool { self.resolve_macro_call(macro_call) - .map_or(false, |m| matches!(m.id, MacroId::ProcMacroId(..))) + .is_some_and(|m| matches!(m.id, MacroId::ProcMacroId(..))) } pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> { @@ -1523,6 +1564,13 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { + self.resolve_path_with_subst(path).map(|(it, _)| it) + } + + pub fn resolve_path_with_subst( + &self, + path: &ast::Path, + ) -> Option<(PathResolution, Option<GenericSubstitution>)> { self.analyze(path.syntax())?.resolve_path(self.db, path) } @@ -2038,6 +2086,11 @@ impl SemanticsScope<'_> { ) } + pub fn resolve_mod_path(&self, path: &ModPath) -> impl Iterator<Item = ItemInNs> { + let items = self.resolver.resolve_module_path_in_items(self.db.upcast(), path); + items.iter_items().map(|(item, _)| item.into()) + } + /// Iterates over associated types that may be specified after the given path (using /// `Ty::Assoc` syntax). pub fn assoc_type_shorthand_candidates<R>( |