diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 62 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 42 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/traits.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 50 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 53 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 160 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 179 |
17 files changed, 530 insertions, 123 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 55e1793c5..0c4a80bfa 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -703,6 +703,10 @@ impl Trait { | |||
703 | TraitRef::for_trait(db, self) | 703 | TraitRef::for_trait(db, self) |
704 | } | 704 | } |
705 | 705 | ||
706 | pub fn is_auto(self, db: &impl DefDatabase) -> bool { | ||
707 | self.trait_data(db).is_auto() | ||
708 | } | ||
709 | |||
706 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | 710 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { |
707 | let r = self.module(db).resolver(db); | 711 | let r = self.module(db).resolver(db); |
708 | // add generic params, if present | 712 | // add generic params, if present |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 8aaf0375a..8f98ca3a5 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | DefWithBody, Trait, | 11 | DefWithBody, Trait, |
12 | ids, | 12 | ids, |
13 | nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap}, | 13 | nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap}, |
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor}, | 14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor, GenericPredicate}, |
15 | adt::{StructData, EnumData}, | 15 | adt::{StructData, EnumData}, |
16 | impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock}, | 16 | impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock}, |
17 | generics::{GenericParams, GenericDef}, | 17 | generics::{GenericParams, GenericDef}, |
@@ -138,6 +138,9 @@ pub trait HirDatabase: DefDatabase { | |||
138 | #[salsa::invoke(crate::ty::callable_item_sig)] | 138 | #[salsa::invoke(crate::ty::callable_item_sig)] |
139 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 139 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; |
140 | 140 | ||
141 | #[salsa::invoke(crate::ty::generic_predicates)] | ||
142 | fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; | ||
143 | |||
141 | #[salsa::invoke(crate::expr::body_with_source_map_query)] | 144 | #[salsa::invoke(crate::expr::body_with_source_map_query)] |
142 | fn body_with_source_map( | 145 | fn body_with_source_map( |
143 | &self, | 146 | &self, |
@@ -161,6 +164,13 @@ pub trait HirDatabase: DefDatabase { | |||
161 | #[salsa::invoke(crate::ty::traits::solver)] | 164 | #[salsa::invoke(crate::ty::traits::solver)] |
162 | #[salsa::volatile] | 165 | #[salsa::volatile] |
163 | fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; | 166 | fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; |
167 | |||
168 | #[salsa::invoke(crate::ty::traits::implements)] | ||
169 | fn implements( | ||
170 | &self, | ||
171 | krate: Crate, | ||
172 | goal: crate::ty::Canonical<crate::ty::TraitRef>, | ||
173 | ) -> Option<crate::ty::traits::Solution>; | ||
164 | } | 174 | } |
165 | 175 | ||
166 | #[test] | 176 | #[test] |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 480eaf171..a2b5db1a1 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, | 13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, |
14 | name::AsName, | 14 | name::AsName, |
15 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeRef}, |
16 | }; | 16 | }; |
@@ -828,7 +828,8 @@ where | |||
828 | .ast_id(e) | 828 | .ast_id(e) |
829 | .with_file_id(self.current_file_id); | 829 | .with_file_id(self.current_file_id); |
830 | 830 | ||
831 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) { | 831 | if let Some(def) = self.resolver.resolve_macro_call(path) { |
832 | let call_id = MacroCallLoc { def, ast_id }.id(self.db); | ||
832 | if let Some(tt) = self.db.macro_expand(call_id).ok() { | 833 | if let Some(tt) = self.db.macro_expand(call_id).ok() { |
833 | if let Some(expr) = mbe::token_tree_to_expr(&tt).ok() { | 834 | if let Some(expr) = mbe::token_tree_to_expr(&tt).ok() { |
834 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); | 835 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 2e52c5871..c29b96f50 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -8,7 +8,7 @@ use std::sync::Arc; | |||
8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, | 11 | db::{ HirDatabase, DefDatabase}, |
12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef | 12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef |
13 | }; | 13 | }; |
14 | 14 | ||
@@ -32,8 +32,8 @@ pub struct GenericParams { | |||
32 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | 32 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. |
33 | #[derive(Clone, PartialEq, Eq, Debug)] | 33 | #[derive(Clone, PartialEq, Eq, Debug)] |
34 | pub struct WherePredicate { | 34 | pub struct WherePredicate { |
35 | type_ref: TypeRef, | 35 | pub(crate) type_ref: TypeRef, |
36 | trait_ref: Path, | 36 | pub(crate) trait_ref: Path, |
37 | } | 37 | } |
38 | 38 | ||
39 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | 39 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) |
@@ -90,8 +90,17 @@ impl GenericParams { | |||
90 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { | 90 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { |
91 | for (idx, type_param) in params.type_params().enumerate() { | 91 | for (idx, type_param) in params.type_params().enumerate() { |
92 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); | 92 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); |
93 | let param = GenericParam { idx: idx as u32 + start, name }; | 93 | let param = GenericParam { idx: idx as u32 + start, name: name.clone() }; |
94 | self.params.push(param); | 94 | self.params.push(param); |
95 | |||
96 | let type_ref = TypeRef::Path(name.into()); | ||
97 | for bound in type_param | ||
98 | .type_bound_list() | ||
99 | .iter() | ||
100 | .flat_map(|type_bound_list| type_bound_list.bounds()) | ||
101 | { | ||
102 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
103 | } | ||
95 | } | 104 | } |
96 | } | 105 | } |
97 | 106 | ||
@@ -101,26 +110,28 @@ impl GenericParams { | |||
101 | Some(type_ref) => type_ref, | 110 | Some(type_ref) => type_ref, |
102 | None => continue, | 111 | None => continue, |
103 | }; | 112 | }; |
113 | let type_ref = TypeRef::from_ast(type_ref); | ||
104 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | 114 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { |
105 | let path = bound | 115 | self.add_where_predicate_from_bound(bound, type_ref.clone()); |
106 | .type_ref() | ||
107 | .and_then(|tr| match tr.kind() { | ||
108 | ast::TypeRefKind::PathType(path) => path.path(), | ||
109 | _ => None, | ||
110 | }) | ||
111 | .and_then(Path::from_ast); | ||
112 | let path = match path { | ||
113 | Some(p) => p, | ||
114 | None => continue, | ||
115 | }; | ||
116 | self.where_predicates.push(WherePredicate { | ||
117 | type_ref: TypeRef::from_ast(type_ref), | ||
118 | trait_ref: path, | ||
119 | }); | ||
120 | } | 116 | } |
121 | } | 117 | } |
122 | } | 118 | } |
123 | 119 | ||
120 | fn add_where_predicate_from_bound(&mut self, bound: &ast::TypeBound, type_ref: TypeRef) { | ||
121 | let path = bound | ||
122 | .type_ref() | ||
123 | .and_then(|tr| match tr.kind() { | ||
124 | ast::TypeRefKind::PathType(path) => path.path(), | ||
125 | _ => None, | ||
126 | }) | ||
127 | .and_then(Path::from_ast); | ||
128 | let path = match path { | ||
129 | Some(p) => p, | ||
130 | None => return, | ||
131 | }; | ||
132 | self.where_predicates.push(WherePredicate { type_ref, trait_ref: path }); | ||
133 | } | ||
134 | |||
124 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 135 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
125 | self.params.iter().find(|p| &p.name == name) | 136 | self.params.iter().find(|p| &p.name == name) |
126 | } | 137 | } |
@@ -148,6 +159,19 @@ impl GenericParams { | |||
148 | } | 159 | } |
149 | } | 160 | } |
150 | 161 | ||
162 | impl GenericDef { | ||
163 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> crate::Resolver { | ||
164 | match self { | ||
165 | GenericDef::Function(inner) => inner.resolver(db), | ||
166 | GenericDef::Struct(inner) => inner.resolver(db), | ||
167 | GenericDef::Enum(inner) => inner.resolver(db), | ||
168 | GenericDef::Trait(inner) => inner.resolver(db), | ||
169 | GenericDef::TypeAlias(inner) => inner.resolver(db), | ||
170 | GenericDef::ImplBlock(inner) => inner.resolver(db), | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
151 | impl From<Container> for GenericDef { | 175 | impl From<Container> for GenericDef { |
152 | fn from(c: Container) -> Self { | 176 | fn from(c: Container) -> Self { |
153 | match c { | 177 | match c { |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index a8a466e43..b7dd775f1 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -93,6 +93,10 @@ impl ImplBlock { | |||
93 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() | 93 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() |
94 | } | 94 | } |
95 | 95 | ||
96 | pub fn is_negative(&self, db: &impl DefDatabase) -> bool { | ||
97 | db.impls_in_module(self.module).impls[self.impl_id].negative | ||
98 | } | ||
99 | |||
96 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | 100 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { |
97 | let r = self.module().resolver(db); | 101 | let r = self.module().resolver(db); |
98 | // add generic params, if present | 102 | // add generic params, if present |
@@ -108,6 +112,7 @@ pub struct ImplData { | |||
108 | target_trait: Option<TypeRef>, | 112 | target_trait: Option<TypeRef>, |
109 | target_type: TypeRef, | 113 | target_type: TypeRef, |
110 | items: Vec<ImplItem>, | 114 | items: Vec<ImplItem>, |
115 | negative: bool, | ||
111 | } | 116 | } |
112 | 117 | ||
113 | impl ImplData { | 118 | impl ImplData { |
@@ -120,6 +125,7 @@ impl ImplData { | |||
120 | let target_trait = node.target_trait().map(TypeRef::from_ast); | 125 | let target_trait = node.target_trait().map(TypeRef::from_ast); |
121 | let target_type = TypeRef::from_ast_opt(node.target_type()); | 126 | let target_type = TypeRef::from_ast_opt(node.target_type()); |
122 | let ctx = LocationCtx::new(db, module, file_id); | 127 | let ctx = LocationCtx::new(db, module, file_id); |
128 | let negative = node.is_negative(); | ||
123 | let items = if let Some(item_list) = node.item_list() { | 129 | let items = if let Some(item_list) = node.item_list() { |
124 | item_list | 130 | item_list |
125 | .impl_items() | 131 | .impl_items() |
@@ -132,7 +138,7 @@ impl ImplData { | |||
132 | } else { | 138 | } else { |
133 | Vec::new() | 139 | Vec::new() |
134 | }; | 140 | }; |
135 | ImplData { target_trait, target_type, items } | 141 | ImplData { target_trait, target_type, items, negative } |
136 | } | 142 | } |
137 | 143 | ||
138 | pub fn target_trait(&self) -> Option<&TypeRef> { | 144 | pub fn target_trait(&self) -> Option<&TypeRef> { |
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 5b6400042..2d831f0d8 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -9,4 +9,5 @@ test_utils::marks!( | |||
9 | glob_across_crates | 9 | glob_across_crates |
10 | std_prelude | 10 | std_prelude |
11 | match_ergonomics_ref | 11 | match_ergonomics_ref |
12 | trait_resolution_on_fn_type | ||
12 | ); | 13 | ); |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index a450d7b84..0290b3474 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -272,8 +272,8 @@ impl CrateDefMap { | |||
272 | (res.resolved_def, res.segment_index) | 272 | (res.resolved_def, res.segment_index) |
273 | } | 273 | } |
274 | 274 | ||
275 | pub(crate) fn find_macro(&self, name: &Name) -> Option<&MacroDefId> { | 275 | pub(crate) fn find_macro(&self, name: &Name) -> Option<MacroDefId> { |
276 | self.public_macros.get(name).or(self.local_macros.get(name)) | 276 | self.public_macros.get(name).or(self.local_macros.get(name)).map(|it| *it) |
277 | } | 277 | } |
278 | 278 | ||
279 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 279 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 707556ef8..3874e28bf 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -1,16 +1,12 @@ | |||
1 | //! Name resolution. | 1 | //! Name resolution. |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use ra_syntax::ast; | 4 | use rustc_hash::{FxHashMap, FxHashSet}; |
5 | |||
6 | use rustc_hash::FxHashMap; | ||
7 | 5 | ||
8 | use crate::{ | 6 | use crate::{ |
9 | ModuleDef, Trait, | 7 | ModuleDef, Trait, |
10 | code_model_api::Crate, | 8 | code_model_api::Crate, |
11 | MacroCallId, | 9 | MacroDefId, |
12 | MacroCallLoc, | ||
13 | AstId, | ||
14 | db::HirDatabase, | 10 | db::HirDatabase, |
15 | name::{Name, KnownName}, | 11 | name::{Name, KnownName}, |
16 | nameres::{PerNs, CrateDefMap, CrateModuleId}, | 12 | nameres::{PerNs, CrateDefMap, CrateModuleId}, |
@@ -134,16 +130,9 @@ impl Resolver { | |||
134 | resolution | 130 | resolution |
135 | } | 131 | } |
136 | 132 | ||
137 | pub fn resolve_macro_call( | 133 | pub(crate) fn resolve_macro_call(&self, path: Option<Path>) -> Option<MacroDefId> { |
138 | &self, | ||
139 | db: &impl HirDatabase, | ||
140 | path: Option<Path>, | ||
141 | ast_id: AstId<ast::MacroCall>, | ||
142 | ) -> Option<MacroCallId> { | ||
143 | let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing); | 134 | let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing); |
144 | let def_id = self.module().and_then(|(module, _)| module.find_macro(&name))?; | 135 | self.module()?.0.find_macro(&name) |
145 | let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db); | ||
146 | Some(call_loc) | ||
147 | } | 136 | } |
148 | 137 | ||
149 | /// Returns the resolved path segments | 138 | /// Returns the resolved path segments |
@@ -193,19 +182,18 @@ impl Resolver { | |||
193 | names | 182 | names |
194 | } | 183 | } |
195 | 184 | ||
196 | pub(crate) fn traits_in_scope<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a { | 185 | pub(crate) fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<Trait> { |
197 | // FIXME prelude | 186 | let mut traits = FxHashSet::default(); |
198 | self.scopes | 187 | for scope in &self.scopes { |
199 | .iter() | 188 | if let Scope::ModuleScope(m) = scope { |
200 | .rev() | 189 | if let Some(prelude) = m.crate_def_map.prelude() { |
201 | .flat_map(|scope| { | 190 | let prelude_def_map = db.crate_def_map(prelude.krate); |
202 | match scope { | 191 | traits.extend(prelude_def_map[prelude.module_id].scope.traits()); |
203 | Scope::ModuleScope(m) => Some(m.crate_def_map[m.module_id].scope.traits()), | ||
204 | _ => None, | ||
205 | } | 192 | } |
206 | .into_iter() | 193 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); |
207 | }) | 194 | } |
208 | .flatten() | 195 | } |
196 | traits | ||
209 | } | 197 | } |
210 | 198 | ||
211 | fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { | 199 | fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 31bf13425..179faebfb 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, | 20 | HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, |
21 | AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,Path, | 21 | AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,Path, |
22 | expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, | 22 | expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, |
23 | ids::{LocationCtx,MacroCallId}, | 23 | ids::{LocationCtx, MacroDefId}, |
24 | docs::{docs_from_ast,Documentation}, | 24 | docs::{docs_from_ast,Documentation}, |
25 | expr, AstId, | 25 | expr, AstId, |
26 | }; | 26 | }; |
@@ -191,13 +191,12 @@ pub enum PathResolution { | |||
191 | 191 | ||
192 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 192 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
193 | pub struct MacroByExampleDef { | 193 | pub struct MacroByExampleDef { |
194 | pub(crate) id: MacroCallId, | 194 | pub(crate) id: MacroDefId, |
195 | } | 195 | } |
196 | 196 | ||
197 | impl MacroByExampleDef { | 197 | impl MacroByExampleDef { |
198 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::MacroCall>) { | 198 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::MacroCall>) { |
199 | let loc = self.id.loc(db); | 199 | (self.id.0.file_id(), self.id.0.to_node(db)) |
200 | (self.id.into(), loc.def.0.to_node(db)) | ||
201 | } | 200 | } |
202 | } | 201 | } |
203 | 202 | ||
@@ -284,21 +283,9 @@ impl SourceAnalyzer { | |||
284 | self.infer.as_ref()?.field_resolution(expr_id) | 283 | self.infer.as_ref()?.field_resolution(expr_id) |
285 | } | 284 | } |
286 | 285 | ||
287 | pub fn resolve_macro_call( | 286 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroByExampleDef> { |
288 | &self, | 287 | let id = self.resolver.resolve_macro_call(macro_call.path().and_then(Path::from_ast))?; |
289 | db: &impl HirDatabase, | 288 | Some(MacroByExampleDef { id }) |
290 | file_id: FileId, | ||
291 | macro_call: &ast::MacroCall, | ||
292 | ) -> Option<MacroByExampleDef> { | ||
293 | let hir_id = file_id.into(); | ||
294 | let ast_id = db.ast_id_map(hir_id).ast_id(macro_call).with_file_id(hir_id); | ||
295 | let call_id = self.resolver.resolve_macro_call( | ||
296 | db, | ||
297 | macro_call.path().and_then(Path::from_ast), | ||
298 | ast_id, | ||
299 | ); | ||
300 | |||
301 | call_id.map(|id| MacroByExampleDef { id }) | ||
302 | } | 289 | } |
303 | 290 | ||
304 | pub fn resolve_hir_path( | 291 | pub fn resolve_hir_path( |
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs index 15f0977b7..dfe883fa4 100644 --- a/crates/ra_hir/src/traits.rs +++ b/crates/ra_hir/src/traits.rs | |||
@@ -11,6 +11,7 @@ use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationC | |||
11 | pub struct TraitData { | 11 | pub struct TraitData { |
12 | name: Option<Name>, | 12 | name: Option<Name>, |
13 | items: Vec<TraitItem>, | 13 | items: Vec<TraitItem>, |
14 | auto: bool, | ||
14 | } | 15 | } |
15 | 16 | ||
16 | impl TraitData { | 17 | impl TraitData { |
@@ -19,6 +20,7 @@ impl TraitData { | |||
19 | let name = node.name().map(|n| n.as_name()); | 20 | let name = node.name().map(|n| n.as_name()); |
20 | let module = tr.module(db); | 21 | let module = tr.module(db); |
21 | let ctx = LocationCtx::new(db, module, file_id); | 22 | let ctx = LocationCtx::new(db, module, file_id); |
23 | let auto = node.is_auto(); | ||
22 | let items = if let Some(item_list) = node.item_list() { | 24 | let items = if let Some(item_list) = node.item_list() { |
23 | item_list | 25 | item_list |
24 | .impl_items() | 26 | .impl_items() |
@@ -31,7 +33,7 @@ impl TraitData { | |||
31 | } else { | 33 | } else { |
32 | Vec::new() | 34 | Vec::new() |
33 | }; | 35 | }; |
34 | Arc::new(TraitData { name, items }) | 36 | Arc::new(TraitData { name, items, auto }) |
35 | } | 37 | } |
36 | 38 | ||
37 | pub(crate) fn name(&self) -> &Option<Name> { | 39 | pub(crate) fn name(&self) -> &Option<Name> { |
@@ -41,6 +43,10 @@ impl TraitData { | |||
41 | pub(crate) fn items(&self) -> &[TraitItem] { | 43 | pub(crate) fn items(&self) -> &[TraitItem] { |
42 | &self.items | 44 | &self.items |
43 | } | 45 | } |
46 | |||
47 | pub(crate) fn is_auto(&self) -> bool { | ||
48 | self.auto | ||
49 | } | ||
44 | } | 50 | } |
45 | 51 | ||
46 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 52 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f4eee835f..cfe07156b 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -19,7 +19,7 @@ use std::{fmt, mem}; | |||
19 | use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams}; | 19 | use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams}; |
20 | use display::{HirDisplay, HirFormatter}; | 20 | use display::{HirDisplay, HirFormatter}; |
21 | 21 | ||
22 | pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig}; | 22 | pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig, generic_predicates}; |
23 | pub(crate) use infer::{infer, InferenceResult, InferTy}; | 23 | pub(crate) use infer::{infer, InferenceResult, InferTy}; |
24 | pub use lower::CallableDef; | 24 | pub use lower::CallableDef; |
25 | 25 | ||
@@ -234,13 +234,42 @@ impl TraitRef { | |||
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
237 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
238 | /// parameters of a generic item. | ||
239 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
240 | pub enum GenericPredicate { | ||
241 | /// The given trait needs to be implemented for its type parameters. | ||
242 | Implemented(TraitRef), | ||
243 | /// We couldn't resolve the trait reference. (If some type parameters can't | ||
244 | /// be resolved, they will just be Unknown). | ||
245 | Error, | ||
246 | } | ||
247 | |||
248 | impl GenericPredicate { | ||
249 | pub fn is_error(&self) -> bool { | ||
250 | match self { | ||
251 | GenericPredicate::Error => true, | ||
252 | _ => false, | ||
253 | } | ||
254 | } | ||
255 | |||
256 | pub fn subst(self, substs: &Substs) -> GenericPredicate { | ||
257 | match self { | ||
258 | GenericPredicate::Implemented(trait_ref) => { | ||
259 | GenericPredicate::Implemented(trait_ref.subst(substs)) | ||
260 | } | ||
261 | GenericPredicate::Error => self, | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | |||
237 | /// Basically a claim (currently not validated / checked) that the contained | 266 | /// Basically a claim (currently not validated / checked) that the contained |
238 | /// type / trait ref contains no inference variables; any inference variables it | 267 | /// type / trait ref contains no inference variables; any inference variables it |
239 | /// contained have been replaced by bound variables, and `num_vars` tells us how | 268 | /// contained have been replaced by bound variables, and `num_vars` tells us how |
240 | /// many there are. This is used to erase irrelevant differences between types | 269 | /// many there are. This is used to erase irrelevant differences between types |
241 | /// before using them in queries. | 270 | /// before using them in queries. |
242 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 271 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
243 | pub(crate) struct Canonical<T> { | 272 | pub struct Canonical<T> { |
244 | pub value: T, | 273 | pub value: T, |
245 | pub num_vars: usize, | 274 | pub num_vars: usize, |
246 | } | 275 | } |
@@ -534,3 +563,20 @@ impl HirDisplay for Ty { | |||
534 | Ok(()) | 563 | Ok(()) |
535 | } | 564 | } |
536 | } | 565 | } |
566 | |||
567 | impl HirDisplay for TraitRef { | ||
568 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
569 | write!( | ||
570 | f, | ||
571 | "{}: {}", | ||
572 | self.substs[0].display(f.db), | ||
573 | self.trait_.name(f.db).unwrap_or_else(Name::missing) | ||
574 | )?; | ||
575 | if self.substs.len() > 1 { | ||
576 | write!(f, "<")?; | ||
577 | f.write_joined(&self.substs[1..], ", ")?; | ||
578 | write!(f, ">")?; | ||
579 | } | ||
580 | Ok(()) | ||
581 | } | ||
582 | } | ||
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index edce1afe7..1e7d97f51 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -328,8 +328,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
328 | Obligation::Trait(tr) => { | 328 | Obligation::Trait(tr) => { |
329 | let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); | 329 | let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); |
330 | ( | 330 | ( |
331 | super::traits::implements( | 331 | self.db.implements( |
332 | self.db, | ||
333 | self.resolver.krate().unwrap(), | 332 | self.resolver.krate().unwrap(), |
334 | canonicalized.value.clone(), | 333 | canonicalized.value.clone(), |
335 | ), | 334 | ), |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 8bab7e54b..09d26ce5a 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -5,6 +5,7 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::sync::Arc; | ||
8 | use std::iter; | 9 | use std::iter; |
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
@@ -18,9 +19,9 @@ use crate::{ | |||
18 | resolve::{Resolver, Resolution}, | 19 | resolve::{Resolver, Resolution}, |
19 | path::{PathSegment, GenericArg}, | 20 | path::{PathSegment, GenericArg}, |
20 | generics::{GenericParams, HasGenericParams}, | 21 | generics::{GenericParams, HasGenericParams}, |
21 | adt::VariantDef, Trait | 22 | adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} |
22 | }; | 23 | }; |
23 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef}; | 24 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; |
24 | 25 | ||
25 | impl Ty { | 26 | impl Ty { |
26 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 27 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
@@ -208,16 +209,12 @@ pub(super) fn substs_from_path_segment( | |||
208 | } | 209 | } |
209 | 210 | ||
210 | impl TraitRef { | 211 | impl TraitRef { |
211 | pub(crate) fn from_hir( | 212 | pub(crate) fn from_path( |
212 | db: &impl HirDatabase, | 213 | db: &impl HirDatabase, |
213 | resolver: &Resolver, | 214 | resolver: &Resolver, |
214 | type_ref: &TypeRef, | 215 | path: &Path, |
215 | explicit_self_ty: Option<Ty>, | 216 | explicit_self_ty: Option<Ty>, |
216 | ) -> Option<Self> { | 217 | ) -> Option<Self> { |
217 | let path = match type_ref { | ||
218 | TypeRef::Path(path) => path, | ||
219 | _ => return None, | ||
220 | }; | ||
221 | let resolved = match resolver.resolve_path(db, &path).take_types()? { | 218 | let resolved = match resolver.resolve_path(db, &path).take_types()? { |
222 | Resolution::Def(ModuleDef::Trait(tr)) => tr, | 219 | Resolution::Def(ModuleDef::Trait(tr)) => tr, |
223 | _ => return None, | 220 | _ => return None, |
@@ -232,6 +229,19 @@ impl TraitRef { | |||
232 | Some(TraitRef { trait_: resolved, substs }) | 229 | Some(TraitRef { trait_: resolved, substs }) |
233 | } | 230 | } |
234 | 231 | ||
232 | pub(crate) fn from_hir( | ||
233 | db: &impl HirDatabase, | ||
234 | resolver: &Resolver, | ||
235 | type_ref: &TypeRef, | ||
236 | explicit_self_ty: Option<Ty>, | ||
237 | ) -> Option<Self> { | ||
238 | let path = match type_ref { | ||
239 | TypeRef::Path(path) => path, | ||
240 | _ => return None, | ||
241 | }; | ||
242 | TraitRef::from_path(db, resolver, path, explicit_self_ty) | ||
243 | } | ||
244 | |||
235 | fn substs_from_path( | 245 | fn substs_from_path( |
236 | db: &impl HirDatabase, | 246 | db: &impl HirDatabase, |
237 | resolver: &Resolver, | 247 | resolver: &Resolver, |
@@ -246,6 +256,15 @@ impl TraitRef { | |||
246 | let substs = Substs::identity(&trait_.generic_params(db)); | 256 | let substs = Substs::identity(&trait_.generic_params(db)); |
247 | TraitRef { trait_, substs } | 257 | TraitRef { trait_, substs } |
248 | } | 258 | } |
259 | |||
260 | pub(crate) fn for_where_predicate( | ||
261 | db: &impl HirDatabase, | ||
262 | resolver: &Resolver, | ||
263 | pred: &WherePredicate, | ||
264 | ) -> Option<TraitRef> { | ||
265 | let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); | ||
266 | TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty)) | ||
267 | } | ||
249 | } | 268 | } |
250 | 269 | ||
251 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 270 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
@@ -294,6 +313,24 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
294 | Ty::from_hir(db, &resolver, type_ref) | 313 | Ty::from_hir(db, &resolver, type_ref) |
295 | } | 314 | } |
296 | 315 | ||
316 | /// Resolve the where clause(s) of an item with generics. | ||
317 | pub(crate) fn generic_predicates( | ||
318 | db: &impl HirDatabase, | ||
319 | def: GenericDef, | ||
320 | ) -> Arc<[GenericPredicate]> { | ||
321 | let resolver = def.resolver(db); | ||
322 | let generic_params = def.generic_params(db); | ||
323 | let predicates = generic_params | ||
324 | .where_predicates | ||
325 | .iter() | ||
326 | .map(|pred| { | ||
327 | TraitRef::for_where_predicate(db, &resolver, pred) | ||
328 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
329 | }) | ||
330 | .collect::<Vec<_>>(); | ||
331 | predicates.into() | ||
332 | } | ||
333 | |||
297 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | 334 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { |
298 | let signature = def.signature(db); | 335 | let signature = def.signature(db); |
299 | let resolver = def.resolver(db); | 336 | let resolver = def.resolver(db); |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 607e9ba79..34817a5ec 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -75,11 +75,13 @@ impl CrateImplBlocks { | |||
75 | 75 | ||
76 | let target_ty = impl_block.target_ty(db); | 76 | let target_ty = impl_block.target_ty(db); |
77 | 77 | ||
78 | if let Some(tr) = impl_block.target_trait_ref(db) { | 78 | if impl_block.target_trait(db).is_some() { |
79 | self.impls_by_trait | 79 | if let Some(tr) = impl_block.target_trait_ref(db) { |
80 | .entry(tr.trait_) | 80 | self.impls_by_trait |
81 | .or_insert_with(Vec::new) | 81 | .entry(tr.trait_) |
82 | .push((module.module_id, impl_id)); | 82 | .or_insert_with(Vec::new) |
83 | .push((module.module_id, impl_id)); | ||
84 | } | ||
83 | } else { | 85 | } else { |
84 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | 86 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { |
85 | self.impls | 87 | self.impls |
@@ -183,7 +185,7 @@ fn iterate_trait_method_candidates<T>( | |||
183 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 185 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
184 | ) -> Option<T> { | 186 | ) -> Option<T> { |
185 | let krate = resolver.krate()?; | 187 | let krate = resolver.krate()?; |
186 | 'traits: for t in resolver.traits_in_scope() { | 188 | 'traits: for t in resolver.traits_in_scope(db) { |
187 | let data = t.trait_data(db); | 189 | let data = t.trait_data(db); |
188 | // we'll be lazy about checking whether the type implements the | 190 | // we'll be lazy about checking whether the type implements the |
189 | // trait, but if we find out it doesn't, we'll skip the rest of the | 191 | // trait, but if we find out it doesn't, we'll skip the rest of the |
@@ -196,8 +198,7 @@ fn iterate_trait_method_candidates<T>( | |||
196 | if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() { | 198 | if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() { |
197 | if !known_implemented { | 199 | if !known_implemented { |
198 | let trait_ref = canonical_trait_ref(db, t, ty.clone()); | 200 | let trait_ref = canonical_trait_ref(db, t, ty.clone()); |
199 | // FIXME cache this implements check (without solution) in a query? | 201 | if db.implements(krate, trait_ref).is_none() { |
200 | if super::traits::implements(db, krate, trait_ref).is_none() { | ||
201 | continue 'traits; | 202 | continue 'traits; |
202 | } | 203 | } |
203 | } | 204 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index a38fe35c7..978cc2587 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2502,6 +2502,50 @@ fn test() { (&S).foo()<|>; } | |||
2502 | } | 2502 | } |
2503 | 2503 | ||
2504 | #[test] | 2504 | #[test] |
2505 | fn method_resolution_trait_from_prelude() { | ||
2506 | let (mut db, pos) = MockDatabase::with_position( | ||
2507 | r#" | ||
2508 | //- /main.rs | ||
2509 | struct S; | ||
2510 | impl Clone for S {} | ||
2511 | |||
2512 | fn test() { | ||
2513 | S.clone()<|>; | ||
2514 | } | ||
2515 | |||
2516 | //- /lib.rs | ||
2517 | #[prelude_import] use foo::*; | ||
2518 | |||
2519 | mod foo { | ||
2520 | trait Clone { | ||
2521 | fn clone(&self) -> Self; | ||
2522 | } | ||
2523 | } | ||
2524 | "#, | ||
2525 | ); | ||
2526 | db.set_crate_graph_from_fixture(crate_graph! { | ||
2527 | "main": ("/main.rs", ["other_crate"]), | ||
2528 | "other_crate": ("/lib.rs", []), | ||
2529 | }); | ||
2530 | assert_eq!("S", type_at_pos(&db, pos)); | ||
2531 | } | ||
2532 | |||
2533 | #[test] | ||
2534 | fn method_resolution_where_clause_for_unknown_trait() { | ||
2535 | // The blanket impl shouldn't apply because we can't even resolve UnknownTrait | ||
2536 | let t = type_at( | ||
2537 | r#" | ||
2538 | //- /main.rs | ||
2539 | trait Trait { fn foo(self) -> u128; } | ||
2540 | struct S; | ||
2541 | impl<T> Trait for T where T: UnknownTrait {} | ||
2542 | fn test() { (&S).foo()<|>; } | ||
2543 | "#, | ||
2544 | ); | ||
2545 | assert_eq!(t, "{unknown}"); | ||
2546 | } | ||
2547 | |||
2548 | #[test] | ||
2505 | fn method_resolution_where_clause_not_met() { | 2549 | fn method_resolution_where_clause_not_met() { |
2506 | // The blanket impl shouldn't apply because we can't prove S: Clone | 2550 | // The blanket impl shouldn't apply because we can't prove S: Clone |
2507 | let t = type_at( | 2551 | let t = type_at( |
@@ -2510,12 +2554,122 @@ fn method_resolution_where_clause_not_met() { | |||
2510 | trait Clone {} | 2554 | trait Clone {} |
2511 | trait Trait { fn foo(self) -> u128; } | 2555 | trait Trait { fn foo(self) -> u128; } |
2512 | struct S; | 2556 | struct S; |
2513 | impl S { fn foo(self) -> i8 { 0 } } | 2557 | impl<T> Trait for T where T: Clone {} |
2514 | impl<T> Trait for T where T: Clone { fn foo(self) -> u128 { 0 } } | ||
2515 | fn test() { (&S).foo()<|>; } | 2558 | fn test() { (&S).foo()<|>; } |
2516 | "#, | 2559 | "#, |
2517 | ); | 2560 | ); |
2518 | assert_eq!(t, "i8"); | 2561 | // This is also to make sure that we don't resolve to the foo method just |
2562 | // because that's the only method named foo we can find, which would make | ||
2563 | // the below tests not work | ||
2564 | assert_eq!(t, "{unknown}"); | ||
2565 | } | ||
2566 | |||
2567 | #[test] | ||
2568 | fn method_resolution_where_clause_inline_not_met() { | ||
2569 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
2570 | let t = type_at( | ||
2571 | r#" | ||
2572 | //- /main.rs | ||
2573 | trait Clone {} | ||
2574 | trait Trait { fn foo(self) -> u128; } | ||
2575 | struct S; | ||
2576 | impl<T: Clone> Trait for T {} | ||
2577 | fn test() { (&S).foo()<|>; } | ||
2578 | "#, | ||
2579 | ); | ||
2580 | assert_eq!(t, "{unknown}"); | ||
2581 | } | ||
2582 | |||
2583 | #[test] | ||
2584 | fn method_resolution_where_clause_1() { | ||
2585 | let t = type_at( | ||
2586 | r#" | ||
2587 | //- /main.rs | ||
2588 | trait Clone {} | ||
2589 | trait Trait { fn foo(self) -> u128; } | ||
2590 | struct S; | ||
2591 | impl Clone for S {}; | ||
2592 | impl<T> Trait for T where T: Clone {} | ||
2593 | fn test() { S.foo()<|>; } | ||
2594 | "#, | ||
2595 | ); | ||
2596 | assert_eq!(t, "u128"); | ||
2597 | } | ||
2598 | |||
2599 | #[test] | ||
2600 | fn method_resolution_where_clause_2() { | ||
2601 | let t = type_at( | ||
2602 | r#" | ||
2603 | //- /main.rs | ||
2604 | trait Into<T> { fn into(self) -> T; } | ||
2605 | trait From<T> { fn from(other: T) -> Self; } | ||
2606 | struct S1; | ||
2607 | struct S2; | ||
2608 | impl From<S2> for S1 {}; | ||
2609 | impl<T, U> Into<U> for T where U: From<T> {} | ||
2610 | fn test() { S2.into()<|>; } | ||
2611 | "#, | ||
2612 | ); | ||
2613 | assert_eq!(t, "S1"); | ||
2614 | } | ||
2615 | |||
2616 | #[test] | ||
2617 | fn method_resolution_where_clause_inline() { | ||
2618 | let t = type_at( | ||
2619 | r#" | ||
2620 | //- /main.rs | ||
2621 | trait Into<T> { fn into(self) -> T; } | ||
2622 | trait From<T> { fn from(other: T) -> Self; } | ||
2623 | struct S1; | ||
2624 | struct S2; | ||
2625 | impl From<S2> for S1 {}; | ||
2626 | impl<T, U: From<T>> Into<U> for T {} | ||
2627 | fn test() { S2.into()<|>; } | ||
2628 | "#, | ||
2629 | ); | ||
2630 | assert_eq!(t, "S1"); | ||
2631 | } | ||
2632 | |||
2633 | #[test] | ||
2634 | fn method_resolution_encountering_fn_type() { | ||
2635 | covers!(trait_resolution_on_fn_type); | ||
2636 | type_at( | ||
2637 | r#" | ||
2638 | //- /main.rs | ||
2639 | fn foo() {} | ||
2640 | trait FnOnce { fn call(self); } | ||
2641 | fn test() { foo.call()<|>; } | ||
2642 | "#, | ||
2643 | ); | ||
2644 | } | ||
2645 | |||
2646 | #[test] | ||
2647 | fn method_resolution_slow() { | ||
2648 | // this can get quite slow if we set the solver size limit too high | ||
2649 | let t = type_at( | ||
2650 | r#" | ||
2651 | //- /main.rs | ||
2652 | trait SendX {} | ||
2653 | |||
2654 | struct S1; impl SendX for S1; | ||
2655 | struct S2; impl SendX for S2; | ||
2656 | struct U1; | ||
2657 | |||
2658 | trait Trait { fn method(self); } | ||
2659 | |||
2660 | struct X1<A, B> {} | ||
2661 | impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {} | ||
2662 | |||
2663 | struct S<B, C> {} | ||
2664 | |||
2665 | trait FnX {} | ||
2666 | |||
2667 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | ||
2668 | |||
2669 | fn test() { (S {}).method()<|>; } | ||
2670 | "#, | ||
2671 | ); | ||
2672 | assert_eq!(t, "{unknown}"); | ||
2519 | } | 2673 | } |
2520 | 2674 | ||
2521 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2675 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index a1ed0c028..4260f7ef7 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use rustc_hash::FxHashSet; | ||
4 | use log::debug; | 5 | use log::debug; |
5 | use chalk_ir::cast::Cast; | 6 | use chalk_ir::cast::Cast; |
6 | 7 | ||
@@ -13,6 +14,11 @@ mod chalk; | |||
13 | 14 | ||
14 | pub(crate) type Solver = chalk_solve::Solver; | 15 | pub(crate) type Solver = chalk_solve::Solver; |
15 | 16 | ||
17 | /// This controls the maximum size of types Chalk considers. If we set this too | ||
18 | /// high, we can run into slow edge cases; if we set it too low, Chalk won't | ||
19 | /// find some solutions. | ||
20 | const CHALK_SOLVER_MAX_SIZE: usize = 2; | ||
21 | |||
16 | #[derive(Debug, Copy, Clone)] | 22 | #[derive(Debug, Copy, Clone)] |
17 | struct ChalkContext<'a, DB> { | 23 | struct ChalkContext<'a, DB> { |
18 | db: &'a DB, | 24 | db: &'a DB, |
@@ -21,7 +27,8 @@ struct ChalkContext<'a, DB> { | |||
21 | 27 | ||
22 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { | 28 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { |
23 | // krate parameter is just so we cache a unique solver per crate | 29 | // krate parameter is just so we cache a unique solver per crate |
24 | let solver_choice = chalk_solve::SolverChoice::SLG { max_size: 10 }; | 30 | let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; |
31 | debug!("Creating new solver for crate {:?}", _krate); | ||
25 | Arc::new(Mutex::new(solver_choice.into_solver())) | 32 | Arc::new(Mutex::new(solver_choice.into_solver())) |
26 | } | 33 | } |
27 | 34 | ||
@@ -31,7 +38,7 @@ pub(crate) fn impls_for_trait( | |||
31 | krate: Crate, | 38 | krate: Crate, |
32 | trait_: Trait, | 39 | trait_: Trait, |
33 | ) -> Arc<[ImplBlock]> { | 40 | ) -> Arc<[ImplBlock]> { |
34 | let mut impls = Vec::new(); | 41 | let mut impls = FxHashSet::default(); |
35 | // We call the query recursively here. On the one hand, this means we can | 42 | // We call the query recursively here. On the one hand, this means we can |
36 | // reuse results from queries for different crates; on the other hand, this | 43 | // reuse results from queries for different crates; on the other hand, this |
37 | // will only ever get called for a few crates near the root of the tree (the | 44 | // will only ever get called for a few crates near the root of the tree (the |
@@ -42,7 +49,7 @@ pub(crate) fn impls_for_trait( | |||
42 | } | 49 | } |
43 | let crate_impl_blocks = db.impls_in_crate(krate); | 50 | let crate_impl_blocks = db.impls_in_crate(krate); |
44 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); | 51 | impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_)); |
45 | impls.into() | 52 | impls.into_iter().collect::<Vec<_>>().into() |
46 | } | 53 | } |
47 | 54 | ||
48 | fn solve( | 55 | fn solve( |
@@ -52,6 +59,7 @@ fn solve( | |||
52 | ) -> Option<chalk_solve::Solution> { | 59 | ) -> Option<chalk_solve::Solution> { |
53 | let context = ChalkContext { db, krate }; | 60 | let context = ChalkContext { db, krate }; |
54 | let solver = db.solver(krate); | 61 | let solver = db.solver(krate); |
62 | debug!("solve goal: {:?}", goal); | ||
55 | let solution = solver.lock().unwrap().solve(&context, goal); | 63 | let solution = solver.lock().unwrap().solve(&context, goal); |
56 | debug!("solve({:?}) => {:?}", goal, solution); | 64 | debug!("solve({:?}) => {:?}", goal, solution); |
57 | solution | 65 | solution |
@@ -125,11 +133,11 @@ fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) - | |||
125 | } | 133 | } |
126 | 134 | ||
127 | #[derive(Clone, Debug, PartialEq, Eq)] | 135 | #[derive(Clone, Debug, PartialEq, Eq)] |
128 | pub(crate) struct SolutionVariables(pub Canonical<Vec<Ty>>); | 136 | pub struct SolutionVariables(pub Canonical<Vec<Ty>>); |
129 | 137 | ||
130 | #[derive(Clone, Debug, PartialEq, Eq)] | 138 | #[derive(Clone, Debug, PartialEq, Eq)] |
131 | /// A (possible) solution for a proposed goal. | 139 | /// A (possible) solution for a proposed goal. |
132 | pub(crate) enum Solution { | 140 | pub enum Solution { |
133 | /// The goal indeed holds, and there is a unique value for all existential | 141 | /// The goal indeed holds, and there is a unique value for all existential |
134 | /// variables. | 142 | /// variables. |
135 | Unique(SolutionVariables), | 143 | Unique(SolutionVariables), |
@@ -144,7 +152,7 @@ pub(crate) enum Solution { | |||
144 | #[derive(Clone, Debug, PartialEq, Eq)] | 152 | #[derive(Clone, Debug, PartialEq, Eq)] |
145 | /// When a goal holds ambiguously (e.g., because there are multiple possible | 153 | /// When a goal holds ambiguously (e.g., because there are multiple possible |
146 | /// solutions), we issue a set of *guidance* back to type inference. | 154 | /// solutions), we issue a set of *guidance* back to type inference. |
147 | pub(crate) enum Guidance { | 155 | pub enum Guidance { |
148 | /// The existential variables *must* have the given values if the goal is | 156 | /// The existential variables *must* have the given values if the goal is |
149 | /// ever to hold, but that alone isn't enough to guarantee the goal will | 157 | /// ever to hold, but that alone isn't enough to guarantee the goal will |
150 | /// actually hold. | 158 | /// actually hold. |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 8b77d21b4..78440b258 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -6,15 +6,22 @@ use log::debug; | |||
6 | use chalk_ir::{TypeId, ImplId, TypeKindId, ProjectionTy, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; | 6 | use chalk_ir::{TypeId, ImplId, TypeKindId, ProjectionTy, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; |
7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; | 7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; |
8 | 8 | ||
9 | use test_utils::tested_by; | ||
9 | use ra_db::salsa::{InternId, InternKey}; | 10 | use ra_db::salsa::{InternId, InternKey}; |
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{ |
12 | Trait, HasGenericParams, ImplBlock, | 13 | Trait, HasGenericParams, ImplBlock, |
13 | db::HirDatabase, | 14 | db::HirDatabase, |
14 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs}, | 15 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef}, |
16 | ty::display::HirDisplay, | ||
17 | generics::GenericDef, | ||
15 | }; | 18 | }; |
16 | use super::ChalkContext; | 19 | use super::ChalkContext; |
17 | 20 | ||
21 | /// This represents a trait whose name we could not resolve. | ||
22 | const UNKNOWN_TRAIT: chalk_ir::TraitId = | ||
23 | chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); | ||
24 | |||
18 | pub(super) trait ToChalk { | 25 | pub(super) trait ToChalk { |
19 | type Chalk; | 26 | type Chalk; |
20 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; | 27 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; |
@@ -45,7 +52,10 @@ impl ToChalk for Ty { | |||
45 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 52 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
46 | // FIXME this is clearly incorrect, but probably not too incorrect | 53 | // FIXME this is clearly incorrect, but probably not too incorrect |
47 | // and I'm not sure what to actually do with Ty::Unknown | 54 | // and I'm not sure what to actually do with Ty::Unknown |
48 | Ty::Unknown => PlaceholderIndex { ui: UniverseIndex::ROOT, idx: 0 }.to_ty(), | 55 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) |
56 | Ty::Unknown => { | ||
57 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() | ||
58 | } | ||
49 | } | 59 | } |
50 | } | 60 | } |
51 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { | 61 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { |
@@ -146,6 +156,33 @@ impl ToChalk for ImplBlock { | |||
146 | } | 156 | } |
147 | } | 157 | } |
148 | 158 | ||
159 | impl ToChalk for GenericPredicate { | ||
160 | type Chalk = chalk_ir::QuantifiedWhereClause; | ||
161 | |||
162 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { | ||
163 | match self { | ||
164 | GenericPredicate::Implemented(trait_ref) => { | ||
165 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | ||
166 | } | ||
167 | GenericPredicate::Error => { | ||
168 | let impossible_trait_ref = chalk_ir::TraitRef { | ||
169 | trait_id: UNKNOWN_TRAIT, | ||
170 | parameters: vec![Ty::Unknown.to_chalk(db).cast()], | ||
171 | }; | ||
172 | make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | fn from_chalk( | ||
178 | _db: &impl HirDatabase, | ||
179 | _where_clause: chalk_ir::QuantifiedWhereClause, | ||
180 | ) -> GenericPredicate { | ||
181 | // This should never need to be called | ||
182 | unimplemented!() | ||
183 | } | ||
184 | } | ||
185 | |||
149 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 186 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
150 | chalk_ir::Binders { | 187 | chalk_ir::Binders { |
151 | value, | 188 | value, |
@@ -153,6 +190,40 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
153 | } | 190 | } |
154 | } | 191 | } |
155 | 192 | ||
193 | fn blacklisted_trait(db: &impl HirDatabase, trait_: Trait) -> bool { | ||
194 | let name = trait_.name(db).unwrap_or_else(crate::Name::missing).to_string(); | ||
195 | match &*name { | ||
196 | "Send" | "Sync" | "Sized" | "Fn" | "FnMut" | "FnOnce" => true, | ||
197 | _ => false, | ||
198 | } | ||
199 | } | ||
200 | |||
201 | fn convert_where_clauses( | ||
202 | db: &impl HirDatabase, | ||
203 | def: GenericDef, | ||
204 | substs: &Substs, | ||
205 | ) -> Vec<chalk_ir::QuantifiedWhereClause> { | ||
206 | let generic_predicates = db.generic_predicates(def); | ||
207 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
208 | for pred in generic_predicates.iter() { | ||
209 | if pred.is_error() { | ||
210 | // HACK: Return just the single predicate (which is always false | ||
211 | // anyway), otherwise Chalk can easily get into slow situations | ||
212 | return vec![pred.clone().subst(substs).to_chalk(db)]; | ||
213 | } | ||
214 | match pred { | ||
215 | GenericPredicate::Implemented(trait_ref) => { | ||
216 | if blacklisted_trait(db, trait_ref.trait_) { | ||
217 | continue; | ||
218 | } | ||
219 | } | ||
220 | _ => {} | ||
221 | } | ||
222 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
223 | } | ||
224 | result | ||
225 | } | ||
226 | |||
156 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 227 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> |
157 | where | 228 | where |
158 | DB: HirDatabase, | 229 | DB: HirDatabase, |
@@ -162,18 +233,36 @@ where | |||
162 | } | 233 | } |
163 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 234 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { |
164 | debug!("trait_datum {:?}", trait_id); | 235 | debug!("trait_datum {:?}", trait_id); |
236 | if trait_id == UNKNOWN_TRAIT { | ||
237 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | ||
238 | trait_ref: chalk_ir::TraitRef { | ||
239 | trait_id: UNKNOWN_TRAIT, | ||
240 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | ||
241 | }, | ||
242 | associated_ty_ids: Vec::new(), | ||
243 | where_clauses: Vec::new(), | ||
244 | flags: chalk_rust_ir::TraitFlags { | ||
245 | auto: false, | ||
246 | marker: false, | ||
247 | upstream: true, | ||
248 | fundamental: false, | ||
249 | }, | ||
250 | }; | ||
251 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) }); | ||
252 | } | ||
165 | let trait_: Trait = from_chalk(self.db, trait_id); | 253 | let trait_: Trait = from_chalk(self.db, trait_id); |
254 | debug!("trait {:?} = {:?}", trait_id, trait_.name(self.db)); | ||
166 | let generic_params = trait_.generic_params(self.db); | 255 | let generic_params = trait_.generic_params(self.db); |
167 | let bound_vars = Substs::bound_vars(&generic_params); | 256 | let bound_vars = Substs::bound_vars(&generic_params); |
168 | let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); | 257 | let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); |
169 | let flags = chalk_rust_ir::TraitFlags { | 258 | let flags = chalk_rust_ir::TraitFlags { |
259 | auto: trait_.is_auto(self.db), | ||
260 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), | ||
170 | // FIXME set these flags correctly | 261 | // FIXME set these flags correctly |
171 | auto: false, | ||
172 | marker: false, | 262 | marker: false, |
173 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), | ||
174 | fundamental: false, | 263 | fundamental: false, |
175 | }; | 264 | }; |
176 | let where_clauses = Vec::new(); // FIXME add where clauses | 265 | let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); |
177 | let associated_ty_ids = Vec::new(); // FIXME add associated tys | 266 | let associated_ty_ids = Vec::new(); // FIXME add associated tys |
178 | let trait_datum_bound = | 267 | let trait_datum_bound = |
179 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; | 268 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; |
@@ -183,23 +272,51 @@ where | |||
183 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { | 272 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { |
184 | debug!("struct_datum {:?}", struct_id); | 273 | debug!("struct_datum {:?}", struct_id); |
185 | let type_ctor = from_chalk(self.db, struct_id); | 274 | let type_ctor = from_chalk(self.db, struct_id); |
275 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | ||
186 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor | 276 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor |
187 | // FIXME extract this to a method on Ty | 277 | // FIXME extract this to a method on Ty |
188 | let (num_params, upstream) = match type_ctor { | 278 | let (num_params, where_clauses, upstream) = match type_ctor { |
189 | TypeCtor::Bool | 279 | TypeCtor::Bool |
190 | | TypeCtor::Char | 280 | | TypeCtor::Char |
191 | | TypeCtor::Int(_) | 281 | | TypeCtor::Int(_) |
192 | | TypeCtor::Float(_) | 282 | | TypeCtor::Float(_) |
193 | | TypeCtor::Never | 283 | | TypeCtor::Never |
194 | | TypeCtor::Str => (0, true), | 284 | | TypeCtor::Str => (0, vec![], true), |
195 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => (1, true), | 285 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => { |
196 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, true), | 286 | (1, vec![], true) |
197 | TypeCtor::Tuple { cardinality } => (cardinality as usize, true), | 287 | } |
198 | TypeCtor::FnDef(_) => unimplemented!(), | 288 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true), |
289 | TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true), | ||
290 | TypeCtor::FnDef(callable) => { | ||
291 | tested_by!(trait_resolution_on_fn_type); | ||
292 | let krate = match callable { | ||
293 | CallableDef::Function(f) => f.module(self.db).krate(self.db), | ||
294 | CallableDef::Struct(s) => s.module(self.db).krate(self.db), | ||
295 | CallableDef::EnumVariant(v) => { | ||
296 | v.parent_enum(self.db).module(self.db).krate(self.db) | ||
297 | } | ||
298 | }; | ||
299 | let generic_def: GenericDef = match callable { | ||
300 | CallableDef::Function(f) => f.into(), | ||
301 | CallableDef::Struct(s) => s.into(), | ||
302 | CallableDef::EnumVariant(v) => v.parent_enum(self.db).into(), | ||
303 | }; | ||
304 | let generic_params = generic_def.generic_params(self.db); | ||
305 | let bound_vars = Substs::bound_vars(&generic_params); | ||
306 | let where_clauses = convert_where_clauses(self.db, generic_def, &bound_vars); | ||
307 | ( | ||
308 | generic_params.count_params_including_parent(), | ||
309 | where_clauses, | ||
310 | krate != Some(self.krate), | ||
311 | ) | ||
312 | } | ||
199 | TypeCtor::Adt(adt) => { | 313 | TypeCtor::Adt(adt) => { |
200 | let generic_params = adt.generic_params(self.db); | 314 | let generic_params = adt.generic_params(self.db); |
315 | let bound_vars = Substs::bound_vars(&generic_params); | ||
316 | let where_clauses = convert_where_clauses(self.db, adt.into(), &bound_vars); | ||
201 | ( | 317 | ( |
202 | generic_params.count_params_including_parent(), | 318 | generic_params.count_params_including_parent(), |
319 | where_clauses, | ||
203 | adt.krate(self.db) != Some(self.krate), | 320 | adt.krate(self.db) != Some(self.krate), |
204 | ) | 321 | ) |
205 | } | 322 | } |
@@ -209,7 +326,6 @@ where | |||
209 | // FIXME set fundamental flag correctly | 326 | // FIXME set fundamental flag correctly |
210 | fundamental: false, | 327 | fundamental: false, |
211 | }; | 328 | }; |
212 | let where_clauses = Vec::new(); // FIXME add where clauses | ||
213 | let self_ty = chalk_ir::ApplicationTy { | 329 | let self_ty = chalk_ir::ApplicationTy { |
214 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), | 330 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), |
215 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | 331 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), |
@@ -237,10 +353,23 @@ where | |||
237 | } else { | 353 | } else { |
238 | chalk_rust_ir::ImplType::External | 354 | chalk_rust_ir::ImplType::External |
239 | }; | 355 | }; |
356 | let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars); | ||
357 | let negative = impl_block.is_negative(self.db); | ||
358 | debug!( | ||
359 | "impl {:?}: {}{} where {:?}", | ||
360 | impl_id, | ||
361 | if negative { "!" } else { "" }, | ||
362 | trait_ref.display(self.db), | ||
363 | where_clauses | ||
364 | ); | ||
365 | let trait_ref = trait_ref.to_chalk(self.db); | ||
240 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 366 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
241 | // FIXME handle negative impls (impl !Sync for Foo) | 367 | trait_ref: if negative { |
242 | trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), | 368 | chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref) |
243 | where_clauses: Vec::new(), // FIXME add where clauses | 369 | } else { |
370 | chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref) | ||
371 | }, | ||
372 | where_clauses, | ||
244 | associated_ty_values: Vec::new(), // FIXME add associated type values | 373 | associated_ty_values: Vec::new(), // FIXME add associated type values |
245 | impl_type, | 374 | impl_type, |
246 | }; | 375 | }; |
@@ -249,16 +378,22 @@ where | |||
249 | } | 378 | } |
250 | fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { | 379 | fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { |
251 | debug!("impls_for_trait {:?}", trait_id); | 380 | debug!("impls_for_trait {:?}", trait_id); |
252 | let trait_ = from_chalk(self.db, trait_id); | 381 | if trait_id == UNKNOWN_TRAIT { |
253 | self.db | 382 | return Vec::new(); |
383 | } | ||
384 | let trait_: Trait = from_chalk(self.db, trait_id); | ||
385 | let blacklisted = blacklisted_trait(self.db, trait_); | ||
386 | if blacklisted { | ||
387 | return Vec::new(); | ||
388 | } | ||
389 | let result: Vec<_> = self | ||
390 | .db | ||
254 | .impls_for_trait(self.krate, trait_) | 391 | .impls_for_trait(self.krate, trait_) |
255 | .iter() | 392 | .iter() |
256 | // FIXME temporary hack -- as long as we're not lowering where clauses | ||
257 | // correctly, ignore impls with them completely so as to not treat | ||
258 | // impl<T> Trait for T where T: ... as a blanket impl on all types | ||
259 | .filter(|impl_block| impl_block.generic_params(self.db).where_predicates.is_empty()) | ||
260 | .map(|impl_block| impl_block.to_chalk(self.db)) | 393 | .map(|impl_block| impl_block.to_chalk(self.db)) |
261 | .collect() | 394 | .collect(); |
395 | debug!("impls_for_trait returned {} impls", result.len()); | ||
396 | result | ||
262 | } | 397 | } |
263 | fn impl_provided_for( | 398 | fn impl_provided_for( |
264 | &self, | 399 | &self, |