Skip to content

Commit 7fda874

Browse files
committed
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.
1 parent c8b8589 commit 7fda874

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

crates/ra_hir/src/ty/tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,22 +2620,22 @@ fn method_resolution_slow() {
26202620
let t = type_at(
26212621
r#"
26222622
//- /main.rs
2623-
trait Send {}
2623+
trait SendX {}
26242624
2625-
struct S1; impl Send for S1;
2626-
struct S2; impl Send for S2;
2625+
struct S1; impl SendX for S1;
2626+
struct S2; impl SendX for S2;
26272627
struct U1;
26282628
26292629
trait Trait { fn method(self); }
26302630
26312631
struct X1<A, B> {}
2632-
impl<A, B> Send for X1<A, B> where A: Send, B: Send {}
2632+
impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {}
26332633
26342634
struct S<B, C> {}
26352635
2636-
trait Fn {}
2636+
trait FnX {}
26372637
2638-
impl<B, C> Trait for S<B, C> where C: Fn, B: Send {}
2638+
impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
26392639
26402640
fn test() { (S {}).method()<|>; }
26412641
"#,

crates/ra_hir/src/ty/traits/chalk.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
190190
}
191191
}
192192

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+
193201
fn convert_where_clauses(
194202
db: &impl HirDatabase,
195203
def: GenericDef,
@@ -198,6 +206,19 @@ fn convert_where_clauses(
198206
let generic_predicates = db.generic_predicates(def);
199207
let mut result = Vec::with_capacity(generic_predicates.len());
200208
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+
}
201222
result.push(pred.clone().subst(substs).to_chalk(db));
202223
}
203224
result
@@ -230,6 +251,7 @@ where
230251
return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) });
231252
}
232253
let trait_: Trait = from_chalk(self.db, trait_id);
254+
debug!("trait {:?} = {:?}", trait_id, trait_.name(self.db));
233255
let generic_params = trait_.generic_params(self.db);
234256
let bound_vars = Substs::bound_vars(&generic_params);
235257
let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db);
@@ -250,6 +272,7 @@ where
250272
fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
251273
debug!("struct_datum {:?}", struct_id);
252274
let type_ctor = from_chalk(self.db, struct_id);
275+
debug!("struct {:?} = {:?}", struct_id, type_ctor);
253276
// FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
254277
// FIXME extract this to a method on Ty
255278
let (num_params, where_clauses, upstream) = match type_ctor {
@@ -358,7 +381,11 @@ where
358381
if trait_id == UNKNOWN_TRAIT {
359382
return Vec::new();
360383
}
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+
}
362389
let result: Vec<_> = self
363390
.db
364391
.impls_for_trait(self.krate, trait_)

0 commit comments

Comments
 (0)