Unnamed repository; edit this file 'description' to name the repository.
Collapse term search exprs before Cartesian product to avoid OOM
Tavo Annus 2024-05-07
parent c4618fe · commit c3ab435
-rw-r--r--crates/hir/src/term_search.rs20
-rw-r--r--crates/hir/src/term_search/expr.rs32
-rw-r--r--crates/ide-completion/src/render.rs7
-rw-r--r--crates/ide-diagnostics/src/handlers/typed_hole.rs4
4 files changed, 43 insertions, 20 deletions
diff --git a/crates/hir/src/term_search.rs b/crates/hir/src/term_search.rs
index 93e7300491..ea13b0c8a8 100644
--- a/crates/hir/src/term_search.rs
+++ b/crates/hir/src/term_search.rs
@@ -127,6 +127,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone());
}
+ // Collapse suggestions if there are many
+ if let Some(res) = &res {
+ if res.len() > self.many_threshold {
+ return Some(vec![Expr::Many(ty.clone())]);
+ }
+ }
+
res
}
@@ -158,6 +165,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone());
}
+ // Collapse suggestions if there are many
+ if let Some(res) = &res {
+ if res.len() > self.many_threshold {
+ return Some(vec![Expr::Many(ty.clone())]);
+ }
+ }
+
res
}
@@ -176,11 +190,11 @@ impl LookupTable {
}
None => {
self.data.insert(ty.clone(), AlternativeExprs::new(self.many_threshold, exprs));
- for it in self.new_types.values_mut() {
- it.push(ty.clone());
- }
}
}
+ for it in self.new_types.values_mut() {
+ it.push(ty.clone());
+ }
}
/// Iterate all the reachable types
diff --git a/crates/hir/src/term_search/expr.rs b/crates/hir/src/term_search/expr.rs
index 2d0c5630e1..06372355c5 100644
--- a/crates/hir/src/term_search/expr.rs
+++ b/crates/hir/src/term_search/expr.rs
@@ -211,13 +211,13 @@ impl Expr {
}
}
Expr::Method { func, target, params, .. } => {
- if target.contains_many_in_illegal_pos() {
+ if self.contains_many_in_illegal_pos(db) {
return Ok(many_formatter(&target.ty(db)));
}
let func_name = func.name(db).display(db.upcast()).to_string();
let self_param = func.self_param(db).unwrap();
- let target = target.gen_source_code(
+ let target_str = target.gen_source_code(
sema_scope,
many_formatter,
prefer_no_std,
@@ -236,9 +236,12 @@ impl Expr {
Some(trait_) => {
let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?;
let target = match self_param.access(db) {
- crate::Access::Shared => format!("&{target}"),
- crate::Access::Exclusive => format!("&mut {target}"),
- crate::Access::Owned => target,
+ crate::Access::Shared if !target.is_many() => format!("&{target_str}"),
+ crate::Access::Exclusive if !target.is_many() => {
+ format!("&mut {target_str}")
+ }
+ crate::Access::Owned => target_str,
+ _ => many_formatter(&target.ty(db)),
};
let res = match args.is_empty() {
true => format!("{trait_name}::{func_name}({target})",),
@@ -246,7 +249,7 @@ impl Expr {
};
Ok(res)
}
- None => Ok(format!("{target}.{func_name}({args})")),
+ None => Ok(format!("{target_str}.{func_name}({args})")),
}
}
Expr::Variant { variant, generics, params } => {
@@ -381,7 +384,7 @@ impl Expr {
Ok(res)
}
Expr::Field { expr, field } => {
- if expr.contains_many_in_illegal_pos() {
+ if expr.contains_many_in_illegal_pos(db) {
return Ok(many_formatter(&expr.ty(db)));
}
@@ -395,7 +398,7 @@ impl Expr {
Ok(format!("{strukt}.{field}"))
}
Expr::Reference(expr) => {
- if expr.contains_many_in_illegal_pos() {
+ if expr.contains_many_in_illegal_pos(db) {
return Ok(many_formatter(&expr.ty(db)));
}
@@ -466,10 +469,17 @@ impl Expr {
/// macro!().bar()
/// &macro!()
/// ```
- fn contains_many_in_illegal_pos(&self) -> bool {
+ fn contains_many_in_illegal_pos(&self, db: &dyn HirDatabase) -> bool {
match self {
- Expr::Method { target, .. } => target.contains_many_in_illegal_pos(),
- Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(),
+ Expr::Method { target, func, .. } => {
+ match func.as_assoc_item(db).and_then(|it| it.container_or_implemented_trait(db)) {
+ Some(_) => false,
+ None => {
+ target.is_many()
+ }
+ }
+ }
+ Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(db),
Expr::Reference(target) => target.is_many(),
Expr::Many(_) => true,
_ => false,
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 0f13bea7b6..2b4743cf18 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -1808,8 +1808,7 @@ fn f() { A { bar: b$0 }; }
fn baz() [type]
ex baz() [type]
ex bar() [type]
- ex A { bar: baz() }.bar [type]
- ex A { bar: bar() }.bar [type]
+ ex A { bar: ... }.bar [type]
st A []
fn f() []
"#]],
@@ -1947,8 +1946,8 @@ fn main() {
}
"#,
expect![[r#"
- ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify]
ex core::ops::Deref::deref(&t) (use core::ops::Deref) [type_could_unify]
+ ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify]
lc m [local]
lc t [local]
lc &t [type+local]
@@ -1997,8 +1996,8 @@ fn main() {
}
"#,
expect![[r#"
- ex core::ops::DerefMut::deref_mut(&mut T(S)) (use core::ops::DerefMut) [type_could_unify]
ex core::ops::DerefMut::deref_mut(&mut t) (use core::ops::DerefMut) [type_could_unify]
+ ex core::ops::DerefMut::deref_mut(&mut T(S)) (use core::ops::DerefMut) [type_could_unify]
lc m [local]
lc t [local]
lc &mut t [type+local]
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 56c8181e84..e78bd2db8b 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -274,7 +274,7 @@ impl Foo for Baz {
}
fn asd() -> Bar {
let a = Baz;
- Foo::foo(a)
+ Foo::foo(_)
}
",
);
@@ -363,7 +363,7 @@ impl Foo for A {
}
fn main() {
let a = A;
- let c: Bar = Foo::foo(&a);
+ let c: Bar = Foo::foo(_);
}"#,
);
}