From 7fda874dd4c84d4b53ed625e9eccc92c3fa9a48e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 11 May 2019 20:31:41 +0200 Subject: 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. --- crates/ra_hir/src/ty/tests.rs | 12 ++++++------ crates/ra_hir/src/ty/traits/chalk.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'crates') 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() { let t = type_at( r#" //- /main.rs -trait Send {} +trait SendX {} -struct S1; impl Send for S1; -struct S2; impl Send for S2; +struct S1; impl SendX for S1; +struct S2; impl SendX for S2; struct U1; trait Trait { fn method(self); } struct X1 {} -impl Send for X1 where A: Send, B: Send {} +impl SendX for X1 where A: SendX, B: SendX {} struct S {} -trait Fn {} +trait FnX {} -impl Trait for S where C: Fn, B: Send {} +impl Trait for S where C: FnX, B: SendX {} fn test() { (S {}).method()<|>; } "#, 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(value: T, num_vars: usize) -> chalk_ir::Binders { } } +fn blacklisted_trait(db: &impl HirDatabase, trait_: Trait) -> bool { + let name = trait_.name(db).unwrap_or_else(crate::Name::missing).to_string(); + match &*name { + "Send" | "Sync" | "Sized" | "Fn" | "FnMut" | "FnOnce" => true, + _ => false, + } +} + fn convert_where_clauses( db: &impl HirDatabase, def: GenericDef, @@ -198,6 +206,19 @@ fn convert_where_clauses( let generic_predicates = db.generic_predicates(def); let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { + if pred.is_error() { + // HACK: Return just the single predicate (which is always false + // anyway), otherwise Chalk can easily get into slow situations + return vec![pred.clone().subst(substs).to_chalk(db)]; + } + match pred { + GenericPredicate::Implemented(trait_ref) => { + if blacklisted_trait(db, trait_ref.trait_) { + continue; + } + } + _ => {} + } result.push(pred.clone().subst(substs).to_chalk(db)); } result @@ -230,6 +251,7 @@ where return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) }); } let trait_: Trait = from_chalk(self.db, trait_id); + debug!("trait {:?} = {:?}", trait_id, trait_.name(self.db)); let generic_params = trait_.generic_params(self.db); let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); @@ -250,6 +272,7 @@ where fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc { debug!("struct_datum {:?}", struct_id); let type_ctor = from_chalk(self.db, struct_id); + debug!("struct {:?} = {:?}", struct_id, type_ctor); // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor // FIXME extract this to a method on Ty let (num_params, where_clauses, upstream) = match type_ctor { @@ -358,7 +381,11 @@ where if trait_id == UNKNOWN_TRAIT { return Vec::new(); } - let trait_ = from_chalk(self.db, trait_id); + let trait_: Trait = from_chalk(self.db, trait_id); + let blacklisted = blacklisted_trait(self.db, trait_); + if blacklisted { + return Vec::new(); + } let result: Vec<_> = self .db .impls_for_trait(self.krate, trait_) -- cgit v1.2.3