Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/render.rs')
-rw-r--r--crates/ide-completion/src/render.rs407
1 files changed, 354 insertions, 53 deletions
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index fbbdffefe3..e48847c983 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -71,7 +71,7 @@ impl<'a, 'db> RenderContext<'a, 'db> {
self.completion.config.snippet_cap
}
- fn db(&self) -> &'a RootDatabase {
+ fn db(&self) -> &'db RootDatabase {
self.completion.db
}
@@ -181,9 +181,9 @@ pub(crate) fn render_field(
if !expected_fn_type
&& let Some(receiver) = &dot_access.receiver
- && let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone())
+ && let Some(receiver) = ctx.completion.sema.original_range_opt(receiver.syntax())
{
- builder.insert(receiver.syntax().text_range().start(), "(".to_owned());
+ builder.insert(receiver.range.start(), "(".to_owned());
builder.insert(ctx.source_range().end(), ")".to_owned());
let is_parens_needed = !matches!(dot_access.kind, DotAccessKind::Method);
@@ -198,10 +198,10 @@ pub(crate) fn render_field(
item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name));
}
if let Some(receiver) = &dot_access.receiver
- && let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone())
+ && let Some(original) = ctx.completion.sema.original_range_opt(receiver.syntax())
&& let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
{
- item.ref_match(ref_mode, original.syntax().text_range().start());
+ item.ref_match(ref_mode, original.range.start());
}
item.doc_aliases(ctx.doc_aliases);
item.build(db)
@@ -294,9 +294,9 @@ pub(crate) fn render_resolution_with_import_pat(
Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
}
-pub(crate) fn render_expr(
- ctx: &CompletionContext<'_, '_>,
- expr: &hir::term_search::Expr<'_>,
+pub(crate) fn render_expr<'db>(
+ ctx: &CompletionContext<'_, 'db>,
+ expr: &hir::term_search::Expr<'db>,
) -> Option<Builder> {
let mut i = 1;
let mut snippet_formatter = |ty: &hir::Type<'_>| {
@@ -341,7 +341,7 @@ pub(crate) fn render_expr(
"Autogenerated expression by term search",
)));
item.set_relevance(crate::CompletionRelevance {
- type_match: compute_type_match(ctx, &expr.ty(ctx.db)),
+ type_match: compute_type_match(ctx, &ctx.rebase_ty(&expr.ty(ctx.db))),
..Default::default()
});
for trait_ in expr.traits_used(ctx.db) {
@@ -405,8 +405,8 @@ fn render_resolution_pat(
}
}
-fn render_resolution_path(
- ctx: RenderContext<'_, '_>,
+fn render_resolution_path<'db>(
+ ctx: RenderContext<'_, 'db>,
path_ctx: &PathCompletionCtx<'_>,
local_name: hir::Name,
import_to_add: Option<LocatedImport>,
@@ -471,18 +471,21 @@ fn render_resolution_path(
.insert_snippet(cap, ""); // set is snippet
}
}
- let allow_module_path = matches!(path_ctx.kind, PathKind::Use) || !config.add_colons_to_module;
+ let allow_module_path = matches!(path_ctx.kind, PathKind::Use)
+ || completion.token.next_token().is_some_and(|it| it.kind() == syntax::T![::])
+ || !config.add_colons_to_module;
if !allow_module_path && matches!(resolution, ScopeDef::ModuleDef(Module(_))) {
insert_text = format_smolstr!("{insert_text}::");
item.lookup_by(name.clone()).label(insert_text.clone());
}
adds_ret_type_arrow(completion, path_ctx, &mut item, insert_text.into());
- let mut set_item_relevance = |ty: Type<'_>| {
+ let mut set_item_relevance = |ty: Type<'db>| {
if !ty.is_unknown() {
item.detail(ty.display(db, krate).to_string());
}
+ let ty = completion.rebase_ty(&ty);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(completion, &ty),
exact_name_match: compute_exact_name_match(completion, &name),
@@ -492,7 +495,13 @@ fn render_resolution_path(
..CompletionRelevance::default()
});
- path_ref_match(completion, path_ctx, &ty, &mut item);
+ match resolution {
+ ScopeDef::Local(_)
+ | ScopeDef::ModuleDef(ModuleDef::Const(_) | ModuleDef::Static(_)) => {
+ path_ref_match(completion, path_ctx, &ty, &mut item)
+ }
+ _ => (),
+ }
};
match resolution {
@@ -680,8 +689,8 @@ fn compute_type_match(
// &mut ty -> &ty
if completion_ty.is_mutable_reference()
- && let Some(expected_type) = expected_type.remove_ref()
- && let Some(completion_ty) = completion_ty.remove_ref()
+ && let Some((expected_type, _)) = expected_type.as_reference()
+ && let Some((completion_ty, _)) = completion_ty.as_reference()
{
return match_types(ctx, &expected_type, &completion_ty);
}
@@ -709,18 +718,19 @@ fn compute_ref_match(
ctx: &CompletionContext<'_, '_>,
completion_ty: &hir::Type<'_>,
) -> Option<CompletionItemRefMode> {
- let expected_type = ctx.expected_type.as_ref()?;
- let expected_without_ref = expected_type.remove_ref();
- let completion_without_ref = completion_ty.remove_ref();
- if expected_type.could_unify_with(ctx.db, completion_ty) {
+ if compute_type_match(ctx, completion_ty).is_some() || completion_ty.is_unit() {
return None;
}
- if let Some(expected_without_ref) = &expected_without_ref
+ let expected_type = ctx.expected_type.as_ref()?;
+ let expected_without_ref = expected_type.as_reference();
+ let completion_without_ref = completion_ty.as_reference();
+
+ if let Some((expected_without_ref, _)) = &expected_without_ref
&& (completion_without_ref.is_none()
|| completion_ty.could_unify_with(ctx.db, expected_without_ref))
&& completion_ty
.autoderef(ctx.db)
- .any(|ty| ty.could_unify_with(ctx.db, expected_without_ref))
+ .any(|ty| !ty.is_unknown() && ty.could_unify_with(ctx.db, expected_without_ref))
{
cov_mark::hit!(suggest_ref);
let mutability = if expected_type.is_mutable_reference() {
@@ -731,7 +741,7 @@ fn compute_ref_match(
return Some(CompletionItemRefMode::Reference(mutability));
}
- if let Some(completion_without_ref) = completion_without_ref
+ if let Some((completion_without_ref, _)) = completion_without_ref
&& completion_without_ref == *expected_type
&& completion_without_ref.is_copy(ctx.db)
{
@@ -750,10 +760,10 @@ fn path_ref_match(
) {
if let Some(original_path) = &path_ctx.original_path {
// At least one char was typed by the user already, in that case look for the original path
- if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
+ if let Some(original_path) = completion.sema.original_range_opt(original_path.syntax())
&& let Some(ref_mode) = compute_ref_match(completion, ty)
{
- item.ref_match(ref_mode, original_path.syntax().text_range().start());
+ item.ref_match(ref_mode, original_path.range.start());
}
} else {
// completion requested on an empty identifier, there is no path here yet.
@@ -865,6 +875,7 @@ mod tests {
exact_name_match,
type_match,
is_local,
+ is_missing,
trait_,
is_name_already_imported: _,
requires_import,
@@ -880,6 +891,7 @@ mod tests {
(type_match == Some(CompletionRelevanceTypeMatch::CouldUnify), "type_could_unify"),
(exact_name_match, "name"),
(is_local, "local"),
+ (is_missing, "missing"),
(postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet"),
(trait_.is_some_and(|it| it.is_op_method), "op_method"),
(requires_import, "requires_import"),
@@ -944,9 +956,9 @@ fn main() {
}
"#,
expect![[r#"
- st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify]
- ex dep::test_mod_b::Struct { } [type_could_unify]
- st Struct Struct [type_could_unify+requires_import]
+ st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type]
+ ex dep::test_mod_b::Struct { } [type]
+ st Struct Struct [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Struct) []
@@ -984,7 +996,7 @@ fn main() {
}
"#,
expect![[r#"
- un Union Union [type_could_unify+requires_import]
+ un Union Union [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Union) []
@@ -1020,9 +1032,9 @@ fn main() {
}
"#,
expect![[r#"
- ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify]
- ex dep::test_mod_b::Enum::variant [type_could_unify]
- en Enum Enum [type_could_unify+requires_import]
+ ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type]
+ ex dep::test_mod_b::Enum::variant [type]
+ en Enum Enum [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Enum) []
@@ -1058,11 +1070,13 @@ fn main() {
}
"#,
expect![[r#"
- ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify]
- ex dep::test_mod_b::Enum::Variant [type_could_unify]
+ ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type]
+ ex dep::test_mod_b::Enum::Variant [type]
+ ev Variant Variant [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(Enum) []
+ ev Variant Variant [requires_import]
"#]],
);
}
@@ -1122,7 +1136,7 @@ fn main() {
}
"#,
expect![[r#"
- ct CONST i32 [type_could_unify+requires_import]
+ ct CONST i32 [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(i32) []
@@ -1154,7 +1168,7 @@ fn main() {
}
"#,
expect![[r#"
- sc STATIC i32 [type_could_unify+requires_import]
+ sc STATIC i32 [type+requires_import]
md dep:: []
fn main() fn() []
fn test(…) fn(i32) []
@@ -1281,6 +1295,7 @@ fn main() { Foo::Fo$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1333,6 +1348,7 @@ fn main() { Foo::Fo$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1478,6 +1494,7 @@ fn main() { Foo::Fo$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1564,6 +1581,7 @@ fn main() { let _: m::Spam = S$0 }
Exact,
),
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1602,6 +1620,7 @@ fn main() { let _: m::Spam = S$0 }
Exact,
),
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1653,6 +1672,7 @@ fn main() { som$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1712,6 +1732,7 @@ fn main() { som$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1755,6 +1776,7 @@ fn main() { A$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1798,6 +1820,7 @@ fn main() { A$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1843,6 +1866,7 @@ fn main() { A::$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1879,6 +1903,7 @@ fn main() { A::$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1929,6 +1954,7 @@ fn main() { A$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -1972,6 +1998,7 @@ fn main() { A$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2012,6 +2039,7 @@ impl A$0
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2052,6 +2080,7 @@ fn main() { A$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2096,6 +2125,7 @@ fn main() { a$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2140,6 +2170,7 @@ fn main() { A { the$0 } }
CouldUnify,
),
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2195,6 +2226,7 @@ impl S {
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2288,6 +2320,7 @@ use self::E::*;
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2360,6 +2393,7 @@ fn foo(s: S) { s.$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2580,6 +2614,7 @@ fn f() -> i32 {
Exact,
),
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2639,7 +2674,6 @@ fn go(world: &WorldSnapshot) { go(w$0) }
st WorldSnapshot {…} WorldSnapshot { _f: () } []
st &WorldSnapshot {…} [type]
st WorldSnapshot WorldSnapshot []
- st &WorldSnapshot [type]
fn go(…) fn(&WorldSnapshot) []
"#]],
);
@@ -2687,6 +2721,7 @@ fn main() {
exact_name_match: false,
type_match: None,
is_local: true,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -2705,6 +2740,204 @@ fn main() {
}
#[test]
+ fn complete_ref_match_in_macro() {
+ check_kinds(
+ r#"
+macro_rules! id { ($($t:tt)*) => ($($t)*); }
+fn foo(data: &i32) {}
+fn main() {
+ let indent = 2i32;
+ id!(foo(i$0))
+}
+"#,
+ &[CompletionItemKind::SymbolKind(SymbolKind::Local)],
+ expect![[r#"
+ [
+ CompletionItem {
+ label: "indent",
+ detail_left: None,
+ detail_right: Some(
+ "i32",
+ ),
+ source_range: 114..115,
+ delete: 114..115,
+ insert: "indent",
+ kind: SymbolKind(
+ Local,
+ ),
+ detail: "i32",
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: true,
+ is_missing: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: None,
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: false,
+ },
+ ref_match: "&@114",
+ },
+ ]
+ "#]],
+ );
+
+ check_kinds(
+ r#"
+macro_rules! id { ($($t:tt)*) => ($($t)*); }
+fn foo(data: &i32) {}
+fn indent() -> i32 { i32 }
+fn main() {
+ id!(foo(i$0))
+}
+"#,
+ &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
+ expect![[r#"
+ [
+ CompletionItem {
+ label: "foo(…)",
+ detail_left: None,
+ detail_right: Some(
+ "fn(&i32)",
+ ),
+ source_range: 118..119,
+ delete: 118..119,
+ insert: "foo(${1:data})$0",
+ kind: SymbolKind(
+ Function,
+ ),
+ lookup: "foo",
+ detail: "fn(&i32)",
+ trigger_call_info: true,
+ },
+ CompletionItem {
+ label: "indent()",
+ detail_left: None,
+ detail_right: Some(
+ "fn() -> i32",
+ ),
+ source_range: 118..119,
+ delete: 118..119,
+ insert: "indent()$0",
+ kind: SymbolKind(
+ Function,
+ ),
+ lookup: "indent",
+ detail: "fn() -> i32",
+ ref_match: "&@118",
+ },
+ CompletionItem {
+ label: "main()",
+ detail_left: None,
+ detail_right: Some(
+ "fn()",
+ ),
+ source_range: 118..119,
+ delete: 118..119,
+ insert: "main()$0",
+ kind: SymbolKind(
+ Function,
+ ),
+ lookup: "main",
+ detail: "fn()",
+ },
+ ]
+ "#]],
+ );
+
+ // FIXME: It is best to test `S.in` if speculative execution is implemented
+ check_kinds(
+ r#"
+macro_rules! id { ($($t:tt)*) => ($($t)*); }
+fn foo(data: &i32) {}
+struct S;
+impl S {fn indent(&self) -> i32 { i32 }}
+fn main() {
+ id!(foo(S.i$0))
+}
+"#,
+ &[CompletionItemKind::SymbolKind(SymbolKind::Method)],
+ expect![[r#"
+ [
+ CompletionItem {
+ label: "indent()",
+ detail_left: None,
+ detail_right: Some(
+ "fn(&self) -> i32",
+ ),
+ source_range: 144..145,
+ delete: 144..145,
+ insert: "indent()$0",
+ kind: SymbolKind(
+ Method,
+ ),
+ lookup: "indent",
+ detail: "fn(&self) -> i32",
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: None,
+ is_local: false,
+ is_missing: false,
+ trait_: None,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_private_editable: false,
+ postfix_match: None,
+ function: Some(
+ CompletionRelevanceFn {
+ has_params: true,
+ has_self_param: true,
+ return_type: Other,
+ },
+ ),
+ is_skipping_completion: false,
+ has_local_inherent_impl: false,
+ is_deprecated: false,
+ },
+ ref_match: "&@142",
+ },
+ ]
+ "#]],
+ );
+
+ check_kinds(
+ r#"
+macro_rules! id { ($($t:tt)*) => ($($t)*); }
+fn foo(data: &i32) {}
+struct S { indent: i32 }
+fn main(s: S) {
+ id!(foo(s.i$0))
+}
+"#,
+ &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
+ expect![[r#"
+ [
+ CompletionItem {
+ label: "indent",
+ detail_left: None,
+ detail_right: Some(
+ "i32",
+ ),
+ source_range: 122..123,
+ delete: 122..123,
+ insert: "indent",
+ kind: SymbolKind(
+ Field,
+ ),
+ detail: "i32",
+ ref_match: "&@120",
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
fn too_many_arguments() {
cov_mark::check!(too_many_arguments);
check_relevance(
@@ -2825,6 +3058,37 @@ mod b {
}
#[test]
+ fn score_patterns() {
+ check_relevance(
+ r#"
+struct Foo(Bar);
+struct Bar { field: i32 }
+fn go(Foo($0): Foo) {}
+"#,
+ expect![[r#"
+ bn Bar {…} Bar { field$1 }$0 [type]
+ st Bar []
+ st Foo []
+ bn Foo(…) Foo($1)$0 []
+ "#]],
+ );
+
+ check_relevance(
+ r#"
+struct Foo(Bar);
+enum Bar { Variant { field: i32 } }
+fn go(foo: Foo) { match foo { Foo($0) } }
+"#,
+ expect![[r#"
+ bn Bar::Variant {…} Bar::Variant { field$1 }$0 [type]
+ en Bar []
+ st Foo []
+ bn Foo(…) Foo($1)$0 []
+ "#]],
+ );
+ }
+
+ #[test]
fn test_avoid_redundant_suggestion() {
check_relevance(
r#"
@@ -2865,7 +3129,6 @@ fn main() {
st S S []
st &mut S [type]
st S S []
- st &mut S [type]
fn foo(…) fn(&mut S) []
fn main() fn() []
"#]],
@@ -2879,6 +3142,7 @@ fn main() {
foo(&mut $0);
}
"#,
+ // FIXME: There are many `S` here
expect![[r#"
lc s S [type+name+local]
st S S [type]
@@ -2940,12 +3204,51 @@ fn main() {
st &mut S(…) [type]
lc ssss S<u32> [local]
lc &mut ssss [type+local]
- st S S<{unknown}> []
- st &mut S [type]
+ st S S<T> []
fn foo(…) fn(&mut S<T>) []
fn main() fn() []
"#]],
);
+ // Regression test https://github.com/rust-lang/rust-analyzer/issues/22324
+ check_relevance(
+ r#"
+//- minicore: deref
+struct S<T>(T);
+impl<T> core::ops::Deref for S<T> {
+ type Target = T;
+}
+fn foo<T>(s: &u32) {}
+fn main() {
+ let ssss = S();
+ foo($0);
+}
+ "#,
+ // FIXME: term_search exclude ssss.0 (field.ty().is_unknown())
+ expect![[r#"
+ ex ssss.0 [type_could_unify]
+ lc ssss S<{unknown}> [local]
+ st S S<T> []
+ md core:: []
+ fn foo(…) fn(&u32) []
+ fn main() fn() []
+ "#]],
+ );
+ check_relevance(
+ r#"
+//- minicore: deref
+fn foo<T>(s: &T) {}
+fn main() {
+ let ssss = &mut 2i32;
+ foo($0);
+}
+ "#,
+ expect![[r#"
+ lc ssss &mut i32 [type_could_unify+local]
+ md core:: []
+ fn foo(…) fn(&T) []
+ fn main() fn() []
+ "#]],
+ );
}
#[test]
@@ -3016,9 +3319,7 @@ fn main() {
lc t T [local]
lc &t [type+local]
st S S []
- st &S [type]
st T T []
- st &T [type]
md core:: []
fn foo(…) fn(&S) []
fn main() fn() []
@@ -3065,9 +3366,7 @@ fn main() {
lc t T [local]
lc &mut t [type+local]
st S S []
- st &mut S [type]
st T T []
- st &mut T [type]
md core:: []
fn foo(…) fn(&mut S) []
fn main() fn() []
@@ -3131,7 +3430,6 @@ fn bar(t: &Foo) {}
ev Foo::B Foo::B []
ev &Foo::B [type]
en Foo Foo []
- en &Foo [type]
fn bar(…) fn(&Foo) []
fn foo() fn() []
"#]],
@@ -3166,9 +3464,7 @@ fn main() {
st &S [type]
ex core::ops::Deref::deref(&bar()) [type_could_unify]
st S S []
- st &S [type]
st T T []
- st &T [type]
fn bar() fn() -> T []
fn &bar() [type]
md core:: []
@@ -3499,6 +3795,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -3594,6 +3891,7 @@ fn foo() {
Exact,
),
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -3648,6 +3946,7 @@ fn main() {
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: None,
is_name_already_imported: false,
requires_import: false,
@@ -3690,14 +3989,14 @@ fn foo() {
}
"#,
expect![[r#"
- ev Foo::B Foo::B [type_could_unify]
- ev Foo::A(…) Foo::A(T) [type_could_unify]
lc foo Foo<u32> [type+local]
ex Foo::B [type]
ex foo [type]
- en Foo Foo<{unknown}> [type_could_unify]
+ ev Foo::B Foo::B [type_could_unify]
+ ev Foo::A(…) Foo::A(T) [type_could_unify]
+ en Foo Foo<T> [type_could_unify]
+ fn baz() fn() -> Foo<T> [type_could_unify]
fn bar() fn() -> Foo<u8> []
- fn baz() fn() -> Foo<T> []
fn foo() fn() []
"#]],
);
@@ -3727,6 +4026,7 @@ fn main() {
&[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
expect![[r#"
sn not !expr [snippet]
+ me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import]
sn box Box::new(expr) []
sn call function(expr) []
sn const const {} []
@@ -3740,7 +4040,6 @@ fn main() {
sn return return expr []
sn unsafe unsafe {} []
sn while while expr {} []
- me not() fn(self) -> <Self as Not>::Output [requires_import]
"#]],
);
}
@@ -3791,7 +4090,7 @@ enum Foo {
en Foo Foo []
st Other Other []
sp Self Foo []
- st Vec<…> Vec<{unknown}> []
+ st Vec<…> Vec<T> []
"#]],
);
}
@@ -4140,6 +4439,7 @@ fn main() {
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: Some(
CompletionRelevanceTraitInfo {
notable_trait: true,
@@ -4176,6 +4476,7 @@ fn main() {
exact_name_match: false,
type_match: None,
is_local: false,
+ is_missing: false,
trait_: Some(
CompletionRelevanceTraitInfo {
notable_trait: true,