Collapse term search exprs before Cartesian product to avoid OOM

This commit is contained in:
Tavo Annus 2024-05-06 08:38:43 +03:00
parent c4618fe14d
commit c3ab435b54
4 changed files with 43 additions and 20 deletions

View file

@ -127,6 +127,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone()); 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 res
} }
@ -158,6 +165,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone()); 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 res
} }
@ -176,11 +190,11 @@ impl LookupTable {
} }
None => { None => {
self.data.insert(ty.clone(), AlternativeExprs::new(self.many_threshold, exprs)); 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 /// Iterate all the reachable types

View file

@ -211,13 +211,13 @@ impl Expr {
} }
} }
Expr::Method { func, target, params, .. } => { 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))); return Ok(many_formatter(&target.ty(db)));
} }
let func_name = func.name(db).display(db.upcast()).to_string(); let func_name = func.name(db).display(db.upcast()).to_string();
let self_param = func.self_param(db).unwrap(); let self_param = func.self_param(db).unwrap();
let target = target.gen_source_code( let target_str = target.gen_source_code(
sema_scope, sema_scope,
many_formatter, many_formatter,
prefer_no_std, prefer_no_std,
@ -236,9 +236,12 @@ impl Expr {
Some(trait_) => { Some(trait_) => {
let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?; let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?;
let target = match self_param.access(db) { let target = match self_param.access(db) {
crate::Access::Shared => format!("&{target}"), crate::Access::Shared if !target.is_many() => format!("&{target_str}"),
crate::Access::Exclusive => format!("&mut {target}"), crate::Access::Exclusive if !target.is_many() => {
crate::Access::Owned => target, format!("&mut {target_str}")
}
crate::Access::Owned => target_str,
_ => many_formatter(&target.ty(db)),
}; };
let res = match args.is_empty() { let res = match args.is_empty() {
true => format!("{trait_name}::{func_name}({target})",), true => format!("{trait_name}::{func_name}({target})",),
@ -246,7 +249,7 @@ impl Expr {
}; };
Ok(res) Ok(res)
} }
None => Ok(format!("{target}.{func_name}({args})")), None => Ok(format!("{target_str}.{func_name}({args})")),
} }
} }
Expr::Variant { variant, generics, params } => { Expr::Variant { variant, generics, params } => {
@ -381,7 +384,7 @@ impl Expr {
Ok(res) Ok(res)
} }
Expr::Field { expr, field } => { 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))); return Ok(many_formatter(&expr.ty(db)));
} }
@ -395,7 +398,7 @@ impl Expr {
Ok(format!("{strukt}.{field}")) Ok(format!("{strukt}.{field}"))
} }
Expr::Reference(expr) => { 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))); return Ok(many_formatter(&expr.ty(db)));
} }
@ -466,10 +469,17 @@ impl Expr {
/// macro!().bar() /// macro!().bar()
/// &macro!() /// &macro!()
/// ``` /// ```
fn contains_many_in_illegal_pos(&self) -> bool { fn contains_many_in_illegal_pos(&self, db: &dyn HirDatabase) -> bool {
match self { match self {
Expr::Method { target, .. } => target.contains_many_in_illegal_pos(), Expr::Method { target, func, .. } => {
Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(), 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::Reference(target) => target.is_many(),
Expr::Many(_) => true, Expr::Many(_) => true,
_ => false, _ => false,

View file

@ -1808,8 +1808,7 @@ fn f() { A { bar: b$0 }; }
fn baz() [type] fn baz() [type]
ex baz() [type] ex baz() [type]
ex bar() [type] ex bar() [type]
ex A { bar: baz() }.bar [type] ex A { bar: ... }.bar [type]
ex A { bar: bar() }.bar [type]
st A [] st A []
fn f() [] fn f() []
"#]], "#]],
@ -1947,8 +1946,8 @@ fn main() {
} }
"#, "#,
expect![[r#" 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) (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 m [local]
lc t [local] lc t [local]
lc &t [type+local] lc &t [type+local]
@ -1997,8 +1996,8 @@ fn main() {
} }
"#, "#,
expect![[r#" 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) (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 m [local]
lc t [local] lc t [local]
lc &mut t [type+local] lc &mut t [type+local]

View file

@ -274,7 +274,7 @@ impl Foo for Baz {
} }
fn asd() -> Bar { fn asd() -> Bar {
let a = Baz; let a = Baz;
Foo::foo(a) Foo::foo(_)
} }
", ",
); );
@ -363,7 +363,7 @@ impl Foo for A {
} }
fn main() { fn main() {
let a = A; let a = A;
let c: Bar = Foo::foo(&a); let c: Bar = Foo::foo(_);
}"#, }"#,
); );
} }