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 | 48 |
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) } |