Skip to content

Commit 595d9e6

Browse files
committed
fix: don't use control flow when extracted fn contains tail expr of original fn
1 parent 2f6d545 commit 595d9e6

File tree

1 file changed

+57
-62
lines changed

1 file changed

+57
-62
lines changed

crates/ide-assists/src/handlers/extract_function.rs

+57-62
Original file line numberDiff line numberDiff line change
@@ -1385,31 +1385,30 @@ enum FlowHandler {
13851385

13861386
impl FlowHandler {
13871387
fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
1388-
match &fun.control_flow.kind {
1389-
None => FlowHandler::None,
1390-
Some(flow_kind) => {
1391-
let action = flow_kind.clone();
1392-
if let FunType::Unit = ret_ty {
1393-
match flow_kind {
1394-
FlowKind::Return(None)
1395-
| FlowKind::Break(_, None)
1396-
| FlowKind::Continue(_) => FlowHandler::If { action },
1397-
FlowKind::Return(_) | FlowKind::Break(_, _) => {
1398-
FlowHandler::IfOption { action }
1399-
}
1400-
FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1401-
}
1402-
} else {
1403-
match flow_kind {
1404-
FlowKind::Return(None)
1405-
| FlowKind::Break(_, None)
1406-
| FlowKind::Continue(_) => FlowHandler::MatchOption { none: action },
1407-
FlowKind::Return(_) | FlowKind::Break(_, _) => {
1408-
FlowHandler::MatchResult { err: action }
1409-
}
1410-
FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1411-
}
1388+
if fun.contains_tail_expr {
1389+
return FlowHandler::None;
1390+
}
1391+
let Some(action) = fun.control_flow.kind.clone() else {
1392+
return FlowHandler::None;
1393+
};
1394+
1395+
if let FunType::Unit = ret_ty {
1396+
match action {
1397+
FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
1398+
FlowHandler::If { action }
1399+
}
1400+
FlowKind::Return(_) | FlowKind::Break(_, _) => FlowHandler::IfOption { action },
1401+
FlowKind::Try { kind } => FlowHandler::Try { kind },
1402+
}
1403+
} else {
1404+
match action {
1405+
FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
1406+
FlowHandler::MatchOption { none: action }
1407+
}
1408+
FlowKind::Return(_) | FlowKind::Break(_, _) => {
1409+
FlowHandler::MatchResult { err: action }
14121410
}
1411+
FlowKind::Try { kind } => FlowHandler::Try { kind },
14131412
}
14141413
}
14151414
}
@@ -1654,11 +1653,7 @@ impl Function {
16541653

16551654
fn make_ret_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> Option<ast::RetType> {
16561655
let fun_ty = self.return_type(ctx);
1657-
let handler = if self.contains_tail_expr {
1658-
FlowHandler::None
1659-
} else {
1660-
FlowHandler::from_ret_ty(self, &fun_ty)
1661-
};
1656+
let handler = FlowHandler::from_ret_ty(self, &fun_ty);
16621657
let ret_ty = match &handler {
16631658
FlowHandler::None => {
16641659
if matches!(fun_ty, FunType::Unit) {
@@ -1728,11 +1723,7 @@ fn make_body(
17281723
fun: &Function,
17291724
) -> ast::BlockExpr {
17301725
let ret_ty = fun.return_type(ctx);
1731-
let handler = if fun.contains_tail_expr {
1732-
FlowHandler::None
1733-
} else {
1734-
FlowHandler::from_ret_ty(fun, &ret_ty)
1735-
};
1726+
let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
17361727

17371728
let block = match &fun.body {
17381729
FunctionBody::Expr(expr) => {
@@ -4471,7 +4462,7 @@ async fn foo() -> Result<(), ()> {
44714462
"#,
44724463
r#"
44734464
async fn foo() -> Result<(), ()> {
4474-
fun_name().await?
4465+
fun_name().await
44754466
}
44764467
44774468
async fn $0fun_name() -> Result<(), ()> {
@@ -4690,15 +4681,15 @@ fn $0fun_name() {
46904681
check_assist(
46914682
extract_function,
46924683
r#"
4693-
//- minicore: result
4684+
//- minicore: result, try
46944685
fn foo() -> Result<(), i64> {
46954686
$0Result::<i32, i64>::Ok(0)?;
46964687
Ok(())$0
46974688
}
46984689
"#,
46994690
r#"
47004691
fn foo() -> Result<(), i64> {
4701-
fun_name()?
4692+
fun_name()
47024693
}
47034694
47044695
fn $0fun_name() -> Result<(), i64> {
@@ -5753,6 +5744,34 @@ fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
57535744
);
57545745
}
57555746

5747+
#[test]
5748+
fn tail_expr_no_extra_control_flow() {
5749+
check_assist(
5750+
extract_function,
5751+
r#"
5752+
//- minicore: result
5753+
fn fallible() -> Result<(), ()> {
5754+
$0if true {
5755+
return Err(());
5756+
}
5757+
Ok(())$0
5758+
}
5759+
"#,
5760+
r#"
5761+
fn fallible() -> Result<(), ()> {
5762+
fun_name()
5763+
}
5764+
5765+
fn $0fun_name() -> Result<(), ()> {
5766+
if true {
5767+
return Err(());
5768+
}
5769+
Ok(())
5770+
}
5771+
"#,
5772+
);
5773+
}
5774+
57565775
#[test]
57575776
fn non_tail_expr_of_tail_expr_loop() {
57585777
check_assist(
@@ -5800,12 +5819,6 @@ fn $0fun_name() -> ControlFlow<()> {
58005819
extract_function,
58015820
r#"
58025821
//- minicore: option, try
5803-
impl<T> core::ops::Try for Option<T> {
5804-
type Output = T;
5805-
type Residual = Option<!>;
5806-
}
5807-
impl<T> core::ops::FromResidual for Option<T> {}
5808-
58095822
fn f() -> Option<()> {
58105823
if true {
58115824
let a = $0if true {
@@ -5820,12 +5833,6 @@ fn f() -> Option<()> {
58205833
}
58215834
"#,
58225835
r#"
5823-
impl<T> core::ops::Try for Option<T> {
5824-
type Output = T;
5825-
type Residual = Option<!>;
5826-
}
5827-
impl<T> core::ops::FromResidual for Option<T> {}
5828-
58295836
fn f() -> Option<()> {
58305837
if true {
58315838
let a = fun_name()?;;
@@ -5852,12 +5859,6 @@ fn $0fun_name() -> Option<()> {
58525859
extract_function,
58535860
r#"
58545861
//- minicore: option, try
5855-
impl<T> core::ops::Try for Option<T> {
5856-
type Output = T;
5857-
type Residual = Option<!>;
5858-
}
5859-
impl<T> core::ops::FromResidual for Option<T> {}
5860-
58615862
fn f() -> Option<()> {
58625863
if true {
58635864
$0{
@@ -5874,15 +5875,9 @@ fn f() -> Option<()> {
58745875
}
58755876
"#,
58765877
r#"
5877-
impl<T> core::ops::Try for Option<T> {
5878-
type Output = T;
5879-
type Residual = Option<!>;
5880-
}
5881-
impl<T> core::ops::FromResidual for Option<T> {}
5882-
58835878
fn f() -> Option<()> {
58845879
if true {
5885-
fun_name()?
5880+
fun_name()
58865881
} else {
58875882
None
58885883
}

0 commit comments

Comments
 (0)