9500: internal: Only inline closure, literal and local arguments when used once r=Veykril a=Veykril

See https://github.com/rust-analyzer/rust-analyzer/pull/9474#discussion_r663881507 for reasoning.

This still inlines single use closures and literals as naming these is usually not as useful. Prime examples being the Option/Result consuming functions like `map_or` etc.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-07-06 16:20:54 +00:00 committed by GitHub
commit 112e53f10e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -157,25 +157,28 @@ pub(crate) fn inline_(
// Inline parameter expressions or generate `let` statements depending on whether inlining works or not. // Inline parameter expressions or generate `let` statements depending on whether inlining works or not.
for ((pat, _), usages, expr) in izip!(params, param_use_nodes, arg_list).rev() { for ((pat, _), usages, expr) in izip!(params, param_use_nodes, arg_list).rev() {
let expr_is_name_ref = matches!(&expr,
ast::Expr::PathExpr(expr)
if expr.path().and_then(|path| path.as_single_name_ref()).is_some()
);
match &*usages { match &*usages {
// inline single use parameters // inline single use closure arguments
[usage] => { [usage]
let expr = if matches!(expr, ast::Expr::ClosureExpr(_)) if matches!(expr, ast::Expr::ClosureExpr(_))
&& usage.syntax().parent().and_then(ast::Expr::cast).is_some() && usage.syntax().parent().and_then(ast::Expr::cast).is_some() =>
{ {
make::expr_paren(expr) cov_mark::hit!(inline_call_inline_closure);
} else { let expr = make::expr_paren(expr);
expr
};
ted::replace(usage.syntax(), expr.syntax().clone_for_update()); ted::replace(usage.syntax(), expr.syntax().clone_for_update());
} }
// inline parameters whose expression is a simple local reference // inline single use literals
[_, ..] [usage] if matches!(expr, ast::Expr::Literal(_)) => {
if matches!(&expr, cov_mark::hit!(inline_call_inline_literal);
ast::Expr::PathExpr(expr) ted::replace(usage.syntax(), expr.syntax().clone_for_update());
if expr.path().and_then(|path| path.as_single_name_ref()).is_some() }
) => // inline direct local arguments
{ [_, ..] if expr_is_name_ref => {
cov_mark::hit!(inline_call_inline_locals);
usages.into_iter().for_each(|usage| { usages.into_iter().for_each(|usage| {
ted::replace(usage.syntax(), &expr.syntax().clone_for_update()); ted::replace(usage.syntax(), &expr.syntax().clone_for_update());
}); });
@ -322,7 +325,10 @@ impl Foo {
} }
fn main() { fn main() {
let x = Foo(Foo(3).0 + 2); let x = {
let this = Foo(3);
Foo(this.0 + 2)
};
} }
"#, "#,
); );
@ -355,7 +361,10 @@ impl Foo {
} }
fn main() { fn main() {
let x = Foo(Foo(3).0 + 2); let x = {
let this = Foo(3);
Foo(this.0 + 2)
};
} }
"#, "#,
); );
@ -435,31 +444,6 @@ fn main() {
); );
} }
#[test]
fn function_single_use_expr_in_param() {
check_assist(
inline_call,
r#"
fn double(x: u32) -> u32 {
2 * x
}
fn main() {
let x = 51;
let x = double$0(10 + x);
}
"#,
r#"
fn double(x: u32) -> u32 {
2 * x
}
fn main() {
let x = 51;
let x = 2 * 10 + x;
}
"#,
);
}
#[test] #[test]
fn function_multi_use_expr_in_param() { fn function_multi_use_expr_in_param() {
check_assist( check_assist(
@ -489,7 +473,8 @@ fn main() {
} }
#[test] #[test]
fn function_multi_use_local_in_param() { fn function_use_local_in_param() {
cov_mark::check!(inline_call_inline_locals);
check_assist( check_assist(
inline_call, inline_call,
r#" r#"
@ -550,6 +535,7 @@ impl Foo {
#[test] #[test]
fn wraps_closure_in_paren() { fn wraps_closure_in_paren() {
cov_mark::check!(inline_call_inline_closure);
check_assist( check_assist(
inline_call, inline_call,
r#" r#"
@ -594,6 +580,32 @@ fn main() {
main(); main();
} }
} }
"#,
);
}
#[test]
fn inline_single_literal_expr() {
cov_mark::check!(inline_call_inline_literal);
check_assist(
inline_call,
r#"
fn foo(x: u32) -> u32{
x
}
fn main() {
foo$0(222);
}
"#,
r#"
fn foo(x: u32) -> u32{
x
}
fn main() {
222;
}
"#, "#,
); );
} }