11173: Allow adding partially resolved types r=Veykril a=SomeoneToIgnore

Sometimes when writing something like `let foo = Arc::new(Mutex::new(CrazyGenerics::new(HashMap::new())))`, I want/have to specify an explicit type for the expression.
Using turbofish isn't very readable and not always appreciated by guidelines, so `let foo: T` has to be filled.

To ease that, the PR enables the `add_explicit_type` assist on types that contain unknown types and some generics.
Fully unresolved types, arrays with unknown types and other known cases behave the same.

`_` placeholder was chosen to replace an unknown type:

```rust
let foo = HashMap::new();
// after assist usage, turns into
let foo: HashMap<_, _> = HashMap::new();
```

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
bors[bot] 2022-01-03 00:40:30 +00:00 committed by GitHub
commit d89a4f0e93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 4 deletions

View file

@ -567,7 +567,27 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
};
if !parameters_to_write.is_empty() {
write!(f, "<")?;
f.write_joined(parameters_to_write, ", ")?;
if f.display_target.is_source_code() {
let mut first = true;
for generic_arg in parameters_to_write {
if !first {
write!(f, ", ")?;
}
first = false;
if generic_arg.ty(Interner).map(|ty| ty.kind(Interner))
== Some(&TyKind::Error)
{
write!(f, "_")?;
} else {
generic_arg.hir_fmt(f)?;
}
}
} else {
f.write_joined(parameters_to_write, ", ")?;
}
write!(f, ">")?;
}
}

View file

@ -60,8 +60,8 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
}
.adjusted();
// Unresolved or unnameable types can't be annotated
if ty.contains_unknown() || ty.is_closure() {
// Fully unresolved or unnameable types can't be annotated
if (ty.contains_unknown() && ty.type_arguments().count() == 0) || ty.is_closure() {
cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
return None;
}
@ -139,11 +139,34 @@ fn add_explicit_type_macro_call_expr() {
}
#[test]
fn add_explicit_type_not_applicable_unresolved() {
fn add_explicit_type_not_applicable_for_fully_unresolved() {
cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred);
check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#);
}
#[test]
fn add_explicit_type_applicable_for_partially_unresolved() {
check_assist(
add_explicit_type,
r#"
struct Vec<T, V> { t: T, v: V }
impl<T> Vec<T, Vec<ZZZ, i32>> {
fn new() -> Self {
panic!()
}
}
fn f() { let a$0 = Vec::new(); }"#,
r#"
struct Vec<T, V> { t: T, v: V }
impl<T> Vec<T, Vec<ZZZ, i32>> {
fn new() -> Self {
panic!()
}
}
fn f() { let a: Vec<_, Vec<_, i32>> = Vec::new(); }"#,
);
}
#[test]
fn add_explicit_type_not_applicable_closure_expr() {
check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = || {}; }"#);