diff --git a/Cargo.lock b/Cargo.lock index ef373519726..8f7783deb9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -274,14 +274,6 @@ dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-queue" version = "0.2.0" @@ -290,15 +282,6 @@ dependencies = [ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-utils" version = "0.7.0" @@ -1092,7 +1075,7 @@ dependencies = [ "ra_syntax 0.1.0", "ra_text_edit 0.1.0", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", @@ -1371,22 +1354,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1833,7 +1816,7 @@ dependencies = [ name = "xtask" version = "0.1.0" dependencies = [ - "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1857,7 +1840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "57114fc2a6cc374bce195d3482057c846e706d252ff3604363449695684d7a0d" +"checksum anyhow 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "e19f23ab207147bbdbcdfa7f7e4ca5e84963d79bae3937074682177ab9150968" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" @@ -1887,9 +1870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" @@ -1984,8 +1965,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a132d128b57..5690040a757 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -10,10 +10,12 @@ adt::VariantData, body::scope::ExprScopes, builtin_type::BuiltinType, + nameres::per_ns::PerNs, + resolver::{HasResolver, TypeNs}, traits::TraitData, type_ref::{Mutability, TypeRef}, - AssocItemId, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, - LocalStructFieldId, Lookup, ModuleId, UnionId, + ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, + ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -25,14 +27,12 @@ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, - generics::{GenericDef, HasGenericParams}, ids::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, TypeAliasId, }, - resolve::{HasResolver, TypeNs}, ty::{InferenceResult, Namespace, TraitRef}, - Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, + Either, HasSource, ImportId, Name, Source, Ty, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -829,12 +829,12 @@ pub fn items(self, db: &impl DefDatabase) -> Vec { } fn direct_super_traits(self, db: &impl HirDatabase) -> Vec { - let resolver = self.resolver(db); + let resolver = self.id.resolver(db); // returning the iterator directly doesn't easily work because of // lifetime problems, but since there usually shouldn't be more than a // few direct traits this should be fine (we could even use some kind of // SmallVec if performance is a concern) - self.generic_params(db) + db.generic_params(self.id.into()) .where_predicates .iter() .filter_map(|pred| match &pred.type_ref { @@ -842,9 +842,10 @@ fn direct_super_traits(self, db: &impl HirDatabase) -> Vec { _ => None, }) .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { - Some(TypeNs::Trait(t)) => Some(t), + Some(TypeNs::TraitId(t)) => Some(t), _ => None, }) + .map(Trait::from) .collect() } @@ -871,14 +872,9 @@ pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec { pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option { let trait_data = self.trait_data(db); - trait_data - .items - .iter() - .filter_map(|item| match item { - AssocItemId::TypeAliasId(t) => Some(TypeAlias::from(*t)), - _ => None, - }) - .find(|t| &t.name(db) == name) + let res = + trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?; + Some(res) } pub fn associated_type_by_name_including_super_traits( @@ -978,16 +974,6 @@ pub enum AssocItem { // casting them, and somehow making the constructors private, which would be annoying. impl_froms!(AssocItem: Function, Const, TypeAlias); -impl From for crate::generics::GenericDef { - fn from(item: AssocItem) -> Self { - match item { - AssocItem::Function(f) => f.into(), - AssocItem::Const(c) => c.into(), - AssocItem::TypeAlias(t) => t.into(), - } - } -} - impl AssocItem { pub fn module(self, db: &impl DefDatabase) -> Module { match self { @@ -1007,6 +993,39 @@ pub fn container(self, db: &impl DefDatabase) -> Container { } } +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum GenericDef { + Function(Function), + Adt(Adt), + Trait(Trait), + TypeAlias(TypeAlias), + ImplBlock(ImplBlock), + // enum variants cannot have generics themselves, but their parent enums + // can, and this makes some code easier to write + EnumVariant(EnumVariant), + // consts can have type parameters from their parents (i.e. associated consts of traits) + Const(Const), +} +impl_froms!( + GenericDef: Function, + Adt(Struct, Enum, Union), + Trait, + TypeAlias, + ImplBlock, + EnumVariant, + Const +); + +impl From for GenericDef { + fn from(item: AssocItem) -> Self { + match item { + AssocItem::Function(f) => f.into(), + AssocItem::Const(c) => c.into(), + AssocItem::TypeAlias(t) => t.into(), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Local { pub(crate) parent: DefWithBody, @@ -1068,3 +1087,26 @@ pub struct GenericParam { pub struct ImplBlock { pub(crate) id: ImplId, } + +/// For IDE only +pub enum ScopeDef { + ModuleDef(ModuleDef), + MacroDef(MacroDef), + GenericParam(GenericParam), + ImplSelfType(ImplBlock), + AdtSelfType(Adt), + Local(Local), + Unknown, +} + +impl From for ScopeDef { + fn from(def: PerNs) -> Self { + def.take_types() + .or_else(|| def.take_values()) + .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) + .or_else(|| { + def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) + }) + .unwrap_or(ScopeDef::Unknown) + } +} diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index a9982a70f6d..ed0d680011e 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,7 +8,6 @@ use crate::{ debug::HirDebugDatabase, - generics::GenericDef, ids, lang_item::{LangItemTarget, LangItems}, ty::{ @@ -18,8 +17,8 @@ TypeCtor, }, type_alias::TypeAliasData, - Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField, - Trait, TypeAlias, + Const, ConstData, Crate, DefWithBody, FnData, Function, GenericDef, ImplBlock, Module, Static, + StructField, Trait, TypeAlias, }; pub use hir_def::db::{ diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 869879bdfa4..6b703d8b4be 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use hir_def::path::known; +use hir_def::{path::known, resolver::HasResolver}; use hir_expand::diagnostics::DiagnosticSink; use ra_syntax::ast; use ra_syntax::AstPtr; @@ -11,9 +11,8 @@ use crate::{ db::HirDatabase, diagnostics::{MissingFields, MissingOkInTailExpr}, - resolve::HasResolver, ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, - Adt, DefWithBody, Function, HasBody, Name, Path, Resolver, + Adt, Function, Name, Path, }; pub use hir_def::{ @@ -27,30 +26,6 @@ }, }; -// needs arbitrary_self_types to be a method... or maybe move to the def? -pub(crate) fn resolver_for_expr( - db: &impl HirDatabase, - owner: DefWithBody, - expr_id: ExprId, -) -> Resolver { - let scopes = owner.expr_scopes(db); - resolver_for_scope(db, owner, scopes.scope_for(expr_id)) -} - -pub(crate) fn resolver_for_scope( - db: &impl HirDatabase, - owner: DefWithBody, - scope_id: Option, -) -> Resolver { - let mut r = owner.resolver(db); - let scopes = owner.expr_scopes(db); - let scope_chain = scopes.scope_chain(scope_id).collect::>(); - for scope in scope_chain.into_iter().rev() { - r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); - } - r -} - pub(crate) struct ExprValidator<'a, 'b: 'a> { func: Function, infer: Arc, @@ -146,13 +121,13 @@ fn validate_results_in_tail_expr( let std_result_path = known::std_result_result(); - let resolver = self.func.resolver(db); + let resolver = self.func.id.resolver(db); let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { Some(it) => it, _ => return, }; - let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum)); + let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum.into())); let params = match &mismatch.expected { Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, _ => return, diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index b7692d40733..e8ed04056a7 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -3,9 +3,22 @@ //! It's unclear if we need this long-term, but it's definitelly useful while we //! are splitting the hir. -use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId}; +use hir_def::{ + AdtId, AssocItemId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, + ModuleDefId, StaticId, StructId, TypeAliasId, UnionId, +}; -use crate::{Adt, AssocItem, DefWithBody, EnumVariant, GenericDef, ModuleDef}; +use crate::{ + ty::{CallableDef, TypableDef}, + Adt, AssocItem, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef, ModuleDef, + Static, TypeAlias, +}; + +impl From for Crate { + fn from(crate_id: ra_db::CrateId) -> Self { + Crate { crate_id } + } +} macro_rules! from_id { ($(($id:path, $ty:path)),*) => {$( @@ -83,6 +96,16 @@ fn from(def: DefWithBody) -> Self { } } +impl From for DefWithBody { + fn from(def: DefWithBodyId) -> Self { + match def { + DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()), + DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()), + DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()), + } + } +} + impl From for AssocItem { fn from(def: AssocItemId) -> Self { match def { @@ -122,3 +145,77 @@ fn from(def: GenericDefId) -> Self { } } } + +impl From for TypableDef { + fn from(id: AdtId) -> Self { + Adt::from(id).into() + } +} + +impl From for TypableDef { + fn from(id: StructId) -> Self { + AdtId::StructId(id).into() + } +} + +impl From for TypableDef { + fn from(id: UnionId) -> Self { + AdtId::UnionId(id).into() + } +} + +impl From for TypableDef { + fn from(id: EnumId) -> Self { + AdtId::EnumId(id).into() + } +} + +impl From for TypableDef { + fn from(id: EnumVariantId) -> Self { + EnumVariant::from(id).into() + } +} + +impl From for TypableDef { + fn from(id: TypeAliasId) -> Self { + TypeAlias::from(id).into() + } +} + +impl From for TypableDef { + fn from(id: FunctionId) -> Self { + Function::from(id).into() + } +} +impl From for TypableDef { + fn from(id: ConstId) -> Self { + Const::from(id).into() + } +} +impl From for TypableDef { + fn from(id: StaticId) -> Self { + Static::from(id).into() + } +} + +impl From for GenericDefId { + fn from(id: Adt) -> Self { + match id { + Adt::Struct(it) => it.id.into(), + Adt::Union(it) => it.id.into(), + Adt::Enum(it) => it.id.into(), + } + } +} + +impl From for GenericDefId { + fn from(def: CallableDef) -> Self { + match def { + CallableDef::Function(it) => it.id.into(), + CallableDef::Struct(it) => it.id.into(), + CallableDef::EnumVariant(it) => { + EnumVariantId { parent: it.parent.id, local_id: it.id }.into() + } + } + } +} diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs deleted file mode 100644 index f1bf2ee9d19..00000000000 --- a/crates/ra_hir/src/generics.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Temp module to wrap hir_def::generics -use std::sync::Arc; - -use crate::{ - db::DefDatabase, Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, - TypeAlias, Union, -}; - -pub use hir_def::generics::{GenericParam, GenericParams, WherePredicate}; - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -pub enum GenericDef { - Function(Function), - Adt(Adt), - Trait(Trait), - TypeAlias(TypeAlias), - ImplBlock(ImplBlock), - // enum variants cannot have generics themselves, but their parent enums - // can, and this makes some code easier to write - EnumVariant(EnumVariant), - // consts can have type parameters from their parents (i.e. associated consts of traits) - Const(Const), -} -impl_froms!( - GenericDef: Function, - Adt(Struct, Enum, Union), - Trait, - TypeAlias, - ImplBlock, - EnumVariant, - Const -); - -impl From for GenericDef { - fn from(c: Container) -> Self { - match c { - Container::Trait(trait_) => trait_.into(), - Container::ImplBlock(impl_block) => impl_block.into(), - } - } -} - -pub trait HasGenericParams: Copy { - fn generic_params(self, db: &impl DefDatabase) -> Arc; -} - -impl HasGenericParams for T -where - T: Into + Copy, -{ - fn generic_params(self, db: &impl DefDatabase) -> Arc { - db.generic_params(self.into().into()) - } -} diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 964a3da8c08..774fa1d9640 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -1,11 +1,10 @@ //! FIXME: write short doc here -use hir_def::{type_ref::TypeRef, AstItemDef}; -use ra_syntax::ast::{self}; +use hir_def::{resolver::HasResolver, type_ref::TypeRef, AstItemDef}; +use ra_syntax::ast; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - resolve::HasResolver, ty::Ty, AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, }; @@ -27,12 +26,12 @@ pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { } pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { - Ty::from_hir(db, &self.resolver(db), &self.target_type(db)) + Ty::from_hir(db, &self.id.resolver(db), &self.target_type(db)) } pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option { let target_ty = self.target_ty(db); - TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty)) + TraitRef::from_hir(db, &self.id.resolver(db), &self.target_trait(db)?, Some(target_ty)) } pub fn items(&self, db: &impl DefDatabase) -> Vec { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 31da74d2f3b..8c6834392df 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -37,8 +37,6 @@ fn from(it: $sv) -> $e { mod impl_block; mod expr; mod lang_item; -pub mod generics; -mod resolve; pub mod diagnostics; mod util; @@ -52,23 +50,19 @@ fn from(it: $sv) -> $e { #[cfg(test)] mod marks; -use crate::resolve::Resolver; - pub use crate::{ code_model::{ attrs::{AttrDef, Attrs}, docs::{DocDef, Docs, Documentation}, src::{HasBodySource, HasSource}, Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, - EnumVariant, FieldSource, FnData, Function, GenericParam, HasBody, ImplBlock, Local, - MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, - Union, VariantDef, + EnumVariant, FieldSource, FnData, Function, GenericDef, GenericParam, HasBody, ImplBlock, + Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, + Trait, TypeAlias, Union, VariantDef, }, expr::ExprScopes, from_source::FromSource, - generics::GenericDef, ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, - resolve::ScopeDef, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, ty::{ display::HirDisplay, diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 727310f0662..797f90d501b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -10,6 +10,8 @@ use hir_def::{ expr::{ExprId, PatId}, path::known, + resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, + DefWithBodyId, }; use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; use ra_syntax::{ @@ -21,12 +23,12 @@ use crate::{ db::HirDatabase, - expr::{self, BodySourceMap, ExprScopes, ScopeId}, + expr::{BodySourceMap, ExprScopes, ScopeId}, ids::LocationCtx, - resolve::{HasResolver, ScopeDef, TypeNs, ValueNs}, ty::method_resolution::{self, implements_trait}, - AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, GenericParam, HasBody, - HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, + Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, + GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, ScopeDef, Static, + Struct, Trait, Ty, TypeAlias, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option { @@ -34,23 +36,25 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) - match (node.value) { ast::Module(it) => { let src = node.with_value(it); - Some(crate::Module::from_declaration(db, src)?.resolver(db)) + Some(crate::Module::from_declaration(db, src)?.id.resolver(db)) }, ast::SourceFile(it) => { let src = node.with_value(crate::ModuleSource::SourceFile(it)); - Some(crate::Module::from_definition(db, src)?.resolver(db)) + Some(crate::Module::from_definition(db, src)?.id.resolver(db)) }, ast::StructDef(it) => { let src = node.with_value(it); - Some(Struct::from_source(db, src)?.resolver(db)) + Some(Struct::from_source(db, src)?.id.resolver(db)) }, ast::EnumDef(it) => { let src = node.with_value(it); - Some(Enum::from_source(db, src)?.resolver(db)) + Some(Enum::from_source(db, src)?.id.resolver(db)) }, _ => match node.value.kind() { FN_DEF | CONST_DEF | STATIC_DEF => { - Some(def_with_body_from_child_node(db, node)?.resolver(db)) + let def = def_with_body_from_child_node(db, node)?; + let def = DefWithBodyId::from(def); + Some(def.resolver(db)) } // FIXME add missing cases _ => None @@ -127,6 +131,7 @@ pub struct ReferenceDescriptor { } pub struct Expansion { + macro_file_kind: MacroFileKind, macro_call_id: MacroCallId, } @@ -141,7 +146,7 @@ pub fn map_token_down( } pub fn file_id(&self) -> HirFileId { - self.macro_call_id.as_file(MacroFileKind::Items) + self.macro_call_id.as_file(self.macro_file_kind) } } @@ -159,7 +164,7 @@ pub fn new( None => scope_for(&scopes, &source_map, node), Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), }; - let resolver = expr::resolver_for_scope(db, def, scope); + let resolver = resolver_for_scope(db, def.into(), scope); SourceAnalyzer { resolver, body_owner: Some(def), @@ -231,7 +236,7 @@ pub fn resolve_macro_call( ) -> Option { // This must be a normal source file rather than macro file. let path = macro_call.path().and_then(Path::from_ast)?; - self.resolver.resolve_path_as_macro(db, &path) + self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) } pub fn resolve_hir_path( @@ -240,16 +245,18 @@ pub fn resolve_hir_path( path: &crate::Path, ) -> Option { let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { - TypeNs::SelfType(it) => PathResolution::SelfType(it), + TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { - parent: self.resolver.generic_def().unwrap(), + parent: self.resolver.generic_def().unwrap().into(), idx, }), - TypeNs::AdtSelfType(it) | TypeNs::Adt(it) => PathResolution::Def(it.into()), - TypeNs::EnumVariant(it) => PathResolution::Def(it.into()), - TypeNs::TypeAlias(it) => PathResolution::Def(it.into()), + TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { + PathResolution::Def(Adt::from(it).into()) + } + TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), - TypeNs::Trait(it) => PathResolution::Def(it.into()), + TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), }); let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { let res = match val { @@ -257,11 +264,11 @@ pub fn resolve_hir_path( let var = Local { parent: self.body_owner?, pat_id }; PathResolution::Local(var) } - ValueNs::Function(it) => PathResolution::Def(it.into()), - ValueNs::Const(it) => PathResolution::Def(it.into()), - ValueNs::Static(it) => PathResolution::Def(it.into()), - ValueNs::Struct(it) => PathResolution::Def(it.into()), - ValueNs::EnumVariant(it) => PathResolution::Def(it.into()), + ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), + ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), + ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), + ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), + ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), }; Some(res) }); @@ -272,7 +279,9 @@ pub fn resolve_hir_path( .take_types() .map(|it| PathResolution::Def(it.into())); types.or(values).or(items).or_else(|| { - self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def)) + self.resolver + .resolve_path_as_macro(db, &path) + .map(|def| PathResolution::Macro(def.into())) }) } @@ -307,7 +316,22 @@ fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option it.into(), + resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), + resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), + resolver::ScopeDef::GenericParam(idx) => { + let parent = self.resolver.generic_def().unwrap().into(); + ScopeDef::GenericParam(GenericParam { parent, idx }) + } + resolver::ScopeDef::Local(pat_id) => { + let parent = self.resolver.body_owner().unwrap().into(); + ScopeDef::Local(Local { parent, pat_id }) + } + }; + f(name, def) + }) } // FIXME: we only use this in `inline_local_variable` assist, ideally, we @@ -392,7 +416,7 @@ pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { let std_future_path = known::std_future_future(); let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { - Some(it) => it, + Some(it) => it.into(), _ => return false, }; @@ -402,7 +426,7 @@ pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { }; let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; - implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) + implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) } pub fn expand( @@ -416,7 +440,10 @@ pub fn expand( db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), ); let macro_call_loc = MacroCallLoc { def, ast_id }; - Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) + Some(Expansion { + macro_call_id: db.intern_macro(macro_call_loc), + macro_file_kind: to_macro_file_kind(macro_call.value), + }) } #[cfg(test)] @@ -515,3 +542,35 @@ fn adjust( }) .map(|(_ptr, scope)| *scope) } + +/// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. +/// FIXME: Not completed +fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { + let syn = macro_call.syntax(); + let parent = match syn.parent() { + Some(it) => it, + None => { + // FIXME: + // If it is root, which means the parent HirFile + // MacroKindFile must be non-items + // return expr now. + return MacroFileKind::Expr; + } + }; + + match parent.kind() { + MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items, + LET_STMT => { + // FIXME: Handle Pattern + MacroFileKind::Expr + } + EXPR_STMT => MacroFileKind::Statements, + BLOCK => MacroFileKind::Statements, + ARG_LIST => MacroFileKind::Expr, + TRY_EXPR => MacroFileKind::Expr, + _ => { + // Unknown , Just guess it is `Items` + MacroFileKind::Items + } + } +} diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 36ece723f23..95b8df18105 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -17,12 +17,11 @@ use std::sync::Arc; use std::{fmt, iter, mem}; +use hir_def::{generics::GenericParams, AdtId}; + use crate::{ - db::HirDatabase, - expr::ExprId, - generics::{GenericParams, HasGenericParams}, - util::make_mut_slice, - Adt, Crate, DefWithBody, FloatTy, IntTy, Mutability, Name, Trait, TypeAlias, Uncertain, + db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, DefWithBody, FloatTy, + GenericDef, IntTy, Mutability, Name, Trait, TypeAlias, Uncertain, }; use display::{HirDisplay, HirFormatter}; @@ -131,15 +130,15 @@ pub fn num_ty_params(self, db: &impl HirDatabase) -> usize { | TypeCtor::Closure { .. } // 1 param representing the signature of the closure => 1, TypeCtor::Adt(adt) => { - let generic_params = adt.generic_params(db); + let generic_params = db.generic_params(AdtId::from(adt).into()); generic_params.count_params_including_parent() } TypeCtor::FnDef(callable) => { - let generic_params = callable.generic_params(db); + let generic_params = db.generic_params(callable.into()); generic_params.count_params_including_parent() } TypeCtor::AssociatedType(type_alias) => { - let generic_params = type_alias.generic_params(db); + let generic_params = db.generic_params(type_alias.id.into()); generic_params.count_params_including_parent() } TypeCtor::FnPtr { num_args } => num_args as usize + 1, @@ -168,7 +167,7 @@ pub fn krate(self, db: &impl HirDatabase) -> Option { } } - pub fn as_generic_def(self) -> Option { + pub fn as_generic_def(self) -> Option { match self { TypeCtor::Bool | TypeCtor::Char @@ -348,8 +347,9 @@ pub fn bound_vars(generic_params: &GenericParams) -> Substs { ) } - pub fn build_for_def(db: &impl HirDatabase, def: impl HasGenericParams) -> SubstsBuilder { - let params = def.generic_params(db); + pub fn build_for_def(db: &impl HirDatabase, def: impl Into) -> SubstsBuilder { + let def = def.into(); + let params = db.generic_params(def.into()); let param_count = params.count_params_including_parent(); Substs::builder(param_count) } diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 872a4517d13..b60e4bb3119 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs @@ -5,11 +5,12 @@ use std::iter::successors; +use hir_def::resolver::Resolver; use hir_expand::name; use log::{info, warn}; use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; -use crate::{db::HirDatabase, generics::HasGenericParams, Resolver}; +use crate::db::HirDatabase; const AUTODEREF_RECURSION_LIMIT: usize = 10; @@ -39,13 +40,13 @@ fn deref_by_trait( ty: &Canonical, ) -> Option> { let krate = resolver.krate()?; - let deref_trait = match db.lang_item(krate, "deref".into())? { + let deref_trait = match db.lang_item(krate.into(), "deref".into())? { crate::lang_item::LangItemTarget::Trait(t) => t, _ => return None, }; let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; - let generic_params = target.generic_params(db); + let generic_params = db.generic_params(target.id.into()); if generic_params.count_params_including_parent() != 1 { // the Target type + Deref trait should only have one generic parameter, // namely Deref's Self type @@ -71,7 +72,7 @@ fn deref_by_trait( let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; - let solution = db.trait_solve(krate, canonical)?; + let solution = db.trait_solve(krate.into(), canonical)?; match &solution { Solution::Unique(vars) => { diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 7f9e81d6492..69b13baefba 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -23,7 +23,9 @@ use hir_def::{ path::known, + resolver::{HasResolver, Resolver, TypeNs}, type_ref::{Mutability, TypeRef}, + AdtId, DefWithBodyId, }; use hir_expand::{diagnostics::DiagnosticSink, name}; use ra_arena::map::ArenaMap; @@ -40,10 +42,9 @@ code_model::TypeAlias, db::HirDatabase, expr::{BindingAnnotation, Body, ExprId, PatId}, - resolve::{HasResolver, Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, - StructField, VariantDef, + StructField, Trait, VariantDef, }; macro_rules! ty_app { @@ -64,7 +65,7 @@ macro_rules! ty_app { /// The entry point of type inference. pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { let _p = profile("infer_query"); - let resolver = def.resolver(db); + let resolver = DefWithBodyId::from(def).resolver(db); let mut ctx = InferenceContext::new(db, def, resolver); match def { @@ -377,8 +378,9 @@ fn resolve_obligations_as_possible(&mut self) { for obligation in obligations { let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); - let solution = - self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); + let solution = self + .db + .trait_solve(self.resolver.krate().unwrap().into(), canonicalized.value.clone()); match solution { Some(Solution::Unique(substs)) => { @@ -518,17 +520,17 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { // FIXME: this should resolve assoc items as well, see this example: // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { - Some(TypeNs::Adt(Adt::Struct(it))) => it.into(), - Some(TypeNs::Adt(Adt::Union(it))) => it.into(), + Some(TypeNs::AdtId(AdtId::StructId(it))) => it.into(), + Some(TypeNs::AdtId(AdtId::UnionId(it))) => it.into(), Some(TypeNs::AdtSelfType(adt)) => adt.into(), - Some(TypeNs::EnumVariant(it)) => it.into(), - Some(TypeNs::TypeAlias(it)) => it.into(), + Some(TypeNs::EnumVariantId(it)) => it.into(), + Some(TypeNs::TypeAliasId(it)) => it.into(), Some(TypeNs::SelfType(_)) | Some(TypeNs::GenericParam(_)) | Some(TypeNs::BuiltinType(_)) | - Some(TypeNs::Trait(_)) | - Some(TypeNs::Adt(Adt::Enum(_))) | + Some(TypeNs::TraitId(_)) | + Some(TypeNs::AdtId(AdtId::EnumId(_))) | None => { return (Ty::Unknown, None) } @@ -576,26 +578,26 @@ fn infer_body(&mut self) { fn resolve_into_iter_item(&self) -> Option { let path = known::std_iter_into_iterator(); - let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); trait_.associated_type_by_name(self.db, &name::ITEM_TYPE) } fn resolve_ops_try_ok(&self) -> Option { let path = known::std_ops_try(); - let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); trait_.associated_type_by_name(self.db, &name::OK_TYPE) } fn resolve_future_future_output(&self) -> Option { let path = known::std_future_future(); - let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE) } fn resolve_boxed_box(&self) -> Option { let path = known::std_boxed_box(); let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; - Some(Adt::Struct(struct_)) + Some(Adt::Struct(struct_.into())) } } diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 6ea135126a5..0772b9df57a 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs @@ -4,19 +4,19 @@ //! //! See: https://doc.rust-lang.org/nomicon/coercions.html +use hir_def::resolver::Resolver; use rustc_hash::FxHashMap; - use test_utils::tested_by; -use super::{InferTy, InferenceContext, TypeVarValue}; use crate::{ db::HirDatabase, lang_item::LangItemTarget, - resolve::Resolver, ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, Adt, Mutability, }; +use super::{InferTy, InferenceContext, TypeVarValue}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// Unify two types, but may coerce the first one to the second one /// using "implicit coercion rules" if needed. @@ -49,8 +49,8 @@ pub(super) fn init_coerce_unsized_map( resolver: &Resolver, ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { let krate = resolver.krate().unwrap(); - let impls = match db.lang_item(krate, "coerce_unsized".into()) { - Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate, trait_), + let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { + Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), _ => return FxHashMap::default(), }; diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index 5e68a1678f4..20a7e93525e 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs @@ -5,15 +5,15 @@ use hir_def::{ builtin_type::Signedness, + generics::GenericParams, path::{GenericArg, GenericArgs}, + resolver::resolver_for_expr, }; use hir_expand::name; -use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; use crate::{ db::HirDatabase, - expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, - generics::{GenericParams, HasGenericParams}, + expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, ty::{ autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, @@ -22,6 +22,8 @@ Adt, Name, }; +use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { let ty = self.infer_expr_inner(tgt_expr, expected); @@ -186,7 +188,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { } Expr::Path(p) => { // FIXME this could be more efficient... - let resolver = expr::resolver_for_expr(self.db, self.owner, tgt_expr); + let resolver = resolver_for_expr(self.db, self.owner.into(), tgt_expr); self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } Expr::Continue => Ty::simple(TypeCtor::Never), @@ -532,7 +534,7 @@ fn infer_method_call( ( ty, self.db.type_for_def(func.into(), Namespace::Values), - Some(func.generic_params(self.db)), + Some(self.db.generic_params(func.id.into())), ) } None => (receiver_ty, Ty::Unknown, None), @@ -643,7 +645,9 @@ fn register_obligations_for_call(&mut self, callable_ty: &Ty) { if let Some(trait_) = f.parent_trait(self.db) { // construct a TraitDef let substs = a_ty.parameters.prefix( - trait_.generic_params(self.db).count_params_including_parent(), + self.db + .generic_params(trait_.id.into()) + .count_params_including_parent(), ); self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); } diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 31ca675aac0..ee54d821738 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs @@ -1,16 +1,18 @@ //! Path expression resolution. -use hir_def::path::PathSegment; +use hir_def::{ + path::PathSegment, + resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, +}; -use super::{ExprOrPatId, InferenceContext, TraitRef}; use crate::{ db::HirDatabase, - generics::HasGenericParams, - resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, - AssocItem, Container, Name, Path, + AssocItem, Container, Function, Name, Path, }; +use super::{ExprOrPatId, InferenceContext, TraitRef}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { pub(super) fn infer_path( &mut self, @@ -60,11 +62,11 @@ fn resolve_value_path( let ty = self.resolve_ty_as_possible(&mut vec![], ty); return Some(ty); } - ValueNs::Function(it) => it.into(), - ValueNs::Const(it) => it.into(), - ValueNs::Static(it) => it.into(), - ValueNs::Struct(it) => it.into(), - ValueNs::EnumVariant(it) => it.into(), + ValueNs::FunctionId(it) => it.into(), + ValueNs::ConstId(it) => it.into(), + ValueNs::StaticId(it) => it.into(), + ValueNs::StructId(it) => it.into(), + ValueNs::EnumVariantId(it) => it.into(), }; let mut ty = self.db.type_for_def(typable, Namespace::Values); @@ -94,13 +96,13 @@ fn resolve_assoc_item( let is_before_last = remaining_segments.len() == 1; match (def, is_before_last) { - (TypeNs::Trait(trait_), true) => { + (TypeNs::TraitId(trait_), true) => { let segment = remaining_segments.last().expect("there should be at least one segment here"); let trait_ref = TraitRef::from_resolved_path( self.db, &self.resolver, - trait_, + trait_.into(), resolved_segment, None, ); @@ -160,8 +162,8 @@ fn resolve_trait_assoc_item( AssocItem::TypeAlias(_) => None, })?; let def = match item { - AssocItem::Function(f) => ValueNs::Function(f), - AssocItem::Const(c) => ValueNs::Const(c), + AssocItem::Function(f) => ValueNs::FunctionId(f.id), + AssocItem::Const(c) => ValueNs::ConstId(c.id), AssocItem::TypeAlias(_) => unreachable!(), }; let substs = Substs::build_for_def(self.db, item) @@ -193,8 +195,8 @@ fn resolve_ty_assoc_item( method_resolution::LookupMode::Path, move |_ty, item| { let def = match item { - AssocItem::Function(f) => ValueNs::Function(f), - AssocItem::Const(c) => ValueNs::Const(c), + AssocItem::Function(f) => ValueNs::FunctionId(f.id), + AssocItem::Const(c) => ValueNs::ConstId(c.id), AssocItem::TypeAlias(_) => unreachable!(), }; let substs = match item.container(self.db) { @@ -224,9 +226,10 @@ fn resolve_ty_assoc_item( } fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option { - if let ValueNs::Function(func) = def { + if let ValueNs::FunctionId(func) = def { + let func = Function::from(*func); // We only do the infer if parent has generic params - let gen = func.generic_params(self.db); + let gen = self.db.generic_params(func.id.into()); if gen.count_parent_params() == 0 { return None; } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 397ee7d5fc3..75c55256929 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -10,8 +10,11 @@ use hir_def::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType}, + generics::WherePredicate, path::{GenericArg, PathSegment}, + resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, + AdtId, GenericDefId, }; use super::{ @@ -20,16 +23,13 @@ }; use crate::{ db::HirDatabase, - generics::HasGenericParams, - generics::{GenericDef, WherePredicate}, - resolve::{HasResolver, Resolver, TypeNs}, ty::{ primitive::{FloatTy, IntTy, Uncertain}, Adt, }, util::make_mut_slice, - Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait, - TypeAlias, Union, VariantDef, + Const, Enum, EnumVariant, Function, GenericDef, ImplBlock, ModuleDef, Path, Static, Struct, + StructField, Trait, TypeAlias, Union, VariantDef, }; // FIXME: this is only really used in `type_for_def`, which contains a bunch of @@ -156,9 +156,14 @@ pub(crate) fn from_partly_resolved_hir_path( remaining_segments: &[PathSegment], ) -> Ty { let ty = match resolution { - TypeNs::Trait(trait_) => { - let trait_ref = - TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); + TypeNs::TraitId(trait_) => { + let trait_ref = TraitRef::from_resolved_path( + db, + resolver, + trait_.into(), + resolved_segment, + None, + ); return if remaining_segments.len() == 1 { let segment = &remaining_segments[0]; match trait_ref @@ -189,18 +194,18 @@ pub(crate) fn from_partly_resolved_hir_path( let name = resolved_segment.name.clone(); Ty::Param { idx, name } } - TypeNs::SelfType(impl_block) => impl_block.target_ty(db), - TypeNs::AdtSelfType(adt) => adt.ty(db), + TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db), + TypeNs::AdtSelfType(adt) => Adt::from(adt).ty(db), - TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), + TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), TypeNs::BuiltinType(it) => { Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) } - TypeNs::TypeAlias(it) => { + TypeNs::TypeAliasId(it) => { Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) } // FIXME: report error - TypeNs::EnumVariant(_) => return Ty::Unknown, + TypeNs::EnumVariantId(_) => return Ty::Unknown, }; Ty::from_type_relative_path(db, resolver, ty, remaining_segments) @@ -247,7 +252,7 @@ fn select_associated_type( Some(def) => def, None => return Ty::Unknown, // this can't actually happen }; - let predicates = db.generic_predicates_for_param(def, param_idx); + let predicates = db.generic_predicates_for_param(def.into(), param_idx); let traits_from_env = predicates.iter().filter_map(|pred| match pred { GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), _ => None, @@ -336,7 +341,7 @@ pub(super) fn substs_from_path_segment( add_self_param: bool, ) -> Substs { let mut substs = Vec::new(); - let def_generics = def_generic.map(|def| def.generic_params(db)); + let def_generics = def_generic.map(|def| db.generic_params(def.into())); let (parent_param_count, param_count) = def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); @@ -391,11 +396,11 @@ pub(crate) fn from_path( explicit_self_ty: Option, ) -> Option { let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? { - TypeNs::Trait(tr) => tr, + TypeNs::TraitId(tr) => tr, _ => return None, }; let segment = path.segments.last().expect("path should have at least one segment"); - Some(TraitRef::from_resolved_path(db, resolver, resolved, segment, explicit_self_ty)) + Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) } pub(super) fn from_resolved_path( @@ -437,7 +442,7 @@ fn substs_from_path( } pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { - let substs = Substs::identity(&trait_.generic_params(db)); + let substs = Substs::identity(&db.generic_params(trait_.id.into())); TraitRef { trait_, substs } } @@ -548,8 +553,8 @@ pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSi pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { let parent_def = field.parent_def(db); let resolver = match parent_def { - VariantDef::Struct(it) => it.resolver(db), - VariantDef::EnumVariant(it) => it.parent_enum(db).resolver(db), + VariantDef::Struct(it) => it.id.resolver(db), + VariantDef::EnumVariant(it) => it.parent.id.resolver(db), }; let var_data = parent_def.variant_data(db); let type_ref = &var_data.fields().unwrap()[field.id].type_ref; @@ -569,7 +574,7 @@ pub(crate) fn generic_predicates_for_param_query( def: GenericDef, param_idx: u32, ) -> Arc<[GenericPredicate]> { - let resolver = def.resolver(db); + let resolver = GenericDefId::from(def).resolver(db); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them @@ -595,7 +600,7 @@ pub(crate) fn generic_predicates_query( db: &impl HirDatabase, def: GenericDef, ) -> Arc<[GenericPredicate]> { - let resolver = def.resolver(db); + let resolver = GenericDefId::from(def).resolver(db); resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) @@ -604,8 +609,8 @@ pub(crate) fn generic_predicates_query( /// Resolve the default type params from generics pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> Substs { - let resolver = def.resolver(db); - let generic_params = def.generic_params(db); + let resolver = GenericDefId::from(def).resolver(db); + let generic_params = db.generic_params(def.into()); let defaults = generic_params .params_including_parent() @@ -618,7 +623,7 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { let data = def.data(db); - let resolver = def.resolver(db); + let resolver = def.id.resolver(db); let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::>(); let ret = Ty::from_hir(db, &resolver, data.ret_type()); FnSig::from_params_and_return(params, ret) @@ -627,7 +632,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { /// Build the declared type of a function. This should not need to look at the /// function body. fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { - let generics = def.generic_params(db); + let generics = db.generic_params(def.id.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(def.into()), substs) } @@ -635,7 +640,7 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { /// Build the declared type of a const. fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { let data = def.data(db); - let resolver = def.resolver(db); + let resolver = def.id.resolver(db); Ty::from_hir(db, &resolver, data.type_ref()) } @@ -643,7 +648,7 @@ fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { /// Build the declared type of a static. fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { let data = def.data(db); - let resolver = def.resolver(db); + let resolver = def.id.resolver(db); Ty::from_hir(db, &resolver, data.type_ref()) } @@ -695,7 +700,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { Some(fields) => fields, None => panic!("fn_sig_for_struct_constructor called on unit struct"), }; - let resolver = def.resolver(db); + let resolver = def.id.resolver(db); let params = fields .iter() .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) @@ -710,7 +715,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { if struct_data.variant_data.fields().is_none() { return type_for_adt(db, def); // Unit struct } - let generics = def.generic_params(db); + let generics = db.generic_params(def.id.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(def.into()), substs) } @@ -721,12 +726,12 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) Some(fields) => fields, None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"), }; - let resolver = def.parent_enum(db).resolver(db); + let resolver = def.parent.id.resolver(db); let params = fields .iter() .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) .collect::>(); - let generics = def.parent_enum(db).generic_params(db); + let generics = db.generic_params(def.parent_enum(db).id.into()); let substs = Substs::identity(&generics); let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs); FnSig::from_params_and_return(params, ret) @@ -738,19 +743,21 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> if var_data.fields().is_none() { return type_for_adt(db, def.parent_enum(db)); // Unit variant } - let generics = def.parent_enum(db).generic_params(db); + let generics = db.generic_params(def.parent_enum(db).id.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(def.into()), substs) } -fn type_for_adt(db: &impl HirDatabase, adt: impl Into + HasGenericParams) -> Ty { - let generics = adt.generic_params(db); - Ty::apply(TypeCtor::Adt(adt.into()), Substs::identity(&generics)) +fn type_for_adt(db: &impl HirDatabase, adt: impl Into) -> Ty { + let adt = adt.into(); + let adt_id: AdtId = adt.into(); + let generics = db.generic_params(adt_id.into()); + Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) } fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { - let generics = t.generic_params(db); - let resolver = t.resolver(db); + let generics = db.generic_params(t.id.into()); + let resolver = t.id.resolver(db); let type_ref = t.type_ref(db); let substs = Substs::identity(&generics); let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index f377fca48a6..64adb814d3f 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -5,11 +5,11 @@ use std::sync::Arc; use arrayvec::ArrayVec; +use hir_def::resolver::Resolver; use rustc_hash::FxHashMap; use crate::{ db::HirDatabase, - resolve::Resolver, ty::primitive::{FloatBitness, Uncertain}, ty::{Ty, TypeCtor}, AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, @@ -172,9 +172,14 @@ pub(crate) fn iterate_method_candidates( // rustc does an autoderef and then autoref again). for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { - if let Some(result) = - iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback) - { + if let Some(result) = iterate_inherent_methods( + &derefed_ty, + db, + name, + mode, + krate.into(), + &mut callback, + ) { return Some(result); } if let Some(result) = iterate_trait_method_candidates( @@ -192,7 +197,7 @@ pub(crate) fn iterate_method_candidates( LookupMode::Path => { // No autoderef for path lookups if let Some(result) = - iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback) + iterate_inherent_methods(&ty, db, name, mode, krate.into(), &mut callback) { return Some(result); } @@ -224,7 +229,9 @@ fn iterate_trait_method_candidates( .trait_predicates_for_self_ty(&ty.value) .map(|tr| tr.trait_) .flat_map(|t| t.all_super_traits(db)); - let traits = inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db)); + let traits = inherent_trait + .chain(traits_from_env) + .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); 'traits: for t in traits { let data = t.trait_data(db); @@ -238,7 +245,7 @@ fn iterate_trait_method_candidates( } if !known_implemented { let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); - if db.trait_solve(krate, goal).is_none() { + if db.trait_solve(krate.into(), goal).is_none() { continue 'traits; } } diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 9bf93981a08..88785f30503 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -16,10 +16,9 @@ use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ db::HirDatabase, - generics::{GenericDef, HasGenericParams}, ty::display::HirDisplay, ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, - Crate, HasBody, ImplBlock, Trait, TypeAlias, + Crate, GenericDef, HasBody, ImplBlock, Trait, TypeAlias, }; /// This represents a trait whose name we could not resolve. @@ -509,7 +508,7 @@ pub(crate) fn associated_ty_data_query( Some(crate::Container::Trait(t)) => t, _ => panic!("associated type not in trait"), }; - let generic_params = type_alias.generic_params(db); + let generic_params = db.generic_params(type_alias.id.into()); let bound_data = chalk_rust_ir::AssociatedTyDatumBound { // FIXME add bounds and where clauses bounds: vec![], @@ -550,7 +549,7 @@ pub(crate) fn trait_datum_query( } let trait_: Trait = from_chalk(db, trait_id); debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); - let generic_params = trait_.generic_params(db); + let generic_params = db.generic_params(trait_.id.into()); let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_.is_auto(db), @@ -594,7 +593,7 @@ pub(crate) fn struct_datum_query( let where_clauses = type_ctor .as_generic_def() .map(|generic_def| { - let generic_params = generic_def.generic_params(db); + let generic_params = db.generic_params(generic_def.into()); let bound_vars = Substs::bound_vars(&generic_params); convert_where_clauses(db, generic_def, &bound_vars) }) @@ -634,7 +633,7 @@ fn impl_block_datum( impl_id: ImplId, impl_block: ImplBlock, ) -> Option>> { - let generic_params = impl_block.generic_params(db); + let generic_params = db.generic_params(impl_block.id.into()); let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); let trait_ = trait_ref.trait_; @@ -786,7 +785,7 @@ fn type_alias_associated_ty_value( let assoc_ty = trait_ .associated_type_by_name(db, &type_alias.name(db)) .expect("assoc ty value should not exist"); // validated when building the impl data as well - let generic_params = impl_block.generic_params(db); + let generic_params = db.generic_params(impl_block.id.into()); let bound_vars = Substs::bound_vars(&generic_params); let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index a5bb60e8576..d8e911aa521 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -12,6 +12,7 @@ }, AstNode, AstPtr, }; +use test_utils::tested_by; use crate::{ body::{Body, BodySourceMap, Expander, PatPtr}, @@ -190,6 +191,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { None => self.collect_expr_opt(condition.expr()), // if let -- desugar to match Some(pat) => { + tested_by!(infer_resolve_while_let); let pat = self.collect_pat(pat); let match_expr = self.collect_expr_opt(condition.expr()); let placeholder_pat = self.missing_pat(); diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index aeb71ff229f..58740b679dc 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -174,7 +174,7 @@ mod tests { use hir_expand::{name::AsName, Source}; use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; - use test_utils::{assert_eq_text, extract_offset}; + use test_utils::{assert_eq_text, covers, extract_offset}; use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; @@ -382,4 +382,20 @@ fn foo() { 53, ); } + + #[test] + fn while_let_desugaring() { + covers!(infer_resolve_while_let); + do_check_local_name( + r#" +fn test() { + let foo: Option = None; + while let Option::Some(spam) = foo { + spam<|> + } +} +"#, + 75, + ); + } } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 0af41de879b..d579f5c7ea5 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -19,6 +19,7 @@ pub mod body; pub mod generics; pub mod traits; +pub mod resolver; #[cfg(test)] mod test_db; diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs index 0b99eac7174..65239ca0a48 100644 --- a/crates/ra_hir_def/src/marks.rs +++ b/crates/ra_hir_def/src/marks.rs @@ -11,4 +11,5 @@ prelude_is_macro_use macro_dollar_crate_self macro_dollar_crate_other + infer_resolve_while_let ); diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir_def/src/resolver.rs similarity index 65% rename from crates/ra_hir/src/resolve.rs rename to crates/ra_hir_def/src/resolver.rs index eca8e05969b..7b5c3ec0618 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -1,26 +1,28 @@ -//! Name resolution. +//! Name resolution façade. use std::sync::Arc; -use hir_def::{ - builtin_type::BuiltinType, - nameres::CrateDefMap, - path::{Path, PathKind}, - AdtId, CrateModuleId, ModuleDefId, +use hir_expand::{ + name::{self, Name}, + MacroDefId, }; -use hir_expand::name::{self, Name}; +use ra_db::CrateId; use rustc_hash::FxHashSet; use crate::{ - code_model::Crate, - db::{DefDatabase, HirDatabase}, - expr::{ExprScopes, PatId, ScopeId}, - generics::{GenericParams, HasGenericParams}, - Adt, Const, Container, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, - MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, + body::scope::{ExprScopes, ScopeId}, + builtin_type::BuiltinType, + db::DefDatabase2, + expr::{ExprId, PatId}, + generics::GenericParams, + nameres::{per_ns::PerNs, CrateDefMap}, + path::{Path, PathKind}, + AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, + TypeAliasId, }; #[derive(Debug, Clone, Default)] -pub(crate) struct Resolver { +pub struct Resolver { scopes: Vec, } @@ -33,7 +35,7 @@ pub(crate) struct ModuleItemMap { #[derive(Debug, Clone)] pub(crate) struct ExprScope { - owner: DefWithBody, + owner: DefWithBodyId, expr_scopes: Arc, scope_id: ScopeId, } @@ -43,80 +45,76 @@ pub(crate) enum Scope { /// All the items and imported names of a module ModuleScope(ModuleItemMap), /// Brings the generic parameters of an item into scope - GenericParams { def: GenericDef, params: Arc }, + GenericParams { def: GenericDefId, params: Arc }, /// Brings `Self` in `impl` block into scope - ImplBlockScope(ImplBlock), + ImplBlockScope(ImplId), /// Brings `Self` in enum, struct and union definitions into scope - AdtScope(Adt), + AdtScope(AdtId), /// Local bindings ExprScope(ExprScope), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum TypeNs { - SelfType(ImplBlock), +pub enum TypeNs { + SelfType(ImplId), GenericParam(u32), - Adt(Adt), - AdtSelfType(Adt), - EnumVariant(EnumVariant), - TypeAlias(TypeAlias), + AdtId(AdtId), + AdtSelfType(AdtId), + EnumVariantId(EnumVariantId), + TypeAliasId(TypeAliasId), BuiltinType(BuiltinType), - Trait(Trait), + TraitId(TraitId), // Module belong to type ns, but the resolver is used when all module paths // are fully resolved. - // Module(Module) + // ModuleId(ModuleId) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum ResolveValueResult { +pub enum ResolveValueResult { ValueNs(ValueNs), Partial(TypeNs, usize), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum ValueNs { +pub enum ValueNs { LocalBinding(PatId), - Function(Function), - Const(Const), - Static(Static), - Struct(Struct), - EnumVariant(EnumVariant), + FunctionId(FunctionId), + ConstId(ConstId), + StaticId(StaticId), + StructId(StructId), + EnumVariantId(EnumVariantId), } impl Resolver { /// Resolve known trait from std, like `std::futures::Future` - pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option { + pub fn resolve_known_trait(&self, db: &impl DefDatabase2, path: &Path) -> Option { let res = self.resolve_module_path(db, path).take_types()?; match res { - ModuleDefId::TraitId(it) => Some(it.into()), + ModuleDefId::TraitId(it) => Some(it), _ => None, } } /// Resolve known struct from std, like `std::boxed::Box` - pub(crate) fn resolve_known_struct( - &self, - db: &impl HirDatabase, - path: &Path, - ) -> Option { + pub fn resolve_known_struct(&self, db: &impl DefDatabase2, path: &Path) -> Option { let res = self.resolve_module_path(db, path).take_types()?; match res { - ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it.into()), + ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), _ => None, } } /// Resolve known enum from std, like `std::result::Result` - pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option { + pub fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option { let res = self.resolve_module_path(db, path).take_types()?; match res { - ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it.into()), + ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), _ => None, } } /// pub only for source-binder - pub(crate) fn resolve_module_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + pub fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { let (item_map, module) = match self.module() { Some(it) => it, None => return PerNs::none(), @@ -128,9 +126,9 @@ pub(crate) fn resolve_module_path(&self, db: &impl HirDatabase, path: &Path) -> module_res } - pub(crate) fn resolve_path_in_type_ns( + pub fn resolve_path_in_type_ns( &self, - db: &impl HirDatabase, + db: &impl DefDatabase2, path: &Path, ) -> Option<(TypeNs, Option)> { if path.is_type_relative() { @@ -164,13 +162,13 @@ pub(crate) fn resolve_path_in_type_ns( Scope::ModuleScope(m) => { let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); let res = match module_def.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()), - ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariant(it.into()), + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()), + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), - ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()), + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::FunctionId(_) | ModuleDefId::ConstId(_) @@ -184,9 +182,9 @@ pub(crate) fn resolve_path_in_type_ns( None } - pub(crate) fn resolve_path_in_type_ns_fully( + pub fn resolve_path_in_type_ns_fully( &self, - db: &impl HirDatabase, + db: &impl DefDatabase2, path: &Path, ) -> Option { let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; @@ -196,9 +194,9 @@ pub(crate) fn resolve_path_in_type_ns_fully( Some(res) } - pub(crate) fn resolve_path_in_value_ns<'p>( + pub fn resolve_path_in_value_ns<'p>( &self, - db: &impl HirDatabase, + db: &impl DefDatabase2, path: &'p Path, ) -> Option { if path.is_type_relative() { @@ -259,13 +257,11 @@ pub(crate) fn resolve_path_in_value_ns<'p>( return match idx { None => { let value = match module_def.take_values()? { - ModuleDefId::FunctionId(it) => ValueNs::Function(it.into()), - ModuleDefId::AdtId(AdtId::StructId(it)) => { - ValueNs::Struct(it.into()) - } - ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariant(it.into()), - ModuleDefId::ConstId(it) => ValueNs::Const(it.into()), - ModuleDefId::StaticId(it) => ValueNs::Static(it.into()), + ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), + ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), + ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), + ModuleDefId::ConstId(it) => ValueNs::ConstId(it), + ModuleDefId::StaticId(it) => ValueNs::StaticId(it), ModuleDefId::AdtId(AdtId::EnumId(_)) | ModuleDefId::AdtId(AdtId::UnionId(_)) @@ -278,9 +274,9 @@ pub(crate) fn resolve_path_in_value_ns<'p>( } Some(idx) => { let ty = match module_def.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()), - ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()), - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()), + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), ModuleDefId::ModuleId(_) @@ -298,9 +294,9 @@ pub(crate) fn resolve_path_in_value_ns<'p>( None } - pub(crate) fn resolve_path_in_value_ns_fully( + pub fn resolve_path_in_value_ns_fully( &self, - db: &impl HirDatabase, + db: &impl DefDatabase2, path: &Path, ) -> Option { match self.resolve_path_in_value_ns(db, path)? { @@ -309,35 +305,26 @@ pub(crate) fn resolve_path_in_value_ns_fully( } } - pub(crate) fn resolve_path_as_macro( - &self, - db: &impl DefDatabase, - path: &Path, - ) -> Option { + pub fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { let (item_map, module) = self.module()?; - item_map.resolve_path(db, module, path).0.get_macros().map(MacroDef::from) + item_map.resolve_path(db, module, path).0.get_macros() } - pub(crate) fn process_all_names( - &self, - db: &impl HirDatabase, - f: &mut dyn FnMut(Name, ScopeDef), - ) { + pub fn process_all_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { for scope in self.scopes.iter().rev() { scope.process_names(db, f); } } - pub(crate) fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet { + pub fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet { let mut traits = FxHashSet::default(); for scope in &self.scopes { if let Scope::ModuleScope(m) = scope { if let Some(prelude) = m.crate_def_map.prelude() { let prelude_def_map = db.crate_def_map(prelude.krate); - traits - .extend(prelude_def_map[prelude.module_id].scope.traits().map(Trait::from)); + traits.extend(prelude_def_map[prelude.module_id].scope.traits()); } - traits.extend(m.crate_def_map[m.module_id].scope.traits().map(Trait::from)); + traits.extend(m.crate_def_map[m.module_id].scope.traits()); } } traits @@ -351,11 +338,11 @@ fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { }) } - pub(crate) fn krate(&self) -> Option { - self.module().map(|t| Crate { crate_id: t.0.krate() }) + pub fn krate(&self) -> Option { + self.module().map(|t| t.0.krate()) } - pub(crate) fn where_predicates_in_scope<'a>( + pub fn where_predicates_in_scope<'a>( &'a self, ) -> impl Iterator + 'a { self.scopes @@ -367,80 +354,31 @@ pub(crate) fn where_predicates_in_scope<'a>( .flat_map(|params| params.where_predicates.iter()) } - pub(crate) fn generic_def(&self) -> Option { + pub fn generic_def(&self) -> Option { self.scopes.iter().find_map(|scope| match scope { Scope::GenericParams { def, .. } => Some(*def), _ => None, }) } -} -impl Resolver { - pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver { - self.scopes.push(scope); - self - } - - pub(crate) fn push_generic_params_scope( - self, - db: &impl DefDatabase, - def: GenericDef, - ) -> Resolver { - let params = def.generic_params(db); - if params.params.is_empty() { - self - } else { - self.push_scope(Scope::GenericParams { def, params }) - } - } - - pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { - self.push_scope(Scope::ImplBlockScope(impl_block)) - } - - pub(crate) fn push_module_scope( - self, - crate_def_map: Arc, - module_id: CrateModuleId, - ) -> Resolver { - self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) - } - - pub(crate) fn push_expr_scope( - self, - owner: DefWithBody, - expr_scopes: Arc, - scope_id: ScopeId, - ) -> Resolver { - self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) + pub fn body_owner(&self) -> Option { + self.scopes.iter().find_map(|scope| match scope { + Scope::ExprScope(it) => Some(it.owner), + _ => None, + }) } } -/// For IDE only pub enum ScopeDef { - ModuleDef(ModuleDef), - MacroDef(MacroDef), + PerNs(PerNs), + ImplSelfType(ImplId), + AdtSelfType(AdtId), GenericParam(u32), - ImplSelfType(ImplBlock), - AdtSelfType(Adt), - Local(Local), - Unknown, -} - -impl From for ScopeDef { - fn from(def: PerNs) -> Self { - def.take_types() - .or_else(|| def.take_values()) - .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) - .or_else(|| { - def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) - }) - .unwrap_or(ScopeDef::Unknown) - } + Local(PatId), } impl Scope { - fn process_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { + fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { match self { Scope::ModuleScope(m) => { // FIXME: should we provide `self` here? @@ -451,18 +389,18 @@ fn process_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef) // }), // ); m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), res.def.into()); + f(name.clone(), ScopeDef::PerNs(res.def)); }); m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { - f(name.clone(), ScopeDef::MacroDef(macro_.into())); + f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); }); m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| { - f(name.clone(), ScopeDef::ModuleDef(def.into())); + f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); }); if let Some(prelude) = m.crate_def_map.prelude() { let prelude_def_map = db.crate_def_map(prelude.krate); prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), res.def.into()); + f(name.clone(), ScopeDef::PerNs(res.def)); }); } } @@ -472,114 +410,175 @@ fn process_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef) } } Scope::ImplBlockScope(i) => { - f(name::SELF_TYPE, ScopeDef::ImplSelfType(*i)); + f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); } Scope::AdtScope(i) => { - f(name::SELF_TYPE, ScopeDef::AdtSelfType(*i)); + f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); } Scope::ExprScope(scope) => { scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { - let local = Local { parent: scope.owner, pat_id: e.pat() }; - f(e.name().clone(), ScopeDef::Local(local)); + f(e.name().clone(), ScopeDef::Local(e.pat())); }); } } } } -pub(crate) trait HasResolver { - /// Builds a resolver for type references inside this def. - fn resolver(self, db: &impl DefDatabase) -> Resolver; +// needs arbitrary_self_types to be a method... or maybe move to the def? +pub fn resolver_for_expr( + db: &impl DefDatabase2, + owner: DefWithBodyId, + expr_id: ExprId, +) -> Resolver { + let scopes = db.expr_scopes(owner); + resolver_for_scope(db, owner, scopes.scope_for(expr_id)) } -impl HasResolver for Module { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - let def_map = db.crate_def_map(self.id.krate); - Resolver::default().push_module_scope(def_map, self.id.module_id) +pub fn resolver_for_scope( + db: &impl DefDatabase2, + owner: DefWithBodyId, + scope_id: Option, +) -> Resolver { + let mut r = owner.resolver(db); + let scopes = db.expr_scopes(owner); + let scope_chain = scopes.scope_chain(scope_id).collect::>(); + for scope in scope_chain.into_iter().rev() { + r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); + } + r +} + +impl Resolver { + fn push_scope(mut self, scope: Scope) -> Resolver { + self.scopes.push(scope); + self + } + + fn push_generic_params_scope(self, db: &impl DefDatabase2, def: GenericDefId) -> Resolver { + let params = db.generic_params(def); + if params.params.is_empty() { + self + } else { + self.push_scope(Scope::GenericParams { def, params }) + } + } + + fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver { + self.push_scope(Scope::ImplBlockScope(impl_block)) + } + + fn push_module_scope( + self, + crate_def_map: Arc, + module_id: CrateModuleId, + ) -> Resolver { + self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) + } + + fn push_expr_scope( + self, + owner: DefWithBodyId, + expr_scopes: Arc, + scope_id: ScopeId, + ) -> Resolver { + self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) } } -impl HasResolver for Trait { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +pub trait HasResolver { + /// Builds a resolver for type references inside this def. + fn resolver(self, db: &impl DefDatabase2) -> Resolver; +} + +impl HasResolver for ModuleId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + let def_map = db.crate_def_map(self.krate); + Resolver::default().push_module_scope(def_map, self.module_id) + } +} + +impl HasResolver for TraitId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { self.module(db).resolver(db).push_generic_params_scope(db, self.into()) } } -impl> HasResolver for T { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +impl> HasResolver for T { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { let def = self.into(); - def.module(db) + let module = match def { + AdtId::StructId(it) => it.0.module(db), + AdtId::UnionId(it) => it.0.module(db), + AdtId::EnumId(it) => it.module(db), + }; + + module .resolver(db) .push_generic_params_scope(db, def.into()) .push_scope(Scope::AdtScope(def)) } } -impl HasResolver for Function { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.container(db) - .map(|c| c.resolver(db)) - .unwrap_or_else(|| self.module(db).resolver(db)) - .push_generic_params_scope(db, self.into()) +impl HasResolver for FunctionId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) } } -impl HasResolver for DefWithBody { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +impl HasResolver for DefWithBodyId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { match self { - DefWithBody::Const(c) => c.resolver(db), - DefWithBody::Function(f) => f.resolver(db), - DefWithBody::Static(s) => s.resolver(db), + DefWithBodyId::ConstId(c) => c.resolver(db), + DefWithBodyId::FunctionId(f) => f.resolver(db), + DefWithBodyId::StaticId(s) => s.resolver(db), } } } -impl HasResolver for Const { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.container(db).map(|c| c.resolver(db)).unwrap_or_else(|| self.module(db).resolver(db)) +impl HasResolver for ConstId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db) } } -impl HasResolver for Static { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +impl HasResolver for StaticId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { self.module(db).resolver(db) } } -impl HasResolver for TypeAlias { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.container(db) - .map(|ib| ib.resolver(db)) - .unwrap_or_else(|| self.module(db).resolver(db)) - .push_generic_params_scope(db, self.into()) +impl HasResolver for TypeAliasId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) } } -impl HasResolver for Container { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +impl HasResolver for ContainerId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { match self { - Container::Trait(trait_) => trait_.resolver(db), - Container::ImplBlock(impl_block) => impl_block.resolver(db), + ContainerId::TraitId(it) => it.resolver(db), + ContainerId::ImplId(it) => it.resolver(db), + ContainerId::ModuleId(it) => it.resolver(db), } } } -impl HasResolver for GenericDef { - fn resolver(self, db: &impl DefDatabase) -> crate::Resolver { +impl HasResolver for GenericDefId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { match self { - GenericDef::Function(inner) => inner.resolver(db), - GenericDef::Adt(adt) => adt.resolver(db), - GenericDef::Trait(inner) => inner.resolver(db), - GenericDef::TypeAlias(inner) => inner.resolver(db), - GenericDef::ImplBlock(inner) => inner.resolver(db), - GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db), - GenericDef::Const(inner) => inner.resolver(db), + GenericDefId::FunctionId(inner) => inner.resolver(db), + GenericDefId::AdtId(adt) => adt.resolver(db), + GenericDefId::TraitId(inner) => inner.resolver(db), + GenericDefId::TypeAliasId(inner) => inner.resolver(db), + GenericDefId::ImplId(inner) => inner.resolver(db), + GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), + GenericDefId::ConstId(inner) => inner.resolver(db), } } } -impl HasResolver for ImplBlock { - fn resolver(self, db: &impl DefDatabase) -> Resolver { +impl HasResolver for ImplId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { self.module(db) .resolver(db) .push_generic_params_scope(db, self.into()) diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs index 877d73d666d..6c2d5b2a9f7 100644 --- a/crates/ra_hir_def/src/traits.rs +++ b/crates/ra_hir_def/src/traits.rs @@ -11,7 +11,7 @@ use crate::{ db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId, - TypeAliasLoc, + TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -56,4 +56,11 @@ pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc impl Iterator + '_ { + self.items.iter().filter_map(|item| match item { + AssocItemId::TypeAliasId(t) => Some(*t), + _ => None, + }) + } } diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 3c11c8a2281..e1d93a8ef53 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -151,6 +151,7 @@ pub(crate) fn parse_macro( let fragment_kind = match macro_file.macro_file_kind { MacroFileKind::Items => FragmentKind::Items, MacroFileKind::Expr => FragmentKind::Expr, + MacroFileKind::Statements => FragmentKind::Statements, }; let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; Some((parse, Arc::new(rev_token_map))) diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 1389f64ce96..126d12fbbed 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -109,6 +109,7 @@ pub struct MacroFile { pub enum MacroFileKind { Items, Expr, + Statements, } /// `MacroCallId` identifies a particular macro invocation, like diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 7f39262dc93..7dbf33a16d4 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs @@ -84,24 +84,19 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { }; res += &match token.kind() { - k @ _ - if (k.is_keyword() || k.is_literal() || k == IDENT) - && is_next(|it| !it.is_punct(), true) => - { + k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { token.text().to_string() + " " } L_CURLY if is_next(|it| it != R_CURLY, true) => { indent += 1; - format!(" {{\n{}", " ".repeat(indent)) + let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; + format!("{}{{\n{}", leading_space, " ".repeat(indent)) } R_CURLY if is_last(|it| it != L_CURLY, true) => { indent = indent.checked_sub(1).unwrap_or(0); - format!("\n}}{}", " ".repeat(indent)) - } - R_CURLY => { - indent = indent.checked_sub(1).unwrap_or(0); - format!("}}\n{}", " ".repeat(indent)) + format!("\n{}}}", " ".repeat(indent)) } + R_CURLY => format!("}}\n{}", " ".repeat(indent)), T![;] => format!(";\n{}", " ".repeat(indent)), T![->] => " -> ".to_string(), T![=] => " = ".to_string(), @@ -112,7 +107,11 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { last = Some(token.kind()); } - res + return res; + + fn is_text(k: SyntaxKind) -> bool { + k.is_keyword() || k.is_literal() || k == IDENT + } } #[cfg(test)] @@ -173,6 +172,49 @@ fn some_thing() -> u32 { let a = 0; a+10 } +"###); + } + + #[test] + fn macro_expand_match_ast() { + let res = check_expand_macro( + r#" + //- /lib.rs + macro_rules! match_ast { + (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; + + (match ($node:expr) { + $( ast::$ast:ident($it:ident) => $res:block, )* + _ => $catch_all:expr $(,)? + }) => {{ + $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* + { $catch_all } + }}; + } + + fn main() { + mat<|>ch_ast! { + match container { + ast::TraitDef(it) => {}, + ast::ImplBlock(it) => {}, + _ => { continue }, + } + } + } + "#, + ); + + assert_eq!(res.name, "match_ast"); + assert_snapshot!(res.expansion, @r###" +{ + if let Some(it) = ast::TraitDef::cast(container.clone()){} + else if let Some(it) = ast::ImplBlock::cast(container.clone()){} + else { + { + continue + } + } +} "###); } } diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index d1c49c0b3f3..1de399fee45 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -5,6 +5,7 @@ ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxTreeBuilder, TextRange, TextUnit, T, }; +use std::iter::successors; use tt::buffer::{Cursor, TokenBuffer}; use crate::subtree_source::SubtreeTokenSource; @@ -160,6 +161,31 @@ fn go(&mut self, tt: &SyntaxNode) -> Option { let first_child = tt.first_child_or_token()?; let last_child = tt.last_child_or_token()?; + + // ignore trivial first_child and last_child + let first_child = successors(Some(first_child), |it| { + if it.kind().is_trivia() { + it.next_sibling_or_token() + } else { + None + } + }) + .last() + .unwrap(); + if first_child.kind().is_trivia() { + return Some(tt::Subtree { token_trees: vec![], delimiter: tt::Delimiter::None }); + } + + let last_child = successors(Some(last_child), |it| { + if it.kind().is_trivia() { + it.prev_sibling_or_token() + } else { + None + } + }) + .last() + .unwrap(); + let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true), (T!['{'], T!['}']) => (tt::Delimiter::Brace, true), @@ -363,6 +389,7 @@ mod tests { use super::*; use crate::tests::{create_rules, expand}; use ra_parser::TokenSource; + use ra_syntax::algo::{insert_children, InsertPosition}; #[test] fn convert_tt_token_source() { @@ -423,4 +450,45 @@ macro_rules! stmts { let expansion = expand(&rules, "stmts!();"); assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); } + + #[test] + fn test_token_tree_last_child_is_white_space() { + let source_file = ast::SourceFile::parse("f!({} );").ok().unwrap(); + let macro_call = source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); + let token_tree = macro_call.token_tree().unwrap(); + + // Token Tree now is : + // TokenTree + // - T!['('] + // - TokenTree + // - T!['{'] + // - T!['}'] + // - WHITE_SPACE + // - T![')'] + + let rbrace = + token_tree.syntax().descendants_with_tokens().find(|it| it.kind() == T!['}']).unwrap(); + let space = token_tree + .syntax() + .descendants_with_tokens() + .find(|it| it.kind() == SyntaxKind::WHITESPACE) + .unwrap(); + + // reorder th white space, such that the white is inside the inner token-tree. + let token_tree = insert_children( + &rbrace.parent().unwrap(), + InsertPosition::Last, + &mut std::iter::once(space), + ); + + // Token Tree now is : + // TokenTree + // - T!['{'] + // - T!['}'] + // - WHITE_SPACE + let token_tree = ast::TokenTree::cast(token_tree).unwrap(); + let tt = ast_to_token_tree(&token_tree).unwrap().0; + + assert_eq!(tt.delimiter, tt::Delimiter::Brace); + } }