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 | 187 |
1 files changed, 93 insertions, 94 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index e5df574199..ca5fa8a7cf 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -12,14 +12,12 @@ use std::{ use either::Either; use hir_def::{ - AsMacroCall, DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId, - expr_store::{Body, ExprOrPatSource}, + DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId, + expr_store::{Body, ExprOrPatSource, path::Path}, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, - lower::LowerCtx, - nameres::{MacroSubNs, ModuleOrigin}, - path::ModPath, + nameres::ModuleOrigin, resolver::{self, HasResolver, Resolver, TypeNs}, - type_ref::{Mutability, TypesMap, TypesSourceMap}, + type_ref::Mutability, }; use hir_expand::{ ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, @@ -29,14 +27,15 @@ use hir_expand::{ files::InRealFile, hygiene::SyntaxContextExt as _, inert_attr_macro::find_builtin_attr_idx, + mod_path::{ModPath, PathKind}, name::AsName, }; use hir_ty::diagnostics::unsafe_operations_for_body; -use intern::{Symbol, sym}; +use intern::{Interned, Symbol, sym}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{SmallVec, smallvec}; -use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContext}; +use span::{EditionedFileId, FileId, HirFileIdRepr, SyntaxContext}; use stdx::TupleExt; use syntax::{ AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, @@ -44,13 +43,12 @@ use syntax::{ algo::skip_trivia_token, ast::{self, HasAttrs as _, HasGenericParams}, }; -use triomphe::Arc; use crate::{ Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, Crate, DefWithBody, 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, + Module, ModuleDef, Name, OverloadedDeref, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, @@ -398,13 +396,7 @@ impl<'db> SemanticsImpl<'db> { let sa = self.analyze_no_infer(macro_call.syntax())?; let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = if let Some(call) = - <ast::MacroCall as crate::semantics::ToDef>::to_def(self, macro_call) - { - call.as_macro_file() - } else { - sa.expand(self.db, macro_call)? - }; + let file_id = sa.expand(self.db, macro_call)?; let node = self.parse_or_expand(file_id.into()); Some(node) @@ -432,13 +424,7 @@ impl<'db> SemanticsImpl<'db> { let sa = self.analyze_no_infer(macro_call.syntax())?; let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = if let Some(call) = - <ast::MacroCall as crate::semantics::ToDef>::to_def(self, macro_call) - { - call.as_macro_file() - } else { - sa.expand(self.db, macro_call)? - }; + let file_id = sa.expand(self.db, macro_call)?; let macro_call = self.db.lookup_intern_macro_call(file_id.macro_call_id); let skip = matches!( @@ -575,16 +561,12 @@ impl<'db> SemanticsImpl<'db> { speculative_args: &ast::TokenTree, token_to_map: SyntaxToken, ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { - let SourceAnalyzer { file_id, resolver, .. } = - self.analyze_no_infer(actual_macro_call.syntax())?; - let macro_call = InFile::new(file_id, actual_macro_call); - let krate = resolver.krate(); - let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { - resolver.resolve_path_as_macro_def(self.db.upcast(), path, Some(MacroSubNs::Bang)) - })?; + let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; + let macro_call = InFile::new(analyzer.file_id, actual_macro_call); + let macro_file = analyzer.expansion(macro_call)?; hir_expand::db::expand_speculative( self.db.upcast(), - macro_call_id, + macro_file.macro_call_id, speculative_args.syntax(), token_to_map, ) @@ -901,13 +883,17 @@ impl<'db> SemanticsImpl<'db> { res } - pub fn descend_into_macros_no_opaque(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> { + pub fn descend_into_macros_no_opaque( + &self, + token: SyntaxToken, + ) -> SmallVec<[InFile<SyntaxToken>; 1]> { let mut res = smallvec![]; - if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() { + let token = self.wrap_token_infile(token); + if let Ok(token) = token.clone().into_real_file() { self.descend_into_macros_impl(token, &mut |t, ctx| { if !ctx.is_opaque(self.db.upcast()) { // Don't descend into opaque contexts - res.push(t.value); + res.push(t); } CONTINUE_NO_BREAKS }); @@ -1093,24 +1079,16 @@ impl<'db> SemanticsImpl<'db> { let file_id = match m_cache.get(&mcall) { Some(&it) => it, None => { - let it = if let Some(call) = - <ast::MacroCall as crate::semantics::ToDef>::to_def( - self, - mcall.as_ref(), - ) { - call.as_macro_file() - } else { - token - .parent() - .and_then(|parent| { - self.analyze_impl( - InFile::new(expansion, &parent), - None, - false, - ) - })? - .expand(self.db, mcall.as_ref())? - }; + let it = token + .parent() + .and_then(|parent| { + self.analyze_impl( + InFile::new(expansion, &parent), + None, + false, + ) + })? + .expand(self.db, mcall.as_ref())?; m_cache.insert(mcall, it); it } @@ -1349,31 +1327,19 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> { let analyze = self.analyze(ty.syntax())?; - let (mut types_map, mut types_source_map) = - (TypesMap::default(), TypesSourceMap::default()); - let mut ctx = - LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let type_ref = crate::TypeRef::from_ast(&mut ctx, ty.clone()); - let ty = hir_ty::TyLoweringContext::new_maybe_unowned( - self.db, - &analyze.resolver, - &types_map, - None, - analyze.resolver.type_owner(), - ) - .lower_ty(type_ref); - Some(Type::new_with_resolver(self.db, &analyze.resolver, ty)) + analyze.type_of_type(self.db, ty) } pub fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> { + let parent_ty = path.syntax().parent().and_then(ast::Type::cast)?; let analyze = self.analyze(path.syntax())?; - let (mut types_map, mut types_source_map) = - (TypesMap::default(), TypesSourceMap::default()); - let mut ctx = - LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let hir_path = Path::from_src(&mut ctx, path.clone())?; - match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? { - TypeNs::TraitId(id) => Some(Trait { id }), + let ty = analyze.store_sm()?.node_type(InFile::new(analyze.file_id, &parent_ty))?; + let path = match &analyze.store()?.types[ty] { + hir_def::type_ref::TypeRef::Path(path) => path, + _ => return None, + }; + match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? { + TypeNs::TraitId(trait_id) => Some(trait_id.into()), _ => None, } } @@ -1752,6 +1718,7 @@ impl<'db> SemanticsImpl<'db> { &self, node: InFile<&SyntaxNode>, offset: Option<TextSize>, + // replace this, just make the inference result a `LazyCell` infer_body: bool, ) -> Option<SourceAnalyzer> { let _p = tracing::info_span!("SemanticsImpl::analyze_impl").entered(); @@ -1766,14 +1733,28 @@ impl<'db> SemanticsImpl<'db> { SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset) }); } - ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), - ChildContainer::TraitAliasId(it) => it.resolver(self.db.upcast()), - ChildContainer::ImplId(it) => it.resolver(self.db.upcast()), + ChildContainer::VariantId(def) => { + return Some(SourceAnalyzer::new_variant_body(self.db, def, node, offset)); + } + ChildContainer::TraitId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + } + ChildContainer::TraitAliasId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + } + ChildContainer::ImplId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + } + ChildContainer::EnumId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + } + ChildContainer::TypeAliasId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + } + ChildContainer::GenericDefId(it) => { + return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset)); + } ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()), - ChildContainer::EnumId(it) => it.resolver(self.db.upcast()), - ChildContainer::VariantId(it) => it.resolver(self.db.upcast()), - ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()), - ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()), }; Some(SourceAnalyzer::new_for_resolver(resolver, node)) } @@ -1879,6 +1860,7 @@ impl<'db> SemanticsImpl<'db> { } } +// FIXME This can't be the best way to do this fn macro_call_to_macro_id( ctx: &mut SourceToDefCtx<'_, '_>, macro_call_id: MacroCallId, @@ -2051,23 +2033,40 @@ impl SemanticsScope<'_> { /// 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, ast_path: &ast::Path) -> Option<PathResolution> { - let root = ast_path.syntax().ancestors().last().unwrap(); - let ast_id_map = Arc::new(AstIdMap::from_source(&root)); - let (mut types_map, mut types_source_map) = - (TypesMap::default(), TypesSourceMap::default()); - let mut ctx = LowerCtx::for_synthetic_ast( - self.db.upcast(), - ast_id_map, - &mut types_map, - &mut types_source_map, - ); - let path = Path::from_src(&mut ctx, ast_path.clone())?; + let mut kind = PathKind::Plain; + let mut segments = vec![]; + let mut first = true; + for segment in ast_path.segments() { + if first { + first = false; + if segment.coloncolon_token().is_some() { + kind = PathKind::Abs; + } + } + + let Some(k) = segment.kind() else { continue }; + match k { + ast::PathSegmentKind::Name(name_ref) => segments.push(name_ref.as_name()), + ast::PathSegmentKind::Type { .. } => continue, + ast::PathSegmentKind::SelfTypeKw => { + segments.push(Name::new_symbol_root(sym::Self_.clone())) + } + ast::PathSegmentKind::SelfKw => kind = PathKind::Super(0), + ast::PathSegmentKind::SuperKw => match kind { + PathKind::Super(s) => kind = PathKind::Super(s + 1), + PathKind::Plain => kind = PathKind::Super(1), + PathKind::Crate | PathKind::Abs | PathKind::DollarCrate(_) => continue, + }, + ast::PathSegmentKind::CrateKw => kind = PathKind::Crate, + } + } + resolve_hir_path( self.db, &self.resolver, - &path, + &Path::BarePath(Interned::new(ModPath::from_segments(kind, segments))), name_hygiene(self.db, InFile::new(self.file_id, ast_path.syntax())), - &types_map, + None, ) } |