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.rs48
1 files changed, 29 insertions, 19 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 407ba6f658..2d2b00b147 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -7,9 +7,10 @@ use std::{cell::RefCell, fmt, iter, mem, ops};
use base_db::{FileId, FileRange};
use either::Either;
use hir_def::{
- body,
- expr::Expr,
+ hir::Expr,
+ lower::LowerCtx,
macro_id_to_def_id,
+ nameres::MacroSubNs,
resolver::{self, HasResolver, Resolver, TypeNs},
type_ref::Mutability,
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
@@ -140,7 +141,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.parse(file_id)
}
- pub fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
+ pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
self.imp.parse_or_expand(file_id)
}
@@ -350,6 +351,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.type_of_pat(pat)
}
+ /// It also includes the changes that binding mode makes in the type. For example in
+ /// `let ref x @ Some(_) = None` the result of `type_of_pat` is `Option<T>` but the result
+ /// of this function is `&mut Option<T>`
+ pub fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option<Type> {
+ self.imp.type_of_binding_in_pat(pat)
+ }
+
pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
self.imp.type_of_self(param)
}
@@ -518,23 +526,23 @@ impl<'db> SemanticsImpl<'db> {
tree
}
- fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
- let node = self.db.parse_or_expand(file_id)?;
+ fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
+ let node = self.db.parse_or_expand(file_id);
self.cache(node.clone(), file_id);
- Some(node)
+ node
}
fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
let sa = self.analyze_no_infer(macro_call.syntax())?;
let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?;
- let node = self.parse_or_expand(file_id)?;
+ let node = self.parse_or_expand(file_id);
Some(node)
}
fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
let src = self.wrap_node_infile(item.clone());
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?;
- self.parse_or_expand(macro_call_id.as_file())
+ Some(self.parse_or_expand(macro_call_id.as_file()))
}
fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
@@ -543,7 +551,7 @@ impl<'db> SemanticsImpl<'db> {
let call_id = self.with_ctx(|ctx| {
ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it)
})?;
- self.parse_or_expand(call_id.as_file())
+ Some(self.parse_or_expand(call_id.as_file()))
}
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<Option<Macro>>> {
@@ -566,7 +574,7 @@ impl<'db> SemanticsImpl<'db> {
.into_iter()
.flat_map(|call| {
let file_id = call?.as_file();
- let node = self.db.parse_or_expand(file_id)?;
+ let node = self.db.parse_or_expand(file_id);
self.cache(node.clone(), file_id);
Some(node)
})
@@ -609,7 +617,7 @@ impl<'db> SemanticsImpl<'db> {
let krate = resolver.krate();
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
resolver
- .resolve_path_as_macro(self.db.upcast(), &path)
+ .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(self.db.upcast(), it))
})?;
hir_expand::db::expand_speculative(
@@ -990,7 +998,7 @@ impl<'db> SemanticsImpl<'db> {
}
fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
- let root = self.parse_or_expand(src.file_id).unwrap();
+ let root = self.parse_or_expand(src.file_id);
let node = src.map(|it| it.to_node(&root));
node.as_ref().original_file_range(self.db.upcast())
}
@@ -1065,7 +1073,7 @@ impl<'db> SemanticsImpl<'db> {
fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
let analyze = self.analyze(ty.syntax())?;
- let ctx = body::LowerCtx::new(self.db.upcast(), analyze.file_id);
+ let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
.lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
@@ -1074,12 +1082,9 @@ impl<'db> SemanticsImpl<'db> {
fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
let analyze = self.analyze(path.syntax())?;
let hygiene = hir_expand::hygiene::Hygiene::new(self.db.upcast(), analyze.file_id);
- let ctx = body::LowerCtx::with_hygiene(self.db.upcast(), &hygiene);
+ let ctx = LowerCtx::with_hygiene(self.db.upcast(), &hygiene);
let hir_path = Path::from_src(path.clone(), &ctx)?;
- match analyze
- .resolver
- .resolve_path_in_type_ns_fully(self.db.upcast(), hir_path.mod_path())?
- {
+ match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
TypeNs::TraitId(id) => Some(Trait { id }),
_ => None,
}
@@ -1141,6 +1146,10 @@ impl<'db> SemanticsImpl<'db> {
.map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
}
+ fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option<Type> {
+ self.analyze(pat.syntax())?.type_of_binding_in_pat(self.db, pat)
+ }
+
fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
self.analyze(param.syntax())?.type_of_self(self.db, param)
}
@@ -1647,6 +1656,7 @@ impl<'a> SemanticsScope<'a> {
VisibleTraits(resolver.traits_in_scope(self.db.upcast()))
}
+ /// Calls the passed closure `f` on all names in scope.
pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
let scope = self.resolver.names_in_scope(self.db.upcast());
for (name, entries) in scope {
@@ -1674,7 +1684,7 @@ impl<'a> SemanticsScope<'a> {
/// Resolve a path as-if it was written at the given scope. This is
/// necessary a heuristic, as it doesn't take hygiene into account.
pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
- let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
+ let ctx = LowerCtx::with_file_id(self.db.upcast(), self.file_id);
let path = Path::from_src(path.clone(), &ctx)?;
resolve_hir_path(self.db, &self.resolver, &path)
}