diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 192403b15d..1e21050911 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs @@ -1319,7 +1319,7 @@ impl Function { .type_arguments() .nth(1) .map(|ty| make_ty(&ty, ctx, module)) - .unwrap_or_else(make::ty_unit); + .unwrap_or_else(make::ty_placeholder); make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty) } FlowHandler::If { .. } => make::ext::ty_bool(), @@ -1327,7 +1327,7 @@ impl Function { let handler_ty = action .expr_ty(ctx) .map(|ty| make_ty(&ty, ctx, module)) - .unwrap_or_else(make::ty_unit); + .unwrap_or_else(make::ty_placeholder); make::ext::ty_option(handler_ty) } FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)), @@ -1335,7 +1335,7 @@ impl Function { let handler_ty = err .expr_ty(ctx) .map(|ty| make_ty(&ty, ctx, module)) - .unwrap_or_else(make::ty_unit); + .unwrap_or_else(make::ty_placeholder); make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty) } }; @@ -1501,7 +1501,7 @@ fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr } fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String { - ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "()".to_string()) + ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string()) } fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type { @@ -4191,6 +4191,29 @@ fn main() { fn $0fun_name(bar: &str) { m!(bar); } +"#, + ); + } + + #[test] + fn unresolveable_types_default_to_placeholder() { + check_assist( + extract_function, + r#" +fn foo() { + let a = __unresolved; + let _ = $0{a}$0; +} +"#, + r#" +fn foo() { + let a = __unresolved; + let _ = fun_name(a); +} + +fn $0fun_name(a: _) -> _ { + a +} "#, ); } diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs index ad98aa16d8..8feae78126 100644 --- a/crates/ide_assists/src/handlers/generate_function.rs +++ b/crates/ide_assists/src/handlers/generate_function.rs @@ -37,7 +37,7 @@ use crate::{ // bar("", baz()); // } // -// fn bar(arg: &str, baz: Baz) ${0:-> ()} { +// fn bar(arg: &str, baz: Baz) ${0:-> _} { // todo!() // } // @@ -342,7 +342,7 @@ impl FunctionBuilder { } /// Makes an optional return type along with whether the return type should be focused by the cursor. -/// If we cannot infer what the return type should be, we create unit as a placeholder. +/// If we cannot infer what the return type should be, we create a placeholder type. /// /// The rule for whether we focus a return type or not (and thus focus the function body), /// is rather simple: @@ -357,14 +357,14 @@ fn make_return_type( ) -> (Option, bool) { let (ret_ty, should_focus_return_type) = { match ctx.sema.type_of_expr(call).map(TypeInfo::original) { - Some(ty) if ty.is_unknown() => (Some(make::ty_unit()), true), - None => (Some(make::ty_unit()), true), + Some(ty) if ty.is_unknown() => (Some(make::ty_placeholder()), true), + None => (Some(make::ty_placeholder()), true), Some(ty) if ty.is_unit() => (None, false), Some(ty) => { let rendered = ty.display_source_code(ctx.db(), target_module.into()); match rendered { Ok(rendered) => (Some(make::ty(&rendered)), false), - Err(_) => (Some(make::ty_unit()), true), + Err(_) => (Some(make::ty_placeholder()), true), } } } @@ -458,7 +458,7 @@ fn fn_args( ty } } - None => String::from("()"), + None => String::from("_"), }); } deduplicate_arg_names(&mut arg_names); @@ -639,7 +639,7 @@ fn foo() { bar(); } -fn bar() ${0:-> ()} { +fn bar() ${0:-> _} { todo!() } ", @@ -666,7 +666,7 @@ impl Foo { } } -fn bar() ${0:-> ()} { +fn bar() ${0:-> _} { todo!() } ", @@ -690,7 +690,7 @@ fn foo1() { bar(); } -fn bar() ${0:-> ()} { +fn bar() ${0:-> _} { todo!() } @@ -716,7 +716,7 @@ mod baz { bar(); } - fn bar() ${0:-> ()} { + fn bar() ${0:-> _} { todo!() } } @@ -740,7 +740,7 @@ fn foo() { bar(BazBaz); } -fn bar(baz_baz: BazBaz) ${0:-> ()} { +fn bar(baz_baz: BazBaz) ${0:-> _} { todo!() } ", @@ -763,7 +763,7 @@ fn foo() { bar(&BazBaz as *const BazBaz); } -fn bar(baz_baz: *const BazBaz) ${0:-> ()} { +fn bar(baz_baz: *const BazBaz) ${0:-> _} { todo!() } ", @@ -788,7 +788,7 @@ fn foo() { bar(baz()); } -fn bar(baz: Baz) ${0:-> ()} { +fn bar(baz: Baz) ${0:-> _} { todo!() } ", @@ -1091,7 +1091,7 @@ fn foo() { bar(Baz::new); } -fn bar(new: fn) ${0:-> ()} { +fn bar(new: fn) ${0:-> _} { todo!() } ", @@ -1115,7 +1115,7 @@ fn foo() { bar(closure) } -fn bar(closure: ()) { +fn bar(closure: _) { ${0:todo!()} } ", @@ -1123,7 +1123,7 @@ fn bar(closure: ()) { } #[test] - fn unresolveable_types_default_to_unit() { + fn unresolveable_types_default_to_placeholder() { check_assist( generate_function, r" @@ -1136,7 +1136,7 @@ fn foo() { bar(baz) } -fn bar(baz: ()) { +fn bar(baz: _) { ${0:todo!()} } ", @@ -1400,7 +1400,7 @@ impl Foo { self.bar(); } - fn bar(&self) ${0:-> ()} { + fn bar(&self) ${0:-> _} { todo!() } } @@ -1422,7 +1422,7 @@ fn foo() { bar(42).await(); } -async fn bar(arg: i32) ${0:-> ()} { +async fn bar(arg: i32) ${0:-> _} { todo!() } ", @@ -1443,7 +1443,7 @@ fn foo() {S.bar();} impl S { -fn bar(&self) ${0:-> ()} { +fn bar(&self) ${0:-> _} { todo!() } } @@ -1465,7 +1465,7 @@ impl S {} struct S; fn foo() {S.bar();} impl S { - fn bar(&self) ${0:-> ()} { + fn bar(&self) ${0:-> _} { todo!() } } @@ -1490,7 +1490,7 @@ mod s { impl S { - pub(crate) fn bar(&self) ${0:-> ()} { + pub(crate) fn bar(&self) ${0:-> _} { todo!() } } @@ -1523,7 +1523,7 @@ mod s { impl S { -fn bar(&self) ${0:-> ()} { +fn bar(&self) ${0:-> _} { todo!() } } @@ -1546,7 +1546,7 @@ fn foo() {S.bar();} impl S { -fn bar(&self) ${0:-> ()} { +fn bar(&self) ${0:-> _} { todo!() } } @@ -1568,7 +1568,7 @@ fn foo() {S::bar();} impl S { -fn bar() ${0:-> ()} { +fn bar() ${0:-> _} { todo!() } } @@ -1590,7 +1590,7 @@ impl S {} struct S; fn foo() {S::bar();} impl S { - fn bar() ${0:-> ()} { + fn bar() ${0:-> _} { todo!() } } @@ -1615,7 +1615,7 @@ mod s { impl S { - pub(crate) fn bar() ${0:-> ()} { + pub(crate) fn bar() ${0:-> _} { todo!() } } @@ -1639,7 +1639,7 @@ fn foo() {S::bar();} impl S { -fn bar() ${0:-> ()} { +fn bar() ${0:-> _} { todo!() } } diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 28f74321da..39ab8c7b74 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs @@ -819,7 +819,7 @@ fn foo() { bar("", baz()); } -fn bar(arg: &str, baz: Baz) ${0:-> ()} { +fn bar(arg: &str, baz: Baz) ${0:-> _} { todo!() } diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 5494dd1d3e..93eca19c30 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -95,6 +95,9 @@ pub fn lifetime(text: &str) -> ast::Lifetime { pub fn ty(text: &str) -> ast::Type { ty_from_text(text) } +pub fn ty_placeholder() -> ast::Type { + ty_from_text("_") +} pub fn ty_unit() -> ast::Type { ty_from_text("()") }