aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-05-11 19:31:41 +0100
committerFlorian Diebold <[email protected]>2019-05-12 19:23:57 +0100
commit7fda874dd4c84d4b53ed625e9eccc92c3fa9a48e (patch)
tree104eccdcdc745f6d15dcf9173996815c807a7287 /crates
parentc8b85891b0c6c03a1b373491f75b8872ec47e06f (diff)
Blacklist some traits from being considered in where clauses
For Send/Sync/Sized, we don't handle auto traits correctly yet and because they have a lot of impls, they can easily lead to slowdowns. In the case of Fn/FnMut/FnOnce, we don't parse the special Fn notation correctly yet and don't handle closures yet, so we are very unlikely to find an impl.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/ty/tests.rs12
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs29
2 files changed, 34 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 59c85daed..510fa5333 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2620,22 +2620,22 @@ fn method_resolution_slow() {
2620 let t = type_at( 2620 let t = type_at(
2621 r#" 2621 r#"
2622//- /main.rs 2622//- /main.rs
2623trait Send {} 2623trait SendX {}
2624 2624
2625struct S1; impl Send for S1; 2625struct S1; impl SendX for S1;
2626struct S2; impl Send for S2; 2626struct S2; impl SendX for S2;
2627struct U1; 2627struct U1;
2628 2628
2629trait Trait { fn method(self); } 2629trait Trait { fn method(self); }
2630 2630
2631struct X1<A, B> {} 2631struct X1<A, B> {}
2632impl<A, B> Send for X1<A, B> where A: Send, B: Send {} 2632impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {}
2633 2633
2634struct S<B, C> {} 2634struct S<B, C> {}
2635 2635
2636trait Fn {} 2636trait FnX {}
2637 2637
2638impl<B, C> Trait for S<B, C> where C: Fn, B: Send {} 2638impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
2639 2639
2640fn test() { (S {}).method()<|>; } 2640fn test() { (S {}).method()<|>; }
2641"#, 2641"#,
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
193fn 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
193fn convert_where_clauses( 201fn 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_)