diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f0793bfb493c..6f8d8fa49277 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2581,6 +2581,35 @@ fn test() { foo.call()<|>; }
);
}
+#[test]
+fn method_resolution_slow() {
+ // this can get quite slow if we set the solver size limit too high
+ let t = type_at(
+ r#"
+//- /main.rs
+trait Send {}
+
+struct S1; impl Send for S1;
+struct S2; impl Send for S2;
+struct U1;
+
+trait Trait { fn method(self); }
+
+struct X1 {}
+impl Send for X1 where A: Send, B: Send {}
+
+struct S {}
+
+trait Fn {}
+
+impl Trait for S where C: Fn, B: Send {}
+
+fn test() { (S {}).method()<|>; }
+"#,
+ );
+ assert_eq!(t, "{unknown}");
+}
+
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
let file = db.parse(pos.file_id);
let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 4bbc99f0ef16..4260f7ef7477 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -14,6 +14,11 @@ mod chalk;
pub(crate) type Solver = chalk_solve::Solver;
+/// This controls the maximum size of types Chalk considers. If we set this too
+/// high, we can run into slow edge cases; if we set it too low, Chalk won't
+/// find some solutions.
+const CHALK_SOLVER_MAX_SIZE: usize = 2;
+
#[derive(Debug, Copy, Clone)]
struct ChalkContext<'a, DB> {
db: &'a DB,
@@ -22,7 +27,8 @@ struct ChalkContext<'a, DB> {
pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc> {
// krate parameter is just so we cache a unique solver per crate
- let solver_choice = chalk_solve::SolverChoice::SLG { max_size: 10 };
+ let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
+ debug!("Creating new solver for crate {:?}", _krate);
Arc::new(Mutex::new(solver_choice.into_solver()))
}
@@ -53,6 +59,7 @@ fn solve(
) -> Option {
let context = ChalkContext { db, krate };
let solver = db.solver(krate);
+ debug!("solve goal: {:?}", goal);
let solution = solver.lock().unwrap().solve(&context, goal);
debug!("solve({:?}) => {:?}", goal, solution);
solution
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 7bb6a4f4add9..8fa0ba7a5112 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -345,11 +345,14 @@ where
return Vec::new();
}
let trait_ = from_chalk(self.db, trait_id);
- self.db
+ let result: Vec<_> = self
+ .db
.impls_for_trait(self.krate, trait_)
.iter()
.map(|impl_block| impl_block.to_chalk(self.db))
- .collect()
+ .collect();
+ debug!("impls_for_trait returned {} impls", result.len());
+ result
}
fn impl_provided_for(
&self,