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.rs107
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>(