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() /// ¯o!() /// ``` - 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(_); }"#, ); }