diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-12 19:36:36 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-12 19:36:36 +0100 |
commit | 0f57564f78207946fdb09e0cddc21a55966b1bc5 (patch) | |
tree | e8aa2948b2bb301f453307c35311634cda5de43b /crates/ra_hir/src/ty/traits | |
parent | 02ba107bbf24b1d09e61f76bb64b7355076744c4 (diff) | |
parent | bc59f83991a6444ff2f2364b0e942e8a82943b6d (diff) |
Merge #1266
1266: Chalk integration / method resolution fixes r=matklad a=flodiebold
- fix impl blocks with unresolved target trait being treated as inherent impls
- add traits from prelude for method resolution, and deduplicate them
- blacklist some traits from being considered in where clauses, namely `Send`, `Sync`, `Sized`, and the `Fn` traits. We don't handle these correctly yet for several reasons, and this makes us much less likely to run into cases where Chalk gets very slow (because these usually only happen if there is no solution, and that's more likely to happen for these traits).
- when there's an errored where clause, return just that one (since it will be always false anyway). This also makes things easier on Chalk ;)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/traits')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 027c5ec4c..78440b258 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -190,6 +190,14 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
190 | } | 190 | } |
191 | } | 191 | } |
192 | 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 | |||
193 | fn convert_where_clauses( | 201 | fn convert_where_clauses( |
194 | db: &impl HirDatabase, | 202 | db: &impl HirDatabase, |
195 | def: GenericDef, | 203 | def: GenericDef, |
@@ -198,6 +206,19 @@ fn convert_where_clauses( | |||
198 | let generic_predicates = db.generic_predicates(def); | 206 | let generic_predicates = db.generic_predicates(def); |
199 | let mut result = Vec::with_capacity(generic_predicates.len()); | 207 | let mut result = Vec::with_capacity(generic_predicates.len()); |
200 | for pred in generic_predicates.iter() { | 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 | } | ||
201 | result.push(pred.clone().subst(substs).to_chalk(db)); | 222 | result.push(pred.clone().subst(substs).to_chalk(db)); |
202 | } | 223 | } |
203 | result | 224 | result |
@@ -230,6 +251,7 @@ where | |||
230 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) }); | 251 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) }); |
231 | } | 252 | } |
232 | 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)); | ||
233 | let generic_params = trait_.generic_params(self.db); | 255 | let generic_params = trait_.generic_params(self.db); |
234 | let bound_vars = Substs::bound_vars(&generic_params); | 256 | let bound_vars = Substs::bound_vars(&generic_params); |
235 | 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); |
@@ -250,6 +272,7 @@ where | |||
250 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { | 272 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { |
251 | debug!("struct_datum {:?}", struct_id); | 273 | debug!("struct_datum {:?}", struct_id); |
252 | 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); | ||
253 | // 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 |
254 | // FIXME extract this to a method on Ty | 277 | // FIXME extract this to a method on Ty |
255 | let (num_params, where_clauses, upstream) = match type_ctor { | 278 | let (num_params, where_clauses, upstream) = match type_ctor { |
@@ -358,7 +381,11 @@ where | |||
358 | if trait_id == UNKNOWN_TRAIT { | 381 | if trait_id == UNKNOWN_TRAIT { |
359 | return Vec::new(); | 382 | return Vec::new(); |
360 | } | 383 | } |
361 | let trait_ = from_chalk(self.db, trait_id); | 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 | } | ||
362 | let result: Vec<_> = self | 389 | let result: Vec<_> = self |
363 | .db | 390 | .db |
364 | .impls_for_trait(self.krate, trait_) | 391 | .impls_for_trait(self.krate, trait_) |