diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 50 | ||||
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 260 | ||||
-rw-r--r-- | crates/ra_hir/src/lang_item.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 119 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 93 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 325 |
16 files changed, 556 insertions, 597 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 078bd8609..731cc1fff 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -11,7 +11,7 @@ use hir_def::{ | |||
11 | body::scope::ExprScopes, | 11 | body::scope::ExprScopes, |
12 | builtin_type::BuiltinType, | 12 | builtin_type::BuiltinType, |
13 | type_ref::{Mutability, TypeRef}, | 13 | type_ref::{Mutability, TypeRef}, |
14 | CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, | 14 | CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, |
15 | }; | 15 | }; |
16 | use hir_expand::{ | 16 | use hir_expand::{ |
17 | diagnostics::DiagnosticSink, | 17 | diagnostics::DiagnosticSink, |
@@ -29,7 +29,6 @@ use crate::{ | |||
29 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, | 29 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, |
30 | TypeAliasId, | 30 | TypeAliasId, |
31 | }, | 31 | }, |
32 | impl_block::ImplBlock, | ||
33 | resolve::{Resolver, Scope, TypeNs}, | 32 | resolve::{Resolver, Scope, TypeNs}, |
34 | traits::TraitData, | 33 | traits::TraitData, |
35 | ty::{InferenceResult, Namespace, TraitRef}, | 34 | ty::{InferenceResult, Namespace, TraitRef}, |
@@ -243,12 +242,8 @@ impl Module { | |||
243 | } | 242 | } |
244 | 243 | ||
245 | pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { | 244 | pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { |
246 | let module_impl_blocks = db.impls_in_module(self); | 245 | let def_map = db.crate_def_map(self.id.krate); |
247 | module_impl_blocks | 246 | def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() |
248 | .impls | ||
249 | .iter() | ||
250 | .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id)) | ||
251 | .collect() | ||
252 | } | 247 | } |
253 | 248 | ||
254 | fn with_module_id(self, module_id: CrateModuleId) -> Module { | 249 | fn with_module_id(self, module_id: CrateModuleId) -> Module { |
@@ -693,8 +688,7 @@ impl Function { | |||
693 | 688 | ||
694 | /// The containing impl block, if this is a method. | 689 | /// The containing impl block, if this is a method. |
695 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { | 690 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { |
696 | let module_impls = db.impls_in_module(self.module(db)); | 691 | ImplBlock::containing(db, self.into()) |
697 | ImplBlock::containing(module_impls, self.into()) | ||
698 | } | 692 | } |
699 | 693 | ||
700 | /// The containing trait, if this is a trait method definition. | 694 | /// The containing trait, if this is a trait method definition. |
@@ -759,8 +753,7 @@ impl Const { | |||
759 | 753 | ||
760 | /// The containing impl block, if this is a method. | 754 | /// The containing impl block, if this is a method. |
761 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { | 755 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { |
762 | let module_impls = db.impls_in_module(self.module(db)); | 756 | ImplBlock::containing(db, self.into()) |
763 | ImplBlock::containing(module_impls, self.into()) | ||
764 | } | 757 | } |
765 | 758 | ||
766 | pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { | 759 | pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { |
@@ -973,8 +966,7 @@ impl TypeAlias { | |||
973 | 966 | ||
974 | /// The containing impl block, if this is a method. | 967 | /// The containing impl block, if this is a method. |
975 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { | 968 | pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { |
976 | let module_impls = db.impls_in_module(self.module(db)); | 969 | ImplBlock::containing(db, self.into()) |
977 | ImplBlock::containing(module_impls, self.into()) | ||
978 | } | 970 | } |
979 | 971 | ||
980 | /// The containing trait, if this is a trait method definition. | 972 | /// The containing trait, if this is a trait method definition. |
@@ -1137,3 +1129,8 @@ pub struct GenericParam { | |||
1137 | pub(crate) parent: GenericDef, | 1129 | pub(crate) parent: GenericDef, |
1138 | pub(crate) idx: u32, | 1130 | pub(crate) idx: u32, |
1139 | } | 1131 | } |
1132 | |||
1133 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
1134 | pub struct ImplBlock { | ||
1135 | pub(crate) id: ImplId, | ||
1136 | } | ||
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index c60029c01..d75d71d66 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -10,22 +10,23 @@ use crate::{ | |||
10 | debug::HirDebugDatabase, | 10 | debug::HirDebugDatabase, |
11 | generics::{GenericDef, GenericParams}, | 11 | generics::{GenericDef, GenericParams}, |
12 | ids, | 12 | ids, |
13 | impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, | ||
14 | lang_item::{LangItemTarget, LangItems}, | 13 | lang_item::{LangItemTarget, LangItems}, |
15 | traits::TraitData, | 14 | traits::TraitData, |
16 | ty::{ | 15 | ty::{ |
17 | method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, | 16 | method_resolution::CrateImplBlocks, |
18 | InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, | 17 | traits::{AssocTyValue, Impl}, |
18 | CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, | ||
19 | TypeCtor, | ||
19 | }, | 20 | }, |
20 | type_alias::TypeAliasData, | 21 | type_alias::TypeAliasData, |
21 | Const, ConstData, Crate, DefWithBody, FnData, Function, Module, Static, StructField, Trait, | 22 | Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField, |
22 | TypeAlias, | 23 | Trait, TypeAlias, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | pub use hir_def::db::{ | 26 | pub use hir_def::db::{ |
26 | BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, | 27 | BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, |
27 | EnumDataQuery, ExprScopesQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, | 28 | EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, |
28 | RawItemsWithSourceMapQuery, StructDataQuery, | 29 | RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, |
29 | }; | 30 | }; |
30 | pub use hir_expand::db::{ | 31 | pub use hir_expand::db::{ |
31 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, | 32 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, |
@@ -42,15 +43,6 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { | |||
42 | #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] | 43 | #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] |
43 | fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; | 44 | fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; |
44 | 45 | ||
45 | #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)] | ||
46 | fn impls_in_module_with_source_map( | ||
47 | &self, | ||
48 | module: Module, | ||
49 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>); | ||
50 | |||
51 | #[salsa::invoke(ModuleImplBlocks::impls_in_module_query)] | ||
52 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; | ||
53 | |||
54 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] | 46 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] |
55 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; | 47 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; |
56 | 48 | ||
@@ -128,27 +120,43 @@ pub trait HirDatabase: DefDatabase + AstDatabase { | |||
128 | #[salsa::interned] | 120 | #[salsa::interned] |
129 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; | 121 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; |
130 | #[salsa::interned] | 122 | #[salsa::interned] |
131 | fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId; | 123 | fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId; |
124 | #[salsa::interned] | ||
125 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> ids::AssocTyValueId; | ||
132 | 126 | ||
133 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] | 127 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] |
134 | fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; | 128 | fn associated_ty_data( |
129 | &self, | ||
130 | id: chalk_ir::TypeId, | ||
131 | ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>; | ||
135 | 132 | ||
136 | #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)] | 133 | #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)] |
137 | fn trait_datum( | 134 | fn trait_datum( |
138 | &self, | 135 | &self, |
139 | krate: Crate, | 136 | krate: Crate, |
140 | trait_id: chalk_ir::TraitId, | 137 | trait_id: chalk_ir::TraitId, |
141 | ) -> Arc<chalk_rust_ir::TraitDatum>; | 138 | ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>; |
142 | 139 | ||
143 | #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)] | 140 | #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)] |
144 | fn struct_datum( | 141 | fn struct_datum( |
145 | &self, | 142 | &self, |
146 | krate: Crate, | 143 | krate: Crate, |
147 | struct_id: chalk_ir::StructId, | 144 | struct_id: chalk_ir::StructId, |
148 | ) -> Arc<chalk_rust_ir::StructDatum>; | 145 | ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>; |
149 | 146 | ||
150 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] | 147 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] |
151 | fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>; | 148 | fn impl_datum( |
149 | &self, | ||
150 | krate: Crate, | ||
151 | impl_id: chalk_ir::ImplId, | ||
152 | ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>; | ||
153 | |||
154 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_value_query)] | ||
155 | fn associated_ty_value( | ||
156 | &self, | ||
157 | krate: Crate, | ||
158 | id: chalk_rust_ir::AssociatedTyValueId, | ||
159 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>; | ||
152 | 160 | ||
153 | #[salsa::invoke(crate::ty::traits::trait_solve_query)] | 161 | #[salsa::invoke(crate::ty::traits::trait_solve_query)] |
154 | fn trait_solve( | 162 | fn trait_solve( |
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 9633ef586..f2203e995 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs | |||
@@ -3,9 +3,9 @@ | |||
3 | //! It's unclear if we need this long-term, but it's definitelly useful while we | 3 | //! It's unclear if we need this long-term, but it's definitelly useful while we |
4 | //! are splitting the hir. | 4 | //! are splitting the hir. |
5 | 5 | ||
6 | use hir_def::{AdtId, DefWithBodyId, EnumVariantId, ModuleDefId}; | 6 | use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; |
7 | 7 | ||
8 | use crate::{Adt, DefWithBody, EnumVariant, ModuleDef}; | 8 | use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; |
9 | 9 | ||
10 | macro_rules! from_id { | 10 | macro_rules! from_id { |
11 | ($(($id:path, $ty:path)),*) => {$( | 11 | ($(($id:path, $ty:path)),*) => {$( |
@@ -27,6 +27,7 @@ from_id![ | |||
27 | (hir_def::StaticId, crate::Static), | 27 | (hir_def::StaticId, crate::Static), |
28 | (hir_def::ConstId, crate::Const), | 28 | (hir_def::ConstId, crate::Const), |
29 | (hir_def::FunctionId, crate::Function), | 29 | (hir_def::FunctionId, crate::Function), |
30 | (hir_def::ImplId, crate::ImplBlock), | ||
30 | (hir_expand::MacroDefId, crate::MacroDef) | 31 | (hir_expand::MacroDefId, crate::MacroDef) |
31 | ]; | 32 | ]; |
32 | 33 | ||
@@ -71,3 +72,13 @@ impl From<DefWithBody> for DefWithBodyId { | |||
71 | } | 72 | } |
72 | } | 73 | } |
73 | } | 74 | } |
75 | |||
76 | impl From<AssocItemId> for AssocItem { | ||
77 | fn from(def: AssocItemId) -> Self { | ||
78 | match def { | ||
79 | AssocItemId::FunctionId(it) => AssocItem::Function(it.into()), | ||
80 | AssocItemId::TypeAliasId(it) => AssocItem::TypeAlias(it.into()), | ||
81 | AssocItemId::ConstId(it) => AssocItem::Const(it.into()), | ||
82 | } | ||
83 | } | ||
84 | } | ||
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 7e5523c54..1c26756c9 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; | 3 | use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; |
4 | use hir_expand::name::AsName; | 4 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, NameOwner}, | 6 | ast::{self, AstNode, NameOwner}, |
7 | match_ast, | 7 | match_ast, |
@@ -11,8 +11,8 @@ use crate::{ | |||
11 | db::{AstDatabase, DefDatabase, HirDatabase}, | 11 | db::{AstDatabase, DefDatabase, HirDatabase}, |
12 | ids::{AstItemDef, LocationCtx}, | 12 | ids::{AstItemDef, LocationCtx}, |
13 | Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, | 13 | Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, |
14 | Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, | 14 | Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, |
15 | VariantDef, | 15 | Union, VariantDef, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub trait FromSource: Sized { | 18 | pub trait FromSource: Sized { |
@@ -77,19 +77,28 @@ impl FromSource for TypeAlias { | |||
77 | Some(TypeAlias { id }) | 77 | Some(TypeAlias { id }) |
78 | } | 78 | } |
79 | } | 79 | } |
80 | // FIXME: add impl FromSource for MacroDef | 80 | |
81 | impl FromSource for MacroDef { | ||
82 | type Ast = ast::MacroCall; | ||
83 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
84 | let kind = MacroDefKind::Declarative; | ||
85 | |||
86 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); | ||
87 | let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; | ||
88 | let krate = module.krate().crate_id(); | ||
89 | |||
90 | let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.ast)); | ||
91 | |||
92 | let id: MacroDefId = MacroDefId { krate, ast_id, kind }; | ||
93 | Some(MacroDef { id }) | ||
94 | } | ||
95 | } | ||
81 | 96 | ||
82 | impl FromSource for ImplBlock { | 97 | impl FromSource for ImplBlock { |
83 | type Ast = ast::ImplBlock; | 98 | type Ast = ast::ImplBlock; |
84 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | 99 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { |
85 | let module_src = crate::ModuleSource::from_child_node( | 100 | let id = from_source(db, src)?; |
86 | db, | 101 | Some(ImplBlock { id }) |
87 | src.file_id.original_file(db), | ||
88 | &src.ast.syntax(), | ||
89 | ); | ||
90 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
91 | let impls = module.impl_blocks(db); | ||
92 | impls.into_iter().find(|b| b.source(db) == src) | ||
93 | } | 102 | } |
94 | } | 103 | } |
95 | 104 | ||
@@ -202,9 +211,8 @@ where | |||
202 | N: AstNode, | 211 | N: AstNode, |
203 | DEF: AstItemDef<N>, | 212 | DEF: AstItemDef<N>, |
204 | { | 213 | { |
205 | let module_src = | 214 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); |
206 | crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax()); | 215 | let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; |
207 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
208 | let ctx = LocationCtx::new(db, module.id, src.file_id); | 216 | let ctx = LocationCtx::new(db, module.id, src.file_id); |
209 | Some(DEF::from_ast(ctx, &src.ast)) | 217 | Some(DEF::from_ast(ctx, &src.ast)) |
210 | } | 218 | } |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index fe083c0c6..2b59365fb 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -37,3 +37,9 @@ impl_intern_key!(TypeCtorId); | |||
37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
38 | pub struct GlobalImplId(salsa::InternId); | 38 | pub struct GlobalImplId(salsa::InternId); |
39 | impl_intern_key!(GlobalImplId); | 39 | impl_intern_key!(GlobalImplId); |
40 | |||
41 | /// This exists just for Chalk, because it needs a unique ID for each associated | ||
42 | /// type value in an impl (even synthetic ones). | ||
43 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
44 | pub struct AssocTyValueId(salsa::InternId); | ||
45 | impl_intern_key!(AssocTyValueId); | ||
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index b1a014074..0c2bb8fee 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -1,88 +1,38 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use rustc_hash::FxHashMap; | 3 | use hir_def::{type_ref::TypeRef, AstItemDef}; |
4 | use std::sync::Arc; | 4 | use ra_syntax::ast::{self}; |
5 | |||
6 | use hir_def::{attr::Attr, type_ref::TypeRef}; | ||
7 | use hir_expand::hygiene::Hygiene; | ||
8 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | ||
9 | use ra_cfg::CfgOptions; | ||
10 | use ra_syntax::{ | ||
11 | ast::{self, AstNode}, | ||
12 | AstPtr, | ||
13 | }; | ||
14 | 5 | ||
15 | use crate::{ | 6 | use crate::{ |
16 | code_model::{Module, ModuleSource}, | ||
17 | db::{AstDatabase, DefDatabase, HirDatabase}, | 7 | db::{AstDatabase, DefDatabase, HirDatabase}, |
18 | generics::HasGenericParams, | 8 | generics::HasGenericParams, |
19 | ids::LocationCtx, | ||
20 | ids::MacroCallLoc, | ||
21 | resolve::Resolver, | 9 | resolve::Resolver, |
22 | ty::Ty, | 10 | ty::Ty, |
23 | AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef, | 11 | AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, |
24 | TypeAlias, | ||
25 | }; | 12 | }; |
26 | 13 | ||
27 | #[derive(Debug, Default, PartialEq, Eq)] | ||
28 | pub struct ImplSourceMap { | ||
29 | map: ArenaMap<ImplId, Source<AstPtr<ast::ImplBlock>>>, | ||
30 | } | ||
31 | |||
32 | impl ImplSourceMap { | ||
33 | fn insert(&mut self, impl_id: ImplId, file_id: HirFileId, impl_block: &ast::ImplBlock) { | ||
34 | let source = Source { file_id, ast: AstPtr::new(impl_block) }; | ||
35 | self.map.insert(impl_id, source) | ||
36 | } | ||
37 | |||
38 | pub fn get(&self, db: &impl AstDatabase, impl_id: ImplId) -> Source<ast::ImplBlock> { | ||
39 | let src = self.map[impl_id]; | ||
40 | let root = src.file_syntax(db); | ||
41 | src.map(|ptr| ptr.to_node(&root)) | ||
42 | } | ||
43 | } | ||
44 | |||
45 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
46 | pub struct ImplBlock { | ||
47 | module: Module, | ||
48 | impl_id: ImplId, | ||
49 | } | ||
50 | |||
51 | impl HasSource for ImplBlock { | 14 | impl HasSource for ImplBlock { |
52 | type Ast = ast::ImplBlock; | 15 | type Ast = ast::ImplBlock; |
53 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> { | 16 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> { |
54 | let source_map = db.impls_in_module_with_source_map(self.module).1; | 17 | self.id.source(db) |
55 | source_map.get(db, self.impl_id) | ||
56 | } | 18 | } |
57 | } | 19 | } |
58 | 20 | ||
59 | impl ImplBlock { | 21 | impl ImplBlock { |
60 | pub(crate) fn containing( | 22 | pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option<ImplBlock> { |
61 | module_impl_blocks: Arc<ModuleImplBlocks>, | 23 | let module = item.module(db); |
62 | item: AssocItem, | 24 | let crate_def_map = db.crate_def_map(module.id.krate); |
63 | ) -> Option<ImplBlock> { | 25 | crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| { |
64 | let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; | 26 | db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item) |
65 | Some(ImplBlock { module: module_impl_blocks.module, impl_id }) | 27 | }) |
66 | } | ||
67 | |||
68 | pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock { | ||
69 | ImplBlock { module, impl_id } | ||
70 | } | ||
71 | |||
72 | pub fn id(&self) -> ImplId { | ||
73 | self.impl_id | ||
74 | } | ||
75 | |||
76 | pub fn module(&self) -> Module { | ||
77 | self.module | ||
78 | } | 28 | } |
79 | 29 | ||
80 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { | 30 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { |
81 | db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() | 31 | db.impl_data(self.id).target_trait().cloned() |
82 | } | 32 | } |
83 | 33 | ||
84 | pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { | 34 | pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { |
85 | db.impls_in_module(self.module).impls[self.impl_id].target_type().clone() | 35 | db.impl_data(self.id).target_type().clone() |
86 | } | 36 | } |
87 | 37 | ||
88 | pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { | 38 | pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { |
@@ -95,15 +45,23 @@ impl ImplBlock { | |||
95 | } | 45 | } |
96 | 46 | ||
97 | pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { | 47 | pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { |
98 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() | 48 | db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect() |
99 | } | 49 | } |
100 | 50 | ||
101 | pub fn is_negative(&self, db: &impl DefDatabase) -> bool { | 51 | pub fn is_negative(&self, db: &impl DefDatabase) -> bool { |
102 | db.impls_in_module(self.module).impls[self.impl_id].negative | 52 | db.impl_data(self.id).is_negative() |
53 | } | ||
54 | |||
55 | pub fn module(&self, db: &impl DefDatabase) -> Module { | ||
56 | self.id.module(db).into() | ||
57 | } | ||
58 | |||
59 | pub fn krate(&self, db: &impl DefDatabase) -> Crate { | ||
60 | Crate { crate_id: self.module(db).id.krate } | ||
103 | } | 61 | } |
104 | 62 | ||
105 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | 63 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { |
106 | let r = self.module().resolver(db); | 64 | let r = self.module(db).resolver(db); |
107 | // add generic params, if present | 65 | // add generic params, if present |
108 | let p = self.generic_params(db); | 66 | let p = self.generic_params(db); |
109 | let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; | 67 | let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; |
@@ -111,175 +69,3 @@ impl ImplBlock { | |||
111 | r | 69 | r |
112 | } | 70 | } |
113 | } | 71 | } |
114 | |||
115 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
116 | pub struct ImplData { | ||
117 | target_trait: Option<TypeRef>, | ||
118 | target_type: TypeRef, | ||
119 | items: Vec<AssocItem>, | ||
120 | negative: bool, | ||
121 | } | ||
122 | |||
123 | impl ImplData { | ||
124 | pub(crate) fn from_ast( | ||
125 | db: &(impl DefDatabase + AstDatabase), | ||
126 | file_id: HirFileId, | ||
127 | module: Module, | ||
128 | node: &ast::ImplBlock, | ||
129 | ) -> Self { | ||
130 | let target_trait = node.target_trait().map(TypeRef::from_ast); | ||
131 | let target_type = TypeRef::from_ast_opt(node.target_type()); | ||
132 | let ctx = LocationCtx::new(db, module.id, file_id); | ||
133 | let negative = node.is_negative(); | ||
134 | let items = if let Some(item_list) = node.item_list() { | ||
135 | item_list | ||
136 | .impl_items() | ||
137 | .map(|item_node| match item_node { | ||
138 | ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(), | ||
139 | ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(), | ||
140 | ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(), | ||
141 | }) | ||
142 | .collect() | ||
143 | } else { | ||
144 | Vec::new() | ||
145 | }; | ||
146 | ImplData { target_trait, target_type, items, negative } | ||
147 | } | ||
148 | |||
149 | pub fn target_trait(&self) -> Option<&TypeRef> { | ||
150 | self.target_trait.as_ref() | ||
151 | } | ||
152 | |||
153 | pub fn target_type(&self) -> &TypeRef { | ||
154 | &self.target_type | ||
155 | } | ||
156 | |||
157 | pub fn items(&self) -> &[AssocItem] { | ||
158 | &self.items | ||
159 | } | ||
160 | } | ||
161 | |||
162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
163 | pub struct ImplId(pub RawId); | ||
164 | impl_arena_id!(ImplId); | ||
165 | |||
166 | /// The collection of impl blocks is a two-step process: first we collect the | ||
167 | /// blocks per-module; then we build an index of all impl blocks in the crate. | ||
168 | /// This way, we avoid having to do this process for the whole crate whenever | ||
169 | /// a file is changed; as long as the impl blocks in the file don't change, | ||
170 | /// we don't need to do the second step again. | ||
171 | #[derive(Debug, PartialEq, Eq)] | ||
172 | pub struct ModuleImplBlocks { | ||
173 | pub(crate) module: Module, | ||
174 | pub(crate) impls: Arena<ImplId, ImplData>, | ||
175 | impls_by_def: FxHashMap<AssocItem, ImplId>, | ||
176 | } | ||
177 | |||
178 | impl ModuleImplBlocks { | ||
179 | pub(crate) fn impls_in_module_with_source_map_query( | ||
180 | db: &(impl DefDatabase + AstDatabase), | ||
181 | module: Module, | ||
182 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { | ||
183 | let mut source_map = ImplSourceMap::default(); | ||
184 | let crate_graph = db.crate_graph(); | ||
185 | let cfg_options = crate_graph.cfg_options(module.id.krate); | ||
186 | |||
187 | let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map); | ||
188 | (Arc::new(result), Arc::new(source_map)) | ||
189 | } | ||
190 | |||
191 | pub(crate) fn impls_in_module_query( | ||
192 | db: &impl DefDatabase, | ||
193 | module: Module, | ||
194 | ) -> Arc<ModuleImplBlocks> { | ||
195 | db.impls_in_module_with_source_map(module).0 | ||
196 | } | ||
197 | |||
198 | fn collect( | ||
199 | db: &(impl DefDatabase + AstDatabase), | ||
200 | cfg_options: &CfgOptions, | ||
201 | module: Module, | ||
202 | source_map: &mut ImplSourceMap, | ||
203 | ) -> Self { | ||
204 | let mut m = ModuleImplBlocks { | ||
205 | module, | ||
206 | impls: Arena::default(), | ||
207 | impls_by_def: FxHashMap::default(), | ||
208 | }; | ||
209 | |||
210 | let src = m.module.definition_source(db); | ||
211 | match &src.ast { | ||
212 | ModuleSource::SourceFile(node) => { | ||
213 | m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id) | ||
214 | } | ||
215 | ModuleSource::Module(node) => { | ||
216 | let item_list = node.item_list().expect("inline module should have item list"); | ||
217 | m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id) | ||
218 | } | ||
219 | }; | ||
220 | m | ||
221 | } | ||
222 | |||
223 | fn collect_from_item_owner( | ||
224 | &mut self, | ||
225 | db: &(impl DefDatabase + AstDatabase), | ||
226 | cfg_options: &CfgOptions, | ||
227 | source_map: &mut ImplSourceMap, | ||
228 | owner: &dyn ast::ModuleItemOwner, | ||
229 | file_id: HirFileId, | ||
230 | ) { | ||
231 | let hygiene = Hygiene::new(db, file_id); | ||
232 | for item in owner.items_with_macros() { | ||
233 | match item { | ||
234 | ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { | ||
235 | let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene); | ||
236 | if attrs.map_or(false, |attrs| { | ||
237 | attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) | ||
238 | }) { | ||
239 | continue; | ||
240 | } | ||
241 | |||
242 | let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast); | ||
243 | let id = self.impls.alloc(impl_block); | ||
244 | for &impl_item in &self.impls[id].items { | ||
245 | self.impls_by_def.insert(impl_item, id); | ||
246 | } | ||
247 | |||
248 | source_map.insert(id, file_id, &impl_block_ast); | ||
249 | } | ||
250 | ast::ItemOrMacro::Item(_) => (), | ||
251 | ast::ItemOrMacro::Macro(macro_call) => { | ||
252 | let attrs = Attr::from_attrs_owner(¯o_call, &hygiene); | ||
253 | if attrs.map_or(false, |attrs| { | ||
254 | attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) | ||
255 | }) { | ||
256 | continue; | ||
257 | } | ||
258 | |||
259 | //FIXME: we should really cut down on the boilerplate required to process a macro | ||
260 | let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(¯o_call)); | ||
261 | if let Some(path) = | ||
262 | macro_call.path().and_then(|path| Path::from_src(path, &hygiene)) | ||
263 | { | ||
264 | if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) | ||
265 | { | ||
266 | let call_id = db.intern_macro(MacroCallLoc { def: def.id, ast_id }); | ||
267 | let file_id = call_id.as_file(MacroFileKind::Items); | ||
268 | if let Some(item_list) = | ||
269 | db.parse_or_expand(file_id).and_then(ast::MacroItems::cast) | ||
270 | { | ||
271 | self.collect_from_item_owner( | ||
272 | db, | ||
273 | cfg_options, | ||
274 | source_map, | ||
275 | &item_list, | ||
276 | file_id, | ||
277 | ) | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | } | ||
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index e1780ed38..fa2ef8a17 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs | |||
@@ -25,7 +25,7 @@ impl LangItemTarget { | |||
25 | Some(match self { | 25 | Some(match self { |
26 | LangItemTarget::Enum(e) => e.module(db).krate(), | 26 | LangItemTarget::Enum(e) => e.module(db).krate(), |
27 | LangItemTarget::Function(f) => f.module(db).krate(), | 27 | LangItemTarget::Function(f) => f.module(db).krate(), |
28 | LangItemTarget::ImplBlock(i) => i.module().krate(), | 28 | LangItemTarget::ImplBlock(i) => i.krate(db), |
29 | LangItemTarget::Static(s) => s.module(db).krate(), | 29 | LangItemTarget::Static(s) => s.module(db).krate(), |
30 | LangItemTarget::Struct(s) => s.module(db).krate(), | 30 | LangItemTarget::Struct(s) => s.module(db).krate(), |
31 | LangItemTarget::Trait(t) => t.module(db).krate(), | 31 | LangItemTarget::Trait(t) => t.module(db).krate(), |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 5ba847d35..da33c9591 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -54,12 +54,11 @@ mod test_db; | |||
54 | #[cfg(test)] | 54 | #[cfg(test)] |
55 | mod marks; | 55 | mod marks; |
56 | 56 | ||
57 | use hir_expand::AstId; | 57 | use crate::resolve::Resolver; |
58 | |||
59 | use crate::{ids::MacroFileKind, resolve::Resolver}; | ||
60 | 58 | ||
61 | pub use crate::{ | 59 | pub use crate::{ |
62 | adt::VariantDef, | 60 | adt::VariantDef, |
61 | code_model::ImplBlock, | ||
63 | code_model::{ | 62 | code_model::{ |
64 | attrs::{AttrDef, Attrs}, | 63 | attrs::{AttrDef, Attrs}, |
65 | docs::{DocDef, Docs, Documentation}, | 64 | docs::{DocDef, Docs, Documentation}, |
@@ -72,7 +71,6 @@ pub use crate::{ | |||
72 | from_source::FromSource, | 71 | from_source::FromSource, |
73 | generics::GenericDef, | 72 | generics::GenericDef, |
74 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, | 73 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, |
75 | impl_block::ImplBlock, | ||
76 | resolve::ScopeDef, | 74 | resolve::ScopeDef, |
77 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, | 75 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, |
78 | ty::{ | 76 | ty::{ |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 2fb913108..79b92180a 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -15,9 +15,8 @@ use crate::{ | |||
15 | db::{DefDatabase, HirDatabase}, | 15 | db::{DefDatabase, HirDatabase}, |
16 | expr::{ExprScopes, PatId, ScopeId}, | 16 | expr::{ExprScopes, PatId, ScopeId}, |
17 | generics::GenericParams, | 17 | generics::GenericParams, |
18 | impl_block::ImplBlock, | 18 | Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef, |
19 | Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, | 19 | PerNs, Static, Struct, Trait, TypeAlias, |
20 | Static, Struct, Trait, TypeAlias, | ||
21 | }; | 20 | }; |
22 | 21 | ||
23 | #[derive(Debug, Clone, Default)] | 22 | #[derive(Debug, Clone, Default)] |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 662d3f880..f0ed8e2b2 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -11,13 +11,12 @@ use hir_def::{ | |||
11 | expr::{ExprId, PatId}, | 11 | expr::{ExprId, PatId}, |
12 | path::known, | 12 | path::known, |
13 | }; | 13 | }; |
14 | use hir_expand::{name::AsName, Source}; | 14 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; |
15 | use ra_db::FileId; | ||
16 | use ra_syntax::{ | 15 | use ra_syntax::{ |
17 | ast::{self, AstNode}, | 16 | ast::{self, AstNode}, |
18 | match_ast, AstPtr, | 17 | match_ast, AstPtr, |
19 | SyntaxKind::*, | 18 | SyntaxKind::*, |
20 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 19 | SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, |
21 | }; | 20 | }; |
22 | 21 | ||
23 | use crate::{ | 22 | use crate::{ |
@@ -30,52 +29,45 @@ use crate::{ | |||
30 | HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, | 29 | HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, |
31 | }; | 30 | }; |
32 | 31 | ||
33 | fn try_get_resolver_for_node( | 32 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
34 | db: &impl HirDatabase, | ||
35 | file_id: FileId, | ||
36 | node: &SyntaxNode, | ||
37 | ) -> Option<Resolver> { | ||
38 | match_ast! { | 33 | match_ast! { |
39 | match node { | 34 | match (node.ast) { |
40 | ast::Module(it) => { | 35 | ast::Module(it) => { |
41 | let src = crate::Source { file_id: file_id.into(), ast: it }; | 36 | let src = node.with_ast(it); |
42 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) | 37 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) |
43 | }, | 38 | }, |
44 | ast::SourceFile(it) => { | 39 | ast::SourceFile(it) => { |
45 | let src = | 40 | let src = node.with_ast(crate::ModuleSource::SourceFile(it)); |
46 | crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(it) }; | ||
47 | Some(crate::Module::from_definition(db, src)?.resolver(db)) | 41 | Some(crate::Module::from_definition(db, src)?.resolver(db)) |
48 | }, | 42 | }, |
49 | ast::StructDef(it) => { | 43 | ast::StructDef(it) => { |
50 | let src = crate::Source { file_id: file_id.into(), ast: it }; | 44 | let src = node.with_ast(it); |
51 | Some(Struct::from_source(db, src)?.resolver(db)) | 45 | Some(Struct::from_source(db, src)?.resolver(db)) |
52 | }, | 46 | }, |
53 | ast::EnumDef(it) => { | 47 | ast::EnumDef(it) => { |
54 | let src = crate::Source { file_id: file_id.into(), ast: it }; | 48 | let src = node.with_ast(it); |
55 | Some(Enum::from_source(db, src)?.resolver(db)) | 49 | Some(Enum::from_source(db, src)?.resolver(db)) |
56 | }, | 50 | }, |
57 | _ => { | 51 | _ => match node.ast.kind() { |
58 | if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | 52 | FN_DEF | CONST_DEF | STATIC_DEF => { |
59 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) | 53 | Some(def_with_body_from_child_node(db, node)?.resolver(db)) |
60 | } else { | ||
61 | // FIXME add missing cases | ||
62 | None | ||
63 | } | 54 | } |
64 | }, | 55 | // FIXME add missing cases |
56 | _ => None | ||
57 | } | ||
65 | } | 58 | } |
66 | } | 59 | } |
67 | } | 60 | } |
68 | 61 | ||
69 | fn def_with_body_from_child_node( | 62 | fn def_with_body_from_child_node( |
70 | db: &impl HirDatabase, | 63 | db: &impl HirDatabase, |
71 | file_id: FileId, | 64 | child: Source<&SyntaxNode>, |
72 | node: &SyntaxNode, | ||
73 | ) -> Option<DefWithBody> { | 65 | ) -> Option<DefWithBody> { |
74 | let src = crate::ModuleSource::from_child_node(db, file_id, node); | 66 | let module_source = crate::ModuleSource::from_child_node(db, child); |
75 | let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?; | 67 | let module = Module::from_definition(db, Source::new(child.file_id, module_source))?; |
76 | let ctx = LocationCtx::new(db, module.id, file_id.into()); | 68 | let ctx = LocationCtx::new(db, module.id, child.file_id); |
77 | 69 | ||
78 | node.ancestors().find_map(|node| { | 70 | child.ast.ancestors().find_map(|node| { |
79 | match_ast! { | 71 | match_ast! { |
80 | match node { | 72 | match node { |
81 | ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, | 73 | ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, |
@@ -91,8 +83,7 @@ fn def_with_body_from_child_node( | |||
91 | /// original source files. It should not be used inside the HIR itself. | 83 | /// original source files. It should not be used inside the HIR itself. |
92 | #[derive(Debug)] | 84 | #[derive(Debug)] |
93 | pub struct SourceAnalyzer { | 85 | pub struct SourceAnalyzer { |
94 | // FIXME: this doesn't handle macros at all | 86 | file_id: HirFileId, |
95 | file_id: FileId, | ||
96 | resolver: Resolver, | 87 | resolver: Resolver, |
97 | body_owner: Option<DefWithBody>, | 88 | body_owner: Option<DefWithBody>, |
98 | body_source_map: Option<Arc<BodySourceMap>>, | 89 | body_source_map: Option<Arc<BodySourceMap>>, |
@@ -135,20 +126,38 @@ pub struct ReferenceDescriptor { | |||
135 | pub name: String, | 126 | pub name: String, |
136 | } | 127 | } |
137 | 128 | ||
129 | pub struct Expansion { | ||
130 | macro_call_id: MacroCallId, | ||
131 | } | ||
132 | |||
133 | impl Expansion { | ||
134 | pub fn map_token_down( | ||
135 | &self, | ||
136 | db: &impl HirDatabase, | ||
137 | token: Source<&SyntaxToken>, | ||
138 | ) -> Option<Source<SyntaxToken>> { | ||
139 | let exp_info = self.file_id().expansion_info(db)?; | ||
140 | exp_info.map_token_down(token) | ||
141 | } | ||
142 | |||
143 | fn file_id(&self) -> HirFileId { | ||
144 | self.macro_call_id.as_file(MacroFileKind::Items) | ||
145 | } | ||
146 | } | ||
147 | |||
138 | impl SourceAnalyzer { | 148 | impl SourceAnalyzer { |
139 | pub fn new( | 149 | pub fn new( |
140 | db: &impl HirDatabase, | 150 | db: &impl HirDatabase, |
141 | file_id: FileId, | 151 | node: Source<&SyntaxNode>, |
142 | node: &SyntaxNode, | ||
143 | offset: Option<TextUnit>, | 152 | offset: Option<TextUnit>, |
144 | ) -> SourceAnalyzer { | 153 | ) -> SourceAnalyzer { |
145 | let def_with_body = def_with_body_from_child_node(db, file_id, node); | 154 | let def_with_body = def_with_body_from_child_node(db, node); |
146 | if let Some(def) = def_with_body { | 155 | if let Some(def) = def_with_body { |
147 | let source_map = def.body_source_map(db); | 156 | let source_map = def.body_source_map(db); |
148 | let scopes = def.expr_scopes(db); | 157 | let scopes = def.expr_scopes(db); |
149 | let scope = match offset { | 158 | let scope = match offset { |
150 | None => scope_for(&scopes, &source_map, file_id.into(), &node), | 159 | None => scope_for(&scopes, &source_map, node), |
151 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), | 160 | Some(offset) => scope_for_offset(&scopes, &source_map, node.with_ast(offset)), |
152 | }; | 161 | }; |
153 | let resolver = expr::resolver_for_scope(db, def, scope); | 162 | let resolver = expr::resolver_for_scope(db, def, scope); |
154 | SourceAnalyzer { | 163 | SourceAnalyzer { |
@@ -157,30 +166,31 @@ impl SourceAnalyzer { | |||
157 | body_source_map: Some(source_map), | 166 | body_source_map: Some(source_map), |
158 | infer: Some(def.infer(db)), | 167 | infer: Some(def.infer(db)), |
159 | scopes: Some(scopes), | 168 | scopes: Some(scopes), |
160 | file_id, | 169 | file_id: node.file_id, |
161 | } | 170 | } |
162 | } else { | 171 | } else { |
163 | SourceAnalyzer { | 172 | SourceAnalyzer { |
164 | resolver: node | 173 | resolver: node |
174 | .ast | ||
165 | .ancestors() | 175 | .ancestors() |
166 | .find_map(|node| try_get_resolver_for_node(db, file_id, &node)) | 176 | .find_map(|it| try_get_resolver_for_node(db, node.with_ast(&it))) |
167 | .unwrap_or_default(), | 177 | .unwrap_or_default(), |
168 | body_owner: None, | 178 | body_owner: None, |
169 | body_source_map: None, | 179 | body_source_map: None, |
170 | infer: None, | 180 | infer: None, |
171 | scopes: None, | 181 | scopes: None, |
172 | file_id, | 182 | file_id: node.file_id, |
173 | } | 183 | } |
174 | } | 184 | } |
175 | } | 185 | } |
176 | 186 | ||
177 | fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { | 187 | fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { |
178 | let src = Source { file_id: self.file_id.into(), ast: expr }; | 188 | let src = Source { file_id: self.file_id, ast: expr }; |
179 | self.body_source_map.as_ref()?.node_expr(src) | 189 | self.body_source_map.as_ref()?.node_expr(src) |
180 | } | 190 | } |
181 | 191 | ||
182 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { | 192 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { |
183 | let src = Source { file_id: self.file_id.into(), ast: pat }; | 193 | let src = Source { file_id: self.file_id, ast: pat }; |
184 | self.body_source_map.as_ref()?.node_pat(src) | 194 | self.body_source_map.as_ref()?.node_pat(src) |
185 | } | 195 | } |
186 | 196 | ||
@@ -288,7 +298,7 @@ impl SourceAnalyzer { | |||
288 | let name = name_ref.as_name(); | 298 | let name = name_ref.as_name(); |
289 | let source_map = self.body_source_map.as_ref()?; | 299 | let source_map = self.body_source_map.as_ref()?; |
290 | let scopes = self.scopes.as_ref()?; | 300 | let scopes = self.scopes.as_ref()?; |
291 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax())?; | 301 | let scope = scope_for(scopes, source_map, Source::new(self.file_id, name_ref.syntax()))?; |
292 | let entry = scopes.resolve_name_in_scope(scope, &name)?; | 302 | let entry = scopes.resolve_name_in_scope(scope, &name)?; |
293 | Some(ScopeEntryWithSyntax { | 303 | Some(ScopeEntryWithSyntax { |
294 | name: entry.name().clone(), | 304 | name: entry.name().clone(), |
@@ -395,6 +405,13 @@ impl SourceAnalyzer { | |||
395 | implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) | 405 | implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) |
396 | } | 406 | } |
397 | 407 | ||
408 | pub fn expand(&self, db: &impl HirDatabase, macro_call: &ast::MacroCall) -> Option<Expansion> { | ||
409 | let def = self.resolve_macro_call(db, macro_call)?.id; | ||
410 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(macro_call)); | ||
411 | let macro_call_loc = MacroCallLoc { def, ast_id }; | ||
412 | Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) | ||
413 | } | ||
414 | |||
398 | #[cfg(test)] | 415 | #[cfg(test)] |
399 | pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> { | 416 | pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> { |
400 | self.body_source_map.clone().unwrap() | 417 | self.body_source_map.clone().unwrap() |
@@ -409,20 +426,19 @@ impl SourceAnalyzer { | |||
409 | fn scope_for( | 426 | fn scope_for( |
410 | scopes: &ExprScopes, | 427 | scopes: &ExprScopes, |
411 | source_map: &BodySourceMap, | 428 | source_map: &BodySourceMap, |
412 | file_id: HirFileId, | 429 | node: Source<&SyntaxNode>, |
413 | node: &SyntaxNode, | ||
414 | ) -> Option<ScopeId> { | 430 | ) -> Option<ScopeId> { |
415 | node.ancestors() | 431 | node.ast |
432 | .ancestors() | ||
416 | .filter_map(ast::Expr::cast) | 433 | .filter_map(ast::Expr::cast) |
417 | .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it })) | 434 | .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) |
418 | .find_map(|it| scopes.scope_for(it)) | 435 | .find_map(|it| scopes.scope_for(it)) |
419 | } | 436 | } |
420 | 437 | ||
421 | fn scope_for_offset( | 438 | fn scope_for_offset( |
422 | scopes: &ExprScopes, | 439 | scopes: &ExprScopes, |
423 | source_map: &BodySourceMap, | 440 | source_map: &BodySourceMap, |
424 | file_id: HirFileId, | 441 | offset: Source<TextUnit>, |
425 | offset: TextUnit, | ||
426 | ) -> Option<ScopeId> { | 442 | ) -> Option<ScopeId> { |
427 | scopes | 443 | scopes |
428 | .scope_by_expr() | 444 | .scope_by_expr() |
@@ -430,7 +446,7 @@ fn scope_for_offset( | |||
430 | .filter_map(|(id, scope)| { | 446 | .filter_map(|(id, scope)| { |
431 | let source = source_map.expr_syntax(*id)?; | 447 | let source = source_map.expr_syntax(*id)?; |
432 | // FIXME: correctly handle macro expansion | 448 | // FIXME: correctly handle macro expansion |
433 | if source.file_id != file_id { | 449 | if source.file_id != offset.file_id { |
434 | return None; | 450 | return None; |
435 | } | 451 | } |
436 | let syntax_node_ptr = | 452 | let syntax_node_ptr = |
@@ -439,9 +455,14 @@ fn scope_for_offset( | |||
439 | }) | 455 | }) |
440 | // find containing scope | 456 | // find containing scope |
441 | .min_by_key(|(ptr, _scope)| { | 457 | .min_by_key(|(ptr, _scope)| { |
442 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) | 458 | ( |
459 | !(ptr.range().start() <= offset.ast && offset.ast <= ptr.range().end()), | ||
460 | ptr.range().len(), | ||
461 | ) | ||
462 | }) | ||
463 | .map(|(ptr, scope)| { | ||
464 | adjust(scopes, source_map, ptr, offset.file_id, offset.ast).unwrap_or(*scope) | ||
443 | }) | 465 | }) |
444 | .map(|(ptr, scope)| adjust(scopes, source_map, ptr, file_id, offset).unwrap_or(*scope)) | ||
445 | } | 466 | } |
446 | 467 | ||
447 | // XXX: during completion, cursor might be outside of any particular | 468 | // XXX: during completion, cursor might be outside of any particular |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index ff6030ac4..b7f50b714 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -79,7 +79,7 @@ pub enum TypeCtor { | |||
79 | /// | 79 | /// |
80 | /// For example the type of `bar` here: | 80 | /// For example the type of `bar` here: |
81 | /// | 81 | /// |
82 | /// ```rust | 82 | /// ``` |
83 | /// fn foo() -> i32 { 1 } | 83 | /// fn foo() -> i32 { 1 } |
84 | /// let bar = foo; // bar: fn() -> i32 {foo} | 84 | /// let bar = foo; // bar: fn() -> i32 {foo} |
85 | /// ``` | 85 | /// ``` |
@@ -89,7 +89,7 @@ pub enum TypeCtor { | |||
89 | /// | 89 | /// |
90 | /// For example the type of `bar` here: | 90 | /// For example the type of `bar` here: |
91 | /// | 91 | /// |
92 | /// ```rust | 92 | /// ``` |
93 | /// fn foo() -> i32 { 1 } | 93 | /// fn foo() -> i32 { 1 } |
94 | /// let bar: fn() -> i32 = foo; | 94 | /// let bar: fn() -> i32 = foo; |
95 | /// ``` | 95 | /// ``` |
@@ -224,8 +224,8 @@ impl TypeWalk for ProjectionTy { | |||
224 | self.parameters.walk(f); | 224 | self.parameters.walk(f); |
225 | } | 225 | } |
226 | 226 | ||
227 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 227 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
228 | self.parameters.walk_mut(f); | 228 | self.parameters.walk_mut_binders(f, binders); |
229 | } | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
@@ -291,6 +291,20 @@ pub enum Ty { | |||
291 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 291 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
292 | pub struct Substs(Arc<[Ty]>); | 292 | pub struct Substs(Arc<[Ty]>); |
293 | 293 | ||
294 | impl TypeWalk for Substs { | ||
295 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
296 | for t in self.0.iter() { | ||
297 | t.walk(f); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { | ||
302 | for t in make_mut_slice(&mut self.0) { | ||
303 | t.walk_mut_binders(f, binders); | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | |||
294 | impl Substs { | 308 | impl Substs { |
295 | pub fn empty() -> Substs { | 309 | pub fn empty() -> Substs { |
296 | Substs(Arc::new([])) | 310 | Substs(Arc::new([])) |
@@ -304,18 +318,6 @@ impl Substs { | |||
304 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) | 318 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) |
305 | } | 319 | } |
306 | 320 | ||
307 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
308 | for t in self.0.iter() { | ||
309 | t.walk(f); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
314 | for t in make_mut_slice(&mut self.0) { | ||
315 | t.walk_mut(f); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | pub fn as_single(&self) -> &Ty { | 321 | pub fn as_single(&self) -> &Ty { |
320 | if self.0.len() != 1 { | 322 | if self.0.len() != 1 { |
321 | panic!("expected substs of len 1, got {:?}", self); | 323 | panic!("expected substs of len 1, got {:?}", self); |
@@ -440,8 +442,8 @@ impl TypeWalk for TraitRef { | |||
440 | self.substs.walk(f); | 442 | self.substs.walk(f); |
441 | } | 443 | } |
442 | 444 | ||
443 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 445 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
444 | self.substs.walk_mut(f); | 446 | self.substs.walk_mut_binders(f, binders); |
445 | } | 447 | } |
446 | } | 448 | } |
447 | 449 | ||
@@ -491,10 +493,12 @@ impl TypeWalk for GenericPredicate { | |||
491 | } | 493 | } |
492 | } | 494 | } |
493 | 495 | ||
494 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 496 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
495 | match self { | 497 | match self { |
496 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | 498 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), |
497 | GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), | 499 | GenericPredicate::Projection(projection_pred) => { |
500 | projection_pred.walk_mut_binders(f, binders) | ||
501 | } | ||
498 | GenericPredicate::Error => {} | 502 | GenericPredicate::Error => {} |
499 | } | 503 | } |
500 | } | 504 | } |
@@ -544,9 +548,9 @@ impl TypeWalk for FnSig { | |||
544 | } | 548 | } |
545 | } | 549 | } |
546 | 550 | ||
547 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 551 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
548 | for t in make_mut_slice(&mut self.params_and_return) { | 552 | for t in make_mut_slice(&mut self.params_and_return) { |
549 | t.walk_mut(f); | 553 | t.walk_mut_binders(f, binders); |
550 | } | 554 | } |
551 | } | 555 | } |
552 | } | 556 | } |
@@ -671,7 +675,20 @@ impl Ty { | |||
671 | /// types, similar to Chalk's `Fold` trait. | 675 | /// types, similar to Chalk's `Fold` trait. |
672 | pub trait TypeWalk { | 676 | pub trait TypeWalk { |
673 | fn walk(&self, f: &mut impl FnMut(&Ty)); | 677 | fn walk(&self, f: &mut impl FnMut(&Ty)); |
674 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)); | 678 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
679 | self.walk_mut_binders(&mut |ty, _binders| f(ty), 0); | ||
680 | } | ||
681 | /// Walk the type, counting entered binders. | ||
682 | /// | ||
683 | /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
684 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
685 | /// substitute a certain bound variable, we can't just walk the whole type | ||
686 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
687 | /// things that introduce new bound variables, we have to keep track of | ||
688 | /// that. Currently, the only thing that introduces bound variables on our | ||
689 | /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound | ||
690 | /// variable for the self type. | ||
691 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize); | ||
675 | 692 | ||
676 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | 693 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self |
677 | where | 694 | where |
@@ -700,14 +717,22 @@ pub trait TypeWalk { | |||
700 | } | 717 | } |
701 | 718 | ||
702 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | 719 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). |
703 | fn subst_bound_vars(self, substs: &Substs) -> Self | 720 | fn subst_bound_vars(mut self, substs: &Substs) -> Self |
704 | where | 721 | where |
705 | Self: Sized, | 722 | Self: Sized, |
706 | { | 723 | { |
707 | self.fold(&mut |ty| match ty { | 724 | self.walk_mut_binders( |
708 | Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)), | 725 | &mut |ty, binders| match ty { |
709 | ty => ty, | 726 | &mut Ty::Bound(idx) => { |
710 | }) | 727 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
728 | *ty = substs.0[idx as usize - binders].clone(); | ||
729 | } | ||
730 | } | ||
731 | _ => {} | ||
732 | }, | ||
733 | 0, | ||
734 | ); | ||
735 | self | ||
711 | } | 736 | } |
712 | 737 | ||
713 | /// Shifts up `Ty::Bound` vars by `n`. | 738 | /// Shifts up `Ty::Bound` vars by `n`. |
@@ -748,22 +773,22 @@ impl TypeWalk for Ty { | |||
748 | f(self); | 773 | f(self); |
749 | } | 774 | } |
750 | 775 | ||
751 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 776 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
752 | match self { | 777 | match self { |
753 | Ty::Apply(a_ty) => { | 778 | Ty::Apply(a_ty) => { |
754 | a_ty.parameters.walk_mut(f); | 779 | a_ty.parameters.walk_mut_binders(f, binders); |
755 | } | 780 | } |
756 | Ty::Projection(p_ty) => { | 781 | Ty::Projection(p_ty) => { |
757 | p_ty.parameters.walk_mut(f); | 782 | p_ty.parameters.walk_mut_binders(f, binders); |
758 | } | 783 | } |
759 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 784 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
760 | for p in make_mut_slice(predicates) { | 785 | for p in make_mut_slice(predicates) { |
761 | p.walk_mut(f); | 786 | p.walk_mut_binders(f, binders + 1); |
762 | } | 787 | } |
763 | } | 788 | } |
764 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 789 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
765 | } | 790 | } |
766 | f(self); | 791 | f(self, binders); |
767 | } | 792 | } |
768 | } | 793 | } |
769 | 794 | ||
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index ca33cc7f8..64d9394cf 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -134,17 +134,19 @@ where | |||
134 | } | 134 | } |
135 | 135 | ||
136 | impl<T> Canonicalized<T> { | 136 | impl<T> Canonicalized<T> { |
137 | pub fn decanonicalize_ty(&self, ty: Ty) -> Ty { | 137 | pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { |
138 | ty.fold(&mut |ty| match ty { | 138 | ty.walk_mut_binders( |
139 | Ty::Bound(idx) => { | 139 | &mut |ty, binders| match ty { |
140 | if (idx as usize) < self.free_vars.len() { | 140 | &mut Ty::Bound(idx) => { |
141 | Ty::Infer(self.free_vars[idx as usize]) | 141 | if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() { |
142 | } else { | 142 | *ty = Ty::Infer(self.free_vars[idx as usize - binders]); |
143 | Ty::Bound(idx) | 143 | } |
144 | } | 144 | } |
145 | } | 145 | _ => {} |
146 | ty => ty, | 146 | }, |
147 | }) | 147 | 0, |
148 | ); | ||
149 | ty | ||
148 | } | 150 | } |
149 | 151 | ||
150 | pub fn apply_solution( | 152 | pub fn apply_solution( |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index eb5ca6769..d20aeaacf 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -5,16 +5,14 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::CrateModuleId; | ||
9 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
10 | 9 | ||
11 | use crate::{ | 10 | use crate::{ |
12 | db::HirDatabase, | 11 | db::HirDatabase, |
13 | impl_block::{ImplBlock, ImplId}, | ||
14 | resolve::Resolver, | 12 | resolve::Resolver, |
15 | ty::primitive::{FloatBitness, Uncertain}, | 13 | ty::primitive::{FloatBitness, Uncertain}, |
16 | ty::{Ty, TypeCtor}, | 14 | ty::{Ty, TypeCtor}, |
17 | AssocItem, Crate, Function, Module, Mutability, Name, Trait, | 15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, |
18 | }; | 16 | }; |
19 | 17 | ||
20 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 18 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
@@ -39,65 +37,46 @@ impl TyFingerprint { | |||
39 | 37 | ||
40 | #[derive(Debug, PartialEq, Eq)] | 38 | #[derive(Debug, PartialEq, Eq)] |
41 | pub struct CrateImplBlocks { | 39 | pub struct CrateImplBlocks { |
42 | /// To make sense of the CrateModuleIds, we need the source root. | 40 | impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>, |
43 | krate: Crate, | 41 | impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>, |
44 | impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>, | ||
45 | impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>, | ||
46 | } | 42 | } |
47 | 43 | ||
48 | impl CrateImplBlocks { | 44 | impl CrateImplBlocks { |
49 | pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + 'a { | 45 | pub(crate) fn impls_in_crate_query( |
46 | db: &impl HirDatabase, | ||
47 | krate: Crate, | ||
48 | ) -> Arc<CrateImplBlocks> { | ||
49 | let mut crate_impl_blocks = | ||
50 | CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; | ||
51 | if let Some(module) = krate.root_module(db) { | ||
52 | crate_impl_blocks.collect_recursive(db, module); | ||
53 | } | ||
54 | Arc::new(crate_impl_blocks) | ||
55 | } | ||
56 | pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + '_ { | ||
50 | let fingerprint = TyFingerprint::for_impl(ty); | 57 | let fingerprint = TyFingerprint::for_impl(ty); |
51 | fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map( | 58 | fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() |
52 | move |(module_id, impl_id)| { | ||
53 | let module = Module::new(self.krate, *module_id); | ||
54 | ImplBlock::from_id(module, *impl_id) | ||
55 | }, | ||
56 | ) | ||
57 | } | 59 | } |
58 | 60 | ||
59 | pub fn lookup_impl_blocks_for_trait<'a>( | 61 | pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ { |
60 | &'a self, | 62 | self.impls_by_trait.get(&tr).into_iter().flatten().copied() |
61 | tr: Trait, | ||
62 | ) -> impl Iterator<Item = ImplBlock> + 'a { | ||
63 | self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map( | ||
64 | move |(module_id, impl_id)| { | ||
65 | let module = Module::new(self.krate, *module_id); | ||
66 | ImplBlock::from_id(module, *impl_id) | ||
67 | }, | ||
68 | ) | ||
69 | } | 63 | } |
70 | 64 | ||
71 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { | 65 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { |
72 | self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map( | 66 | self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() |
73 | move |(module_id, impl_id)| { | ||
74 | let module = Module::new(self.krate, *module_id); | ||
75 | ImplBlock::from_id(module, *impl_id) | ||
76 | }, | ||
77 | ) | ||
78 | } | 67 | } |
79 | 68 | ||
80 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { | 69 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { |
81 | let module_impl_blocks = db.impls_in_module(module); | 70 | for impl_block in module.impl_blocks(db) { |
82 | |||
83 | for (impl_id, _) in module_impl_blocks.impls.iter() { | ||
84 | let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id); | ||
85 | |||
86 | let target_ty = impl_block.target_ty(db); | 71 | let target_ty = impl_block.target_ty(db); |
87 | 72 | ||
88 | if impl_block.target_trait(db).is_some() { | 73 | if impl_block.target_trait(db).is_some() { |
89 | if let Some(tr) = impl_block.target_trait_ref(db) { | 74 | if let Some(tr) = impl_block.target_trait_ref(db) { |
90 | self.impls_by_trait | 75 | self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block); |
91 | .entry(tr.trait_) | ||
92 | .or_insert_with(Vec::new) | ||
93 | .push((module.id.module_id, impl_id)); | ||
94 | } | 76 | } |
95 | } else { | 77 | } else { |
96 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | 78 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { |
97 | self.impls | 79 | self.impls.entry(target_ty_fp).or_default().push(impl_block); |
98 | .entry(target_ty_fp) | ||
99 | .or_insert_with(Vec::new) | ||
100 | .push((module.id.module_id, impl_id)); | ||
101 | } | 80 | } |
102 | } | 81 | } |
103 | } | 82 | } |
@@ -106,21 +85,6 @@ impl CrateImplBlocks { | |||
106 | self.collect_recursive(db, child); | 85 | self.collect_recursive(db, child); |
107 | } | 86 | } |
108 | } | 87 | } |
109 | |||
110 | pub(crate) fn impls_in_crate_query( | ||
111 | db: &impl HirDatabase, | ||
112 | krate: Crate, | ||
113 | ) -> Arc<CrateImplBlocks> { | ||
114 | let mut crate_impl_blocks = CrateImplBlocks { | ||
115 | krate, | ||
116 | impls: FxHashMap::default(), | ||
117 | impls_by_trait: FxHashMap::default(), | ||
118 | }; | ||
119 | if let Some(module) = krate.root_module(db) { | ||
120 | crate_impl_blocks.collect_recursive(db, module); | ||
121 | } | ||
122 | Arc::new(crate_impl_blocks) | ||
123 | } | ||
124 | } | 88 | } |
125 | 89 | ||
126 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { | 90 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { |
@@ -264,14 +228,10 @@ fn iterate_trait_method_candidates<T>( | |||
264 | 'traits: for t in traits { | 228 | 'traits: for t in traits { |
265 | let data = t.trait_data(db); | 229 | let data = t.trait_data(db); |
266 | 230 | ||
267 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
268 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
269 | let inherently_implemented = ty.value.inherent_trait() == Some(t); | ||
270 | |||
271 | // we'll be lazy about checking whether the type implements the | 231 | // we'll be lazy about checking whether the type implements the |
272 | // trait, but if we find out it doesn't, we'll skip the rest of the | 232 | // trait, but if we find out it doesn't, we'll skip the rest of the |
273 | // iteration | 233 | // iteration |
274 | let mut known_implemented = inherently_implemented; | 234 | let mut known_implemented = false; |
275 | for &item in data.items() { | 235 | for &item in data.items() { |
276 | if !is_valid_candidate(db, name, mode, item) { | 236 | if !is_valid_candidate(db, name, mode, item) { |
277 | continue; | 237 | continue; |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index fe9346c78..ca1693679 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1,3 +1,6 @@ | |||
1 | mod never_type; | ||
2 | mod coercion; | ||
3 | |||
1 | use std::fmt::Write; | 4 | use std::fmt::Write; |
2 | use std::sync::Arc; | 5 | use std::sync::Arc; |
3 | 6 | ||
@@ -11,7 +14,7 @@ use ra_syntax::{ | |||
11 | use test_utils::covers; | 14 | use test_utils::covers; |
12 | 15 | ||
13 | use crate::{ | 16 | use crate::{ |
14 | expr::BodySourceMap, test_db::TestDB, ty::display::HirDisplay, ty::InferenceResult, | 17 | expr::BodySourceMap, test_db::TestDB, ty::display::HirDisplay, ty::InferenceResult, Source, |
15 | SourceAnalyzer, | 18 | SourceAnalyzer, |
16 | }; | 19 | }; |
17 | 20 | ||
@@ -19,9 +22,6 @@ use crate::{ | |||
19 | // against snapshots of the expected results using insta. Use cargo-insta to | 22 | // against snapshots of the expected results using insta. Use cargo-insta to |
20 | // update the snapshots. | 23 | // update the snapshots. |
21 | 24 | ||
22 | mod never_type; | ||
23 | mod coercion; | ||
24 | |||
25 | #[test] | 25 | #[test] |
26 | fn cfg_impl_block() { | 26 | fn cfg_impl_block() { |
27 | let (db, pos) = TestDB::with_position( | 27 | let (db, pos) = TestDB::with_position( |
@@ -3983,11 +3983,11 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | |||
3983 | [180; 183) 'bar': fn bar() -> impl Trait<u64> | 3983 | [180; 183) 'bar': fn bar() -> impl Trait<u64> |
3984 | [180; 185) 'bar()': impl Trait<u64> | 3984 | [180; 185) 'bar()': impl Trait<u64> |
3985 | [191; 192) 'x': impl Trait<u64> | 3985 | [191; 192) 'x': impl Trait<u64> |
3986 | [191; 198) 'x.foo()': {unknown} | 3986 | [191; 198) 'x.foo()': u64 |
3987 | [204; 205) 'y': &impl Trait<u64> | 3987 | [204; 205) 'y': &impl Trait<u64> |
3988 | [204; 211) 'y.foo()': {unknown} | 3988 | [204; 211) 'y.foo()': u64 |
3989 | [217; 218) 'z': impl Trait<u64> | 3989 | [217; 218) 'z': impl Trait<u64> |
3990 | [217; 224) 'z.foo()': {unknown} | 3990 | [217; 224) 'z.foo()': u64 |
3991 | [230; 231) 'x': impl Trait<u64> | 3991 | [230; 231) 'x': impl Trait<u64> |
3992 | [230; 238) 'x.foo2()': i64 | 3992 | [230; 238) 'x.foo2()': i64 |
3993 | [244; 245) 'y': &impl Trait<u64> | 3993 | [244; 245) 'y': &impl Trait<u64> |
@@ -4033,11 +4033,11 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | |||
4033 | [177; 180) 'bar': fn bar() -> dyn Trait<u64> | 4033 | [177; 180) 'bar': fn bar() -> dyn Trait<u64> |
4034 | [177; 182) 'bar()': dyn Trait<u64> | 4034 | [177; 182) 'bar()': dyn Trait<u64> |
4035 | [188; 189) 'x': dyn Trait<u64> | 4035 | [188; 189) 'x': dyn Trait<u64> |
4036 | [188; 195) 'x.foo()': {unknown} | 4036 | [188; 195) 'x.foo()': u64 |
4037 | [201; 202) 'y': &dyn Trait<u64> | 4037 | [201; 202) 'y': &dyn Trait<u64> |
4038 | [201; 208) 'y.foo()': {unknown} | 4038 | [201; 208) 'y.foo()': u64 |
4039 | [214; 215) 'z': dyn Trait<u64> | 4039 | [214; 215) 'z': dyn Trait<u64> |
4040 | [214; 221) 'z.foo()': {unknown} | 4040 | [214; 221) 'z.foo()': u64 |
4041 | [227; 228) 'x': dyn Trait<u64> | 4041 | [227; 228) 'x': dyn Trait<u64> |
4042 | [227; 235) 'x.foo2()': i64 | 4042 | [227; 235) 'x.foo2()': i64 |
4043 | [241; 242) 'y': &dyn Trait<u64> | 4043 | [241; 242) 'y': &dyn Trait<u64> |
@@ -4185,6 +4185,49 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | |||
4185 | } | 4185 | } |
4186 | 4186 | ||
4187 | #[test] | 4187 | #[test] |
4188 | fn impl_trait_assoc_binding_projection_bug() { | ||
4189 | let (db, pos) = TestDB::with_position( | ||
4190 | r#" | ||
4191 | //- /main.rs crate:main deps:std | ||
4192 | pub trait Language { | ||
4193 | type Kind; | ||
4194 | } | ||
4195 | pub enum RustLanguage {} | ||
4196 | impl Language for RustLanguage { | ||
4197 | type Kind = SyntaxKind; | ||
4198 | } | ||
4199 | struct SyntaxNode<L> {} | ||
4200 | fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {} | ||
4201 | |||
4202 | trait Clone { | ||
4203 | fn clone(&self) -> Self; | ||
4204 | } | ||
4205 | |||
4206 | fn api_walkthrough() { | ||
4207 | for node in foo() { | ||
4208 | node.clone()<|>; | ||
4209 | } | ||
4210 | } | ||
4211 | |||
4212 | //- /std.rs crate:std | ||
4213 | #[prelude_import] use iter::*; | ||
4214 | mod iter { | ||
4215 | trait IntoIterator { | ||
4216 | type Item; | ||
4217 | } | ||
4218 | trait Iterator { | ||
4219 | type Item; | ||
4220 | } | ||
4221 | impl<T: Iterator> IntoIterator for T { | ||
4222 | type Item = <T as Iterator>::Item; | ||
4223 | } | ||
4224 | } | ||
4225 | "#, | ||
4226 | ); | ||
4227 | assert_eq!("{unknown}", type_at_pos(&db, pos)); | ||
4228 | } | ||
4229 | |||
4230 | #[test] | ||
4188 | fn projection_eq_within_chalk() { | 4231 | fn projection_eq_within_chalk() { |
4189 | // std::env::set_var("CHALK_DEBUG", "1"); | 4232 | // std::env::set_var("CHALK_DEBUG", "1"); |
4190 | assert_snapshot!( | 4233 | assert_snapshot!( |
@@ -4609,7 +4652,8 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
4609 | fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { | 4652 | fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { |
4610 | let file = db.parse(pos.file_id).ok().unwrap(); | 4653 | let file = db.parse(pos.file_id).ok().unwrap(); |
4611 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 4654 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
4612 | let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset)); | 4655 | let analyzer = |
4656 | SourceAnalyzer::new(db, Source::new(pos.file_id.into(), expr.syntax()), Some(pos.offset)); | ||
4613 | let ty = analyzer.type_of(db, &expr).unwrap(); | 4657 | let ty = analyzer.type_of(db, &expr).unwrap(); |
4614 | ty.display(db).to_string() | 4658 | ty.display(db).to_string() |
4615 | } | 4659 | } |
@@ -4674,7 +4718,7 @@ fn infer(content: &str) -> String { | |||
4674 | 4718 | ||
4675 | for node in source_file.syntax().descendants() { | 4719 | for node in source_file.syntax().descendants() { |
4676 | if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | 4720 | if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { |
4677 | let analyzer = SourceAnalyzer::new(&db, file_id, &node, None); | 4721 | let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None); |
4678 | infer_def(analyzer.inference_result(), analyzer.body_source_map()); | 4722 | infer_def(analyzer.inference_result(), analyzer.body_source_map()); |
4679 | } | 4723 | } |
4680 | } | 4724 | } |
@@ -4715,7 +4759,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | |||
4715 | let file = db.parse(pos.file_id).ok().unwrap(); | 4759 | let file = db.parse(pos.file_id).ok().unwrap(); |
4716 | let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent(); | 4760 | let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent(); |
4717 | let events = db.log_executed(|| { | 4761 | let events = db.log_executed(|| { |
4718 | SourceAnalyzer::new(&db, pos.file_id, &node, None); | 4762 | SourceAnalyzer::new(&db, Source::new(pos.file_id.into(), &node), None); |
4719 | }); | 4763 | }); |
4720 | assert!(format!("{:?}", events).contains("infer")) | 4764 | assert!(format!("{:?}", events).contains("infer")) |
4721 | } | 4765 | } |
@@ -4735,7 +4779,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | |||
4735 | let file = db.parse(pos.file_id).ok().unwrap(); | 4779 | let file = db.parse(pos.file_id).ok().unwrap(); |
4736 | let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent(); | 4780 | let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent(); |
4737 | let events = db.log_executed(|| { | 4781 | let events = db.log_executed(|| { |
4738 | SourceAnalyzer::new(&db, pos.file_id, &node, None); | 4782 | SourceAnalyzer::new(&db, Source::new(pos.file_id.into(), &node), None); |
4739 | }); | 4783 | }); |
4740 | assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) | 4784 | assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) |
4741 | } | 4785 | } |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 4f1eab150..45f725438 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -8,7 +8,7 @@ use ra_prof::profile; | |||
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
9 | 9 | ||
10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait}; | 11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias}; |
12 | 12 | ||
13 | use self::chalk::{from_chalk, ToChalk}; | 13 | use self::chalk::{from_chalk, ToChalk}; |
14 | 14 | ||
@@ -17,7 +17,7 @@ pub(crate) mod chalk; | |||
17 | #[derive(Debug, Clone)] | 17 | #[derive(Debug, Clone)] |
18 | pub struct TraitSolver { | 18 | pub struct TraitSolver { |
19 | krate: Crate, | 19 | krate: Crate, |
20 | inner: Arc<Mutex<chalk_solve::Solver>>, | 20 | inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, |
21 | } | 21 | } |
22 | 22 | ||
23 | /// We need eq for salsa | 23 | /// We need eq for salsa |
@@ -34,7 +34,7 @@ impl TraitSolver { | |||
34 | &self, | 34 | &self, |
35 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, | 36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, |
37 | ) -> Option<chalk_solve::Solution> { | 37 | ) -> Option<chalk_solve::Solution<ChalkIr>> { |
38 | let context = ChalkContext { db, krate: self.krate }; | 38 | let context = ChalkContext { db, krate: self.krate }; |
39 | debug!("solve goal: {:?}", goal); | 39 | debug!("solve goal: {:?}", goal); |
40 | let mut solver = match self.inner.lock() { | 40 | let mut solver = match self.inner.lock() { |
@@ -165,9 +165,9 @@ impl TypeWalk for ProjectionPredicate { | |||
165 | self.ty.walk(f); | 165 | self.ty.walk(f); |
166 | } | 166 | } |
167 | 167 | ||
168 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 168 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
169 | self.projection_ty.walk_mut(f); | 169 | self.projection_ty.walk_mut_binders(f, binders); |
170 | self.ty.walk_mut(f); | 170 | self.ty.walk_mut_binders(f, binders); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
@@ -188,6 +188,7 @@ pub(crate) fn trait_solve_query( | |||
188 | } | 188 | } |
189 | 189 | ||
190 | let canonical = goal.to_chalk(db).cast(); | 190 | let canonical = goal.to_chalk(db).cast(); |
191 | |||
191 | // We currently don't deal with universes (I think / hope they're not yet | 192 | // We currently don't deal with universes (I think / hope they're not yet |
192 | // relevant for our use cases?) | 193 | // relevant for our use cases?) |
193 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; | 194 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; |
@@ -195,7 +196,10 @@ pub(crate) fn trait_solve_query( | |||
195 | solution.map(|solution| solution_from_chalk(db, solution)) | 196 | solution.map(|solution| solution_from_chalk(db, solution)) |
196 | } | 197 | } |
197 | 198 | ||
198 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { | 199 | fn solution_from_chalk( |
200 | db: &impl HirDatabase, | ||
201 | solution: chalk_solve::Solution<ChalkIr>, | ||
202 | ) -> Solution { | ||
199 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { | 203 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { |
200 | let value = subst | 204 | let value = subst |
201 | .value | 205 | .value |
@@ -300,3 +304,14 @@ pub enum Impl { | |||
300 | /// Closure types implement the Fn traits synthetically. | 304 | /// Closure types implement the Fn traits synthetically. |
301 | ClosureFnTraitImpl(ClosureFnTraitImplData), | 305 | ClosureFnTraitImpl(ClosureFnTraitImplData), |
302 | } | 306 | } |
307 | |||
308 | /// An associated type value. Usually this comes from a `type` declaration | ||
309 | /// inside an impl block, but for built-in impls we have to synthesize it. | ||
310 | /// (We only need this because Chalk wants a unique ID for each of these.) | ||
311 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
312 | pub enum AssocTyValue { | ||
313 | /// A normal assoc type value from an impl block. | ||
314 | TypeAlias(TypeAlias), | ||
315 | /// The output type of the Fn trait implementation. | ||
316 | ClosureFnTraitImplOutput(ClosureFnTraitImplData), | ||
317 | } | ||
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 75351c17d..9bf93981a 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -7,22 +7,19 @@ use chalk_ir::{ | |||
7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, | 7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, |
8 | TypeKindId, TypeName, UniverseIndex, | 8 | TypeKindId, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_expand::name; | 12 | use hir_expand::name; |
13 | 13 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 14 | use ra_db::salsa::{InternId, InternKey}; |
15 | 15 | ||
16 | use super::{Canonical, ChalkContext, Impl, Obligation}; | 16 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
17 | use crate::{ | 17 | use crate::{ |
18 | db::HirDatabase, | 18 | db::HirDatabase, |
19 | generics::{GenericDef, HasGenericParams}, | 19 | generics::{GenericDef, HasGenericParams}, |
20 | ty::display::HirDisplay, | 20 | ty::display::HirDisplay, |
21 | ty::{ | 21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, |
22 | ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 22 | Crate, HasBody, ImplBlock, Trait, TypeAlias, |
23 | TypeWalk, | ||
24 | }, | ||
25 | AssocItem, Crate, HasBody, ImplBlock, Trait, TypeAlias, | ||
26 | }; | 23 | }; |
27 | 24 | ||
28 | /// This represents a trait whose name we could not resolve. | 25 | /// This represents a trait whose name we could not resolve. |
@@ -59,29 +56,36 @@ impl ToChalk for Ty { | |||
59 | } | 56 | } |
60 | }; | 57 | }; |
61 | let parameters = apply_ty.parameters.to_chalk(db); | 58 | let parameters = apply_ty.parameters.to_chalk(db); |
62 | chalk_ir::ApplicationTy { name, parameters }.cast() | 59 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
63 | } | 60 | } |
64 | Ty::Projection(proj_ty) => { | 61 | Ty::Projection(proj_ty) => { |
65 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 62 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); |
66 | let parameters = proj_ty.parameters.to_chalk(db); | 63 | let parameters = proj_ty.parameters.to_chalk(db); |
67 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() | 64 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() |
68 | } | 65 | } |
69 | Ty::Param { idx, .. } => { | 66 | Ty::Param { idx, .. } => { |
70 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() | 67 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() |
71 | } | 68 | } |
72 | Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), | 69 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), |
73 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 70 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
74 | // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed | 71 | Ty::Dyn(predicates) => { |
75 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | 72 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); |
73 | chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() | ||
74 | } | ||
75 | Ty::Opaque(predicates) => { | ||
76 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | ||
77 | chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() | ||
78 | } | ||
79 | Ty::Unknown => { | ||
76 | let parameters = Vec::new(); | 80 | let parameters = Vec::new(); |
77 | let name = TypeName::Error; | 81 | let name = TypeName::Error; |
78 | chalk_ir::ApplicationTy { name, parameters }.cast() | 82 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
79 | } | 83 | } |
80 | } | 84 | } |
81 | } | 85 | } |
82 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | 86 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { |
83 | match chalk { | 87 | match chalk.data().clone() { |
84 | chalk_ir::Ty::Apply(apply_ty) => { | 88 | chalk_ir::TyData::Apply(apply_ty) => { |
85 | // FIXME this is kind of hacky due to the fact that | 89 | // FIXME this is kind of hacky due to the fact that |
86 | // TypeName::Placeholder is a Ty::Param on our side | 90 | // TypeName::Placeholder is a Ty::Param on our side |
87 | match apply_ty.name { | 91 | match apply_ty.name { |
@@ -104,21 +108,21 @@ impl ToChalk for Ty { | |||
104 | } | 108 | } |
105 | } | 109 | } |
106 | } | 110 | } |
107 | chalk_ir::Ty::Projection(proj) => { | 111 | chalk_ir::TyData::Projection(proj) => { |
108 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 112 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
109 | let parameters = from_chalk(db, proj.parameters); | 113 | let parameters = from_chalk(db, proj.parameters); |
110 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 114 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
111 | } | 115 | } |
112 | chalk_ir::Ty::ForAll(_) => unimplemented!(), | 116 | chalk_ir::TyData::ForAll(_) => unimplemented!(), |
113 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), | 117 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
114 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, | 118 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
115 | chalk_ir::Ty::Dyn(where_clauses) => { | 119 | chalk_ir::TyData::Dyn(where_clauses) => { |
116 | assert_eq!(where_clauses.binders.len(), 1); | 120 | assert_eq!(where_clauses.binders.len(), 1); |
117 | let predicates = | 121 | let predicates = |
118 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 122 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
119 | Ty::Dyn(predicates) | 123 | Ty::Dyn(predicates) |
120 | } | 124 | } |
121 | chalk_ir::Ty::Opaque(where_clauses) => { | 125 | chalk_ir::TyData::Opaque(where_clauses) => { |
122 | assert_eq!(where_clauses.binders.len(), 1); | 126 | assert_eq!(where_clauses.binders.len(), 1); |
123 | let predicates = | 127 | let predicates = |
124 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 128 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
@@ -191,11 +195,11 @@ impl ToChalk for Impl { | |||
191 | type Chalk = chalk_ir::ImplId; | 195 | type Chalk = chalk_ir::ImplId; |
192 | 196 | ||
193 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { | 197 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { |
194 | db.intern_impl(self).into() | 198 | db.intern_chalk_impl(self).into() |
195 | } | 199 | } |
196 | 200 | ||
197 | fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { | 201 | fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { |
198 | db.lookup_intern_impl(impl_id.into()) | 202 | db.lookup_intern_chalk_impl(impl_id.into()) |
199 | } | 203 | } |
200 | } | 204 | } |
201 | 205 | ||
@@ -211,6 +215,21 @@ impl ToChalk for TypeAlias { | |||
211 | } | 215 | } |
212 | } | 216 | } |
213 | 217 | ||
218 | impl ToChalk for AssocTyValue { | ||
219 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | ||
220 | |||
221 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | ||
222 | db.intern_assoc_ty_value(self).into() | ||
223 | } | ||
224 | |||
225 | fn from_chalk( | ||
226 | db: &impl HirDatabase, | ||
227 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
228 | ) -> AssocTyValue { | ||
229 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
230 | } | ||
231 | } | ||
232 | |||
214 | impl ToChalk for GenericPredicate { | 233 | impl ToChalk for GenericPredicate { |
215 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | 234 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; |
216 | 235 | ||
@@ -399,20 +418,20 @@ fn convert_where_clauses( | |||
399 | result | 418 | result |
400 | } | 419 | } |
401 | 420 | ||
402 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 421 | impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> |
403 | where | 422 | where |
404 | DB: HirDatabase, | 423 | DB: HirDatabase, |
405 | { | 424 | { |
406 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> { | 425 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { |
407 | self.db.associated_ty_data(id) | 426 | self.db.associated_ty_data(id) |
408 | } | 427 | } |
409 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 428 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { |
410 | self.db.trait_datum(self.krate, trait_id) | 429 | self.db.trait_datum(self.krate, trait_id) |
411 | } | 430 | } |
412 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { | 431 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { |
413 | self.db.struct_datum(self.krate, struct_id) | 432 | self.db.struct_datum(self.krate, struct_id) |
414 | } | 433 | } |
415 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { | 434 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> { |
416 | self.db.impl_datum(self.krate, impl_id) | 435 | self.db.impl_datum(self.krate, impl_id) |
417 | } | 436 | } |
418 | fn impls_for_trait( | 437 | fn impls_for_trait( |
@@ -462,13 +481,11 @@ where | |||
462 | fn type_name(&self, _id: TypeKindId) -> Identifier { | 481 | fn type_name(&self, _id: TypeKindId) -> Identifier { |
463 | unimplemented!() | 482 | unimplemented!() |
464 | } | 483 | } |
465 | fn split_projection<'p>( | 484 | fn associated_ty_value( |
466 | &self, | 485 | &self, |
467 | projection: &'p chalk_ir::ProjectionTy<ChalkIr>, | 486 | id: chalk_rust_ir::AssociatedTyValueId, |
468 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) { | 487 | ) -> Arc<AssociatedTyValue<ChalkIr>> { |
469 | debug!("split_projection {:?}", projection); | 488 | self.db.associated_ty_value(self.krate, id) |
470 | // we don't support GATs, so I think this should always be correct currently | ||
471 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) | ||
472 | } | 489 | } |
473 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | 490 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { |
474 | vec![] | 491 | vec![] |
@@ -485,7 +502,7 @@ where | |||
485 | pub(crate) fn associated_ty_data_query( | 502 | pub(crate) fn associated_ty_data_query( |
486 | db: &impl HirDatabase, | 503 | db: &impl HirDatabase, |
487 | id: TypeId, | 504 | id: TypeId, |
488 | ) -> Arc<AssociatedTyDatum> { | 505 | ) -> Arc<AssociatedTyDatum<ChalkIr>> { |
489 | debug!("associated_ty_data {:?}", id); | 506 | debug!("associated_ty_data {:?}", id); |
490 | let type_alias: TypeAlias = from_chalk(db, id); | 507 | let type_alias: TypeAlias = from_chalk(db, id); |
491 | let trait_ = match type_alias.container(db) { | 508 | let trait_ = match type_alias.container(db) { |
@@ -493,19 +510,16 @@ pub(crate) fn associated_ty_data_query( | |||
493 | _ => panic!("associated type not in trait"), | 510 | _ => panic!("associated type not in trait"), |
494 | }; | 511 | }; |
495 | let generic_params = type_alias.generic_params(db); | 512 | let generic_params = type_alias.generic_params(db); |
496 | let parameter_kinds = generic_params | 513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { |
497 | .params_including_parent() | 514 | // FIXME add bounds and where clauses |
498 | .into_iter() | 515 | bounds: vec![], |
499 | .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string()))) | 516 | where_clauses: vec![], |
500 | .collect(); | 517 | }; |
501 | let datum = AssociatedTyDatum { | 518 | let datum = AssociatedTyDatum { |
502 | trait_id: trait_.to_chalk(db), | 519 | trait_id: trait_.to_chalk(db), |
503 | id, | 520 | id, |
504 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), | 521 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), |
505 | parameter_kinds, | 522 | binders: make_binders(bound_data, generic_params.count_params_including_parent()), |
506 | // FIXME add bounds and where clauses | ||
507 | bounds: vec![], | ||
508 | where_clauses: vec![], | ||
509 | }; | 523 | }; |
510 | Arc::new(datum) | 524 | Arc::new(datum) |
511 | } | 525 | } |
@@ -514,17 +528,10 @@ pub(crate) fn trait_datum_query( | |||
514 | db: &impl HirDatabase, | 528 | db: &impl HirDatabase, |
515 | krate: Crate, | 529 | krate: Crate, |
516 | trait_id: chalk_ir::TraitId, | 530 | trait_id: chalk_ir::TraitId, |
517 | ) -> Arc<TraitDatum> { | 531 | ) -> Arc<TraitDatum<ChalkIr>> { |
518 | debug!("trait_datum {:?}", trait_id); | 532 | debug!("trait_datum {:?}", trait_id); |
519 | if trait_id == UNKNOWN_TRAIT { | 533 | if trait_id == UNKNOWN_TRAIT { |
520 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | 534 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; |
521 | trait_ref: chalk_ir::TraitRef { | ||
522 | trait_id: UNKNOWN_TRAIT, | ||
523 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | ||
524 | }, | ||
525 | associated_ty_ids: Vec::new(), | ||
526 | where_clauses: Vec::new(), | ||
527 | }; | ||
528 | 535 | ||
529 | let flags = chalk_rust_ir::TraitFlags { | 536 | let flags = chalk_rust_ir::TraitFlags { |
530 | auto: false, | 537 | auto: false, |
@@ -532,18 +539,24 @@ pub(crate) fn trait_datum_query( | |||
532 | upstream: true, | 539 | upstream: true, |
533 | fundamental: false, | 540 | fundamental: false, |
534 | non_enumerable: true, | 541 | non_enumerable: true, |
542 | coinductive: false, | ||
535 | }; | 543 | }; |
536 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1), flags }); | 544 | return Arc::new(TraitDatum { |
545 | id: trait_id, | ||
546 | binders: make_binders(trait_datum_bound, 1), | ||
547 | flags, | ||
548 | associated_ty_ids: vec![], | ||
549 | }); | ||
537 | } | 550 | } |
538 | let trait_: Trait = from_chalk(db, trait_id); | 551 | let trait_: Trait = from_chalk(db, trait_id); |
539 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | 552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); |
540 | let generic_params = trait_.generic_params(db); | 553 | let generic_params = trait_.generic_params(db); |
541 | let bound_vars = Substs::bound_vars(&generic_params); | 554 | let bound_vars = Substs::bound_vars(&generic_params); |
542 | let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db); | ||
543 | let flags = chalk_rust_ir::TraitFlags { | 555 | let flags = chalk_rust_ir::TraitFlags { |
544 | auto: trait_.is_auto(db), | 556 | auto: trait_.is_auto(db), |
545 | upstream: trait_.module(db).krate() != krate, | 557 | upstream: trait_.module(db).krate() != krate, |
546 | non_enumerable: true, | 558 | non_enumerable: true, |
559 | coinductive: false, // only relevant for Chalk testing | ||
547 | // FIXME set these flags correctly | 560 | // FIXME set these flags correctly |
548 | marker: false, | 561 | marker: false, |
549 | fundamental: false, | 562 | fundamental: false, |
@@ -558,10 +571,13 @@ pub(crate) fn trait_datum_query( | |||
558 | }) | 571 | }) |
559 | .map(|type_alias| type_alias.to_chalk(db)) | 572 | .map(|type_alias| type_alias.to_chalk(db)) |
560 | .collect(); | 573 | .collect(); |
561 | let trait_datum_bound = | 574 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
562 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, associated_ty_ids }; | 575 | let trait_datum = TraitDatum { |
563 | let trait_datum = | 576 | id: trait_id, |
564 | TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()), flags }; | 577 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
578 | flags, | ||
579 | associated_ty_ids, | ||
580 | }; | ||
565 | Arc::new(trait_datum) | 581 | Arc::new(trait_datum) |
566 | } | 582 | } |
567 | 583 | ||
@@ -569,7 +585,7 @@ pub(crate) fn struct_datum_query( | |||
569 | db: &impl HirDatabase, | 585 | db: &impl HirDatabase, |
570 | krate: Crate, | 586 | krate: Crate, |
571 | struct_id: chalk_ir::StructId, | 587 | struct_id: chalk_ir::StructId, |
572 | ) -> Arc<StructDatum> { | 588 | ) -> Arc<StructDatum<ChalkIr>> { |
573 | debug!("struct_datum {:?}", struct_id); | 589 | debug!("struct_datum {:?}", struct_id); |
574 | let type_ctor: TypeCtor = from_chalk(db, struct_id); | 590 | let type_ctor: TypeCtor = from_chalk(db, struct_id); |
575 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 591 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
@@ -588,17 +604,12 @@ pub(crate) fn struct_datum_query( | |||
588 | // FIXME set fundamental flag correctly | 604 | // FIXME set fundamental flag correctly |
589 | fundamental: false, | 605 | fundamental: false, |
590 | }; | 606 | }; |
591 | let self_ty = chalk_ir::ApplicationTy { | ||
592 | name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()), | ||
593 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | ||
594 | }; | ||
595 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { | 607 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { |
596 | self_ty, | ||
597 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 608 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
598 | where_clauses, | 609 | where_clauses, |
599 | flags, | ||
600 | }; | 610 | }; |
601 | let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) }; | 611 | let struct_datum = |
612 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
602 | Arc::new(struct_datum) | 613 | Arc::new(struct_datum) |
603 | } | 614 | } |
604 | 615 | ||
@@ -606,16 +617,15 @@ pub(crate) fn impl_datum_query( | |||
606 | db: &impl HirDatabase, | 617 | db: &impl HirDatabase, |
607 | krate: Crate, | 618 | krate: Crate, |
608 | impl_id: ImplId, | 619 | impl_id: ImplId, |
609 | ) -> Arc<ImplDatum> { | 620 | ) -> Arc<ImplDatum<ChalkIr>> { |
610 | let _p = ra_prof::profile("impl_datum"); | 621 | let _p = ra_prof::profile("impl_datum"); |
611 | debug!("impl_datum {:?}", impl_id); | 622 | debug!("impl_datum {:?}", impl_id); |
612 | let impl_: Impl = from_chalk(db, impl_id); | 623 | let impl_: Impl = from_chalk(db, impl_id); |
613 | match impl_ { | 624 | match impl_ { |
614 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 625 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
615 | Impl::ClosureFnTraitImpl(data) => { | 626 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
616 | closure_fn_trait_impl_datum(db, krate, impl_id, data).unwrap_or_else(invalid_impl_datum) | ||
617 | } | ||
618 | } | 627 | } |
628 | .unwrap_or_else(invalid_impl_datum) | ||
619 | } | 629 | } |
620 | 630 | ||
621 | fn impl_block_datum( | 631 | fn impl_block_datum( |
@@ -623,14 +633,12 @@ fn impl_block_datum( | |||
623 | krate: Crate, | 633 | krate: Crate, |
624 | impl_id: ImplId, | 634 | impl_id: ImplId, |
625 | impl_block: ImplBlock, | 635 | impl_block: ImplBlock, |
626 | ) -> Arc<ImplDatum> { | 636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
627 | let generic_params = impl_block.generic_params(db); | 637 | let generic_params = impl_block.generic_params(db); |
628 | let bound_vars = Substs::bound_vars(&generic_params); | 638 | let bound_vars = Substs::bound_vars(&generic_params); |
629 | let trait_ref = impl_block | 639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); |
630 | .target_trait_ref(db) | 640 | let trait_ = trait_ref.trait_; |
631 | .expect("FIXME handle unresolved impl block trait ref") | 641 | let impl_type = if impl_block.krate(db) == krate { |
632 | .subst(&bound_vars); | ||
633 | let impl_type = if impl_block.module().krate() == krate { | ||
634 | chalk_rust_ir::ImplType::Local | 642 | chalk_rust_ir::ImplType::Local |
635 | } else { | 643 | } else { |
636 | chalk_rust_ir::ImplType::External | 644 | chalk_rust_ir::ImplType::External |
@@ -644,28 +652,7 @@ fn impl_block_datum( | |||
644 | trait_ref.display(db), | 652 | trait_ref.display(db), |
645 | where_clauses | 653 | where_clauses |
646 | ); | 654 | ); |
647 | let trait_ = trait_ref.trait_; | ||
648 | let trait_ref = trait_ref.to_chalk(db); | 655 | let trait_ref = trait_ref.to_chalk(db); |
649 | let associated_ty_values = impl_block | ||
650 | .items(db) | ||
651 | .into_iter() | ||
652 | .filter_map(|item| match item { | ||
653 | AssocItem::TypeAlias(t) => Some(t), | ||
654 | _ => None, | ||
655 | }) | ||
656 | .filter_map(|t| { | ||
657 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; | ||
658 | let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars); | ||
659 | Some(chalk_rust_ir::AssociatedTyValue { | ||
660 | impl_id, | ||
661 | associated_ty_id: assoc_ty.to_chalk(db), | ||
662 | value: chalk_ir::Binders { | ||
663 | value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }, | ||
664 | binders: vec![], // we don't support GATs yet | ||
665 | }, | ||
666 | }) | ||
667 | }) | ||
668 | .collect(); | ||
669 | 656 | ||
670 | let polarity = if negative { | 657 | let polarity = if negative { |
671 | chalk_rust_ir::Polarity::Negative | 658 | chalk_rust_ir::Polarity::Negative |
@@ -673,31 +660,41 @@ fn impl_block_datum( | |||
673 | chalk_rust_ir::Polarity::Positive | 660 | chalk_rust_ir::Polarity::Positive |
674 | }; | 661 | }; |
675 | 662 | ||
676 | let impl_datum_bound = | 663 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; |
677 | chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses, associated_ty_values }; | 664 | let associated_ty_value_ids = impl_block |
665 | .items(db) | ||
666 | .into_iter() | ||
667 | .filter_map(|item| match item { | ||
668 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
669 | _ => None, | ||
670 | }) | ||
671 | .filter(|type_alias| { | ||
672 | // don't include associated types that don't exist in the trait | ||
673 | trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() | ||
674 | }) | ||
675 | .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) | ||
676 | .collect(); | ||
678 | debug!("impl_datum: {:?}", impl_datum_bound); | 677 | debug!("impl_datum: {:?}", impl_datum_bound); |
679 | let impl_datum = ImplDatum { | 678 | let impl_datum = ImplDatum { |
680 | binders: make_binders(impl_datum_bound, bound_vars.len()), | 679 | binders: make_binders(impl_datum_bound, bound_vars.len()), |
681 | impl_type, | 680 | impl_type, |
682 | polarity, | 681 | polarity, |
682 | associated_ty_value_ids, | ||
683 | }; | 683 | }; |
684 | Arc::new(impl_datum) | 684 | Some(Arc::new(impl_datum)) |
685 | } | 685 | } |
686 | 686 | ||
687 | fn invalid_impl_datum() -> Arc<ImplDatum> { | 687 | fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { |
688 | let trait_ref = chalk_ir::TraitRef { | 688 | let trait_ref = chalk_ir::TraitRef { |
689 | trait_id: UNKNOWN_TRAIT, | 689 | trait_id: UNKNOWN_TRAIT, |
690 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | 690 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], |
691 | }; | ||
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | ||
693 | trait_ref, | ||
694 | where_clauses: Vec::new(), | ||
695 | associated_ty_values: Vec::new(), | ||
696 | }; | 691 | }; |
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
697 | let impl_datum = ImplDatum { | 693 | let impl_datum = ImplDatum { |
698 | binders: make_binders(impl_datum_bound, 1), | 694 | binders: make_binders(impl_datum_bound, 1), |
699 | impl_type: chalk_rust_ir::ImplType::External, | 695 | impl_type: chalk_rust_ir::ImplType::External, |
700 | polarity: chalk_rust_ir::Polarity::Positive, | 696 | polarity: chalk_rust_ir::Polarity::Positive, |
697 | associated_ty_value_ids: Vec::new(), | ||
701 | }; | 698 | }; |
702 | Arc::new(impl_datum) | 699 | Arc::new(impl_datum) |
703 | } | 700 | } |
@@ -705,15 +702,19 @@ fn invalid_impl_datum() -> Arc<ImplDatum> { | |||
705 | fn closure_fn_trait_impl_datum( | 702 | fn closure_fn_trait_impl_datum( |
706 | db: &impl HirDatabase, | 703 | db: &impl HirDatabase, |
707 | krate: Crate, | 704 | krate: Crate, |
708 | impl_id: ImplId, | ||
709 | data: super::ClosureFnTraitImplData, | 705 | data: super::ClosureFnTraitImplData, |
710 | ) -> Option<Arc<ImplDatum>> { | 706 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
711 | // for some closure |X, Y| -> Z: | 707 | // for some closure |X, Y| -> Z: |
712 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | 708 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } |
713 | 709 | ||
714 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
715 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | 710 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait |
716 | 711 | ||
712 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
713 | // and don't want to return a valid value only to find out later that FnOnce | ||
714 | // is broken | ||
715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | ||
717 | |||
717 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 718 | let num_args: u16 = match &data.def.body(db)[data.expr] { |
718 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
719 | _ => { | 720 | _ => { |
@@ -726,7 +727,6 @@ fn closure_fn_trait_impl_datum( | |||
726 | TypeCtor::Tuple { cardinality: num_args }, | 727 | TypeCtor::Tuple { cardinality: num_args }, |
727 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | 728 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), |
728 | ); | 729 | ); |
729 | let output_ty = Ty::Bound(num_args.into()); | ||
730 | let sig_ty = Ty::apply( | 730 | let sig_ty = Ty::apply( |
731 | TypeCtor::FnPtr { num_args }, | 731 | TypeCtor::FnPtr { num_args }, |
732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | 732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), |
@@ -739,32 +739,99 @@ fn closure_fn_trait_impl_datum( | |||
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | 739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | 742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); |
743 | |||
744 | let output_ty_value = chalk_rust_ir::AssociatedTyValue { | ||
745 | associated_ty_id: output_ty_id.to_chalk(db), | ||
746 | impl_id, | ||
747 | value: make_binders( | ||
748 | chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }, | ||
749 | 0, | ||
750 | ), | ||
751 | }; | ||
752 | 743 | ||
753 | let impl_type = chalk_rust_ir::ImplType::External; | 744 | let impl_type = chalk_rust_ir::ImplType::External; |
754 | 745 | ||
755 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 746 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
756 | trait_ref: trait_ref.to_chalk(db), | 747 | trait_ref: trait_ref.to_chalk(db), |
757 | where_clauses: Vec::new(), | 748 | where_clauses: Vec::new(), |
758 | associated_ty_values: vec![output_ty_value], | ||
759 | }; | 749 | }; |
760 | let impl_datum = ImplDatum { | 750 | let impl_datum = ImplDatum { |
761 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | 751 | binders: make_binders(impl_datum_bound, num_args as usize + 1), |
762 | impl_type, | 752 | impl_type, |
763 | polarity: chalk_rust_ir::Polarity::Positive, | 753 | polarity: chalk_rust_ir::Polarity::Positive, |
754 | associated_ty_value_ids: vec![output_ty_id], | ||
764 | }; | 755 | }; |
765 | Some(Arc::new(impl_datum)) | 756 | Some(Arc::new(impl_datum)) |
766 | } | 757 | } |
767 | 758 | ||
759 | pub(crate) fn associated_ty_value_query( | ||
760 | db: &impl HirDatabase, | ||
761 | krate: Crate, | ||
762 | id: chalk_rust_ir::AssociatedTyValueId, | ||
763 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { | ||
764 | let data: AssocTyValue = from_chalk(db, id); | ||
765 | match data { | ||
766 | AssocTyValue::TypeAlias(type_alias) => { | ||
767 | type_alias_associated_ty_value(db, krate, type_alias) | ||
768 | } | ||
769 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
770 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
775 | fn type_alias_associated_ty_value( | ||
776 | db: &impl HirDatabase, | ||
777 | _krate: Crate, | ||
778 | type_alias: TypeAlias, | ||
779 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
780 | let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); | ||
781 | let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); | ||
782 | let trait_ = impl_block | ||
783 | .target_trait_ref(db) | ||
784 | .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
785 | .trait_; | ||
786 | let assoc_ty = trait_ | ||
787 | .associated_type_by_name(db, &type_alias.name(db)) | ||
788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | ||
789 | let generic_params = impl_block.generic_params(db); | ||
790 | let bound_vars = Substs::bound_vars(&generic_params); | ||
791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | ||
792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
793 | let value = chalk_rust_ir::AssociatedTyValue { | ||
794 | impl_id, | ||
795 | associated_ty_id: assoc_ty.to_chalk(db), | ||
796 | value: make_binders(value_bound, bound_vars.len()), | ||
797 | }; | ||
798 | Arc::new(value) | ||
799 | } | ||
800 | |||
801 | fn closure_fn_trait_output_assoc_ty_value( | ||
802 | db: &impl HirDatabase, | ||
803 | krate: Crate, | ||
804 | data: super::ClosureFnTraitImplData, | ||
805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
807 | |||
808 | let num_args: u16 = match &data.def.body(db)[data.expr] { | ||
809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
810 | _ => { | ||
811 | log::warn!("closure for closure type {:?} not found", data); | ||
812 | 0 | ||
813 | } | ||
814 | }; | ||
815 | |||
816 | let output_ty = Ty::Bound(num_args.into()); | ||
817 | |||
818 | let fn_once_trait = | ||
819 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
820 | |||
821 | let output_ty_id = fn_once_trait | ||
822 | .associated_type_by_name(db, &name::OUTPUT_TYPE) | ||
823 | .expect("assoc ty value should not exist"); | ||
824 | |||
825 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
826 | |||
827 | let value = chalk_rust_ir::AssociatedTyValue { | ||
828 | associated_ty_id: output_ty_id.to_chalk(db), | ||
829 | impl_id, | ||
830 | value: make_binders(value_bound, num_args as usize + 1), | ||
831 | }; | ||
832 | Arc::new(value) | ||
833 | } | ||
834 | |||
768 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { |
769 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | 836 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; |
770 | match target { | 837 | match target { |
@@ -803,3 +870,15 @@ impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | |||
803 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 870 | chalk_ir::ImplId(id_to_chalk(impl_id)) |
804 | } | 871 | } |
805 | } | 872 | } |
873 | |||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | ||
875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | ||
876 | id_from_chalk(id.0) | ||
877 | } | ||
878 | } | ||
879 | |||
880 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | ||
881 | fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { | ||
882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | ||
883 | } | ||
884 | } | ||