Reduce Chalk max_size parameter, add test for slow case

This commit is contained in:
Florian Diebold 2019-05-07 17:35:45 +02:00
parent d8cd0e36f5
commit 7744cd41e2
3 changed files with 42 additions and 3 deletions

View File

@ -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<A, B> {}
impl<A, B> Send for X1<A, B> where A: Send, B: Send {}
struct S<B, C> {}
trait Fn {}
impl<B, C> Trait for S<B, C> 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::<ast::Expr>(file.syntax(), pos.offset).unwrap();

View File

@ -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<Mutex<Solver>> {
// 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<chalk_solve::Solution> {
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

View File

@ -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,