]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/extract_function.rs
Merge #7994
[rust.git] / crates / ide_assists / src / handlers / extract_function.rs
1 use std::iter;
2
3 use ast::make;
4 use either::Either;
5 use hir::{HirDisplay, Local};
6 use ide_db::{
7     defs::{Definition, NameRefClass},
8     search::{FileReference, ReferenceAccess, SearchScope},
9 };
10 use itertools::Itertools;
11 use stdx::format_to;
12 use syntax::{
13     algo::SyntaxRewriter,
14     ast::{
15         self,
16         edit::{AstNodeEdit, IndentLevel},
17         AstNode,
18     },
19     SyntaxElement,
20     SyntaxKind::{self, BLOCK_EXPR, BREAK_EXPR, COMMENT, PATH_EXPR, RETURN_EXPR},
21     SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T,
22 };
23
24 use crate::{
25     assist_context::{AssistContext, Assists},
26     AssistId,
27 };
28
29 // Assist: extract_function
30 //
31 // Extracts selected statements into new function.
32 //
33 // ```
34 // fn main() {
35 //     let n = 1;
36 //     $0let m = n + 2;
37 //     let k = m + n;$0
38 //     let g = 3;
39 // }
40 // ```
41 // ->
42 // ```
43 // fn main() {
44 //     let n = 1;
45 //     fun_name(n);
46 //     let g = 3;
47 // }
48 //
49 // fn $0fun_name(n: i32) {
50 //     let m = n + 2;
51 //     let k = m + n;
52 // }
53 // ```
54 pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
55     if ctx.frange.range.is_empty() {
56         return None;
57     }
58
59     let node = ctx.covering_element();
60     if node.kind() == COMMENT {
61         cov_mark::hit!(extract_function_in_comment_is_not_applicable);
62         return None;
63     }
64
65     let node = element_to_node(node);
66
67     let body = extraction_target(&node, ctx.frange.range)?;
68
69     let vars_used_in_body = vars_used_in_body(ctx, &body);
70     let self_param = self_param_from_usages(ctx, &body, &vars_used_in_body);
71
72     let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding };
73     let insert_after = scope_for_fn_insertion(&body, anchor)?;
74     let module = ctx.sema.scope(&insert_after).module()?;
75
76     let vars_defined_in_body_and_outlive = vars_defined_in_body_and_outlive(ctx, &body);
77     let ret_ty = body_return_ty(ctx, &body)?;
78
79     // FIXME: we compute variables that outlive here just to check `never!` condition
80     //        this requires traversing whole `body` (cheap) and finding all references (expensive)
81     //        maybe we can move this check to `edit` closure somehow?
82     if stdx::never!(!vars_defined_in_body_and_outlive.is_empty() && !ret_ty.is_unit()) {
83         // We should not have variables that outlive body if we have expression block
84         return None;
85     }
86     let control_flow = external_control_flow(ctx, &body)?;
87
88     let target_range = body.text_range();
89
90     acc.add(
91         AssistId("extract_function", crate::AssistKind::RefactorExtract),
92         "Extract into function",
93         target_range,
94         move |builder| {
95             let params = extracted_function_params(ctx, &body, &vars_used_in_body);
96
97             let fun = Function {
98                 name: "fun_name".to_string(),
99                 self_param: self_param.map(|(_, pat)| pat),
100                 params,
101                 control_flow,
102                 ret_ty,
103                 body,
104                 vars_defined_in_body_and_outlive,
105             };
106
107             let new_indent = IndentLevel::from_node(&insert_after);
108             let old_indent = fun.body.indent_level();
109
110             builder.replace(target_range, format_replacement(ctx, &fun, old_indent));
111
112             let fn_def = format_function(ctx, module, &fun, old_indent, new_indent);
113             let insert_offset = insert_after.text_range().end();
114             match ctx.config.snippet_cap {
115                 Some(cap) => builder.insert_snippet(cap, insert_offset, fn_def),
116                 None => builder.insert(insert_offset, fn_def),
117             }
118         },
119     )
120 }
121
122 fn external_control_flow(ctx: &AssistContext, body: &FunctionBody) -> Option<ControlFlow> {
123     let mut ret_expr = None;
124     let mut try_expr = None;
125     let mut break_expr = None;
126     let mut continue_expr = None;
127     let (syntax, text_range) = match body {
128         FunctionBody::Expr(expr) => (expr.syntax(), expr.syntax().text_range()),
129         FunctionBody::Span { parent, text_range } => (parent.syntax(), *text_range),
130     };
131
132     let mut nested_loop = None;
133     let mut nested_scope = None;
134
135     for e in syntax.preorder() {
136         let e = match e {
137             WalkEvent::Enter(e) => e,
138             WalkEvent::Leave(e) => {
139                 if nested_loop.as_ref() == Some(&e) {
140                     nested_loop = None;
141                 }
142                 if nested_scope.as_ref() == Some(&e) {
143                     nested_scope = None;
144                 }
145                 continue;
146             }
147         };
148         if nested_scope.is_some() {
149             continue;
150         }
151         if !text_range.contains_range(e.text_range()) {
152             continue;
153         }
154         match e.kind() {
155             SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
156                 if nested_loop.is_none() {
157                     nested_loop = Some(e);
158                 }
159             }
160             SyntaxKind::FN
161             | SyntaxKind::CONST
162             | SyntaxKind::STATIC
163             | SyntaxKind::IMPL
164             | SyntaxKind::MODULE => {
165                 if nested_scope.is_none() {
166                     nested_scope = Some(e);
167                 }
168             }
169             SyntaxKind::RETURN_EXPR => {
170                 ret_expr = Some(ast::ReturnExpr::cast(e).unwrap());
171             }
172             SyntaxKind::TRY_EXPR => {
173                 try_expr = Some(ast::TryExpr::cast(e).unwrap());
174             }
175             SyntaxKind::BREAK_EXPR if nested_loop.is_none() => {
176                 break_expr = Some(ast::BreakExpr::cast(e).unwrap());
177             }
178             SyntaxKind::CONTINUE_EXPR if nested_loop.is_none() => {
179                 continue_expr = Some(ast::ContinueExpr::cast(e).unwrap());
180             }
181             _ => {}
182         }
183     }
184
185     let kind = match (try_expr, ret_expr, break_expr, continue_expr) {
186         (Some(e), None, None, None) => {
187             let func = e.syntax().ancestors().find_map(ast::Fn::cast)?;
188             let def = ctx.sema.to_def(&func)?;
189             let ret_ty = def.ret_type(ctx.db());
190             let kind = try_kind_of_ty(ret_ty, ctx)?;
191
192             Some(FlowKind::Try { kind })
193         }
194         (Some(_), Some(r), None, None) => match r.expr() {
195             Some(expr) => {
196                 if let Some(kind) = expr_err_kind(&expr, ctx) {
197                     Some(FlowKind::TryReturn { expr, kind })
198                 } else {
199                     cov_mark::hit!(external_control_flow_try_and_return_non_err);
200                     return None;
201                 }
202             }
203             None => return None,
204         },
205         (Some(_), _, _, _) => {
206             cov_mark::hit!(external_control_flow_try_and_bc);
207             return None;
208         }
209         (None, Some(r), None, None) => match r.expr() {
210             Some(expr) => Some(FlowKind::ReturnValue(expr)),
211             None => Some(FlowKind::Return),
212         },
213         (None, Some(_), _, _) => {
214             cov_mark::hit!(external_control_flow_return_and_bc);
215             return None;
216         }
217         (None, None, Some(_), Some(_)) => {
218             cov_mark::hit!(external_control_flow_break_and_continue);
219             return None;
220         }
221         (None, None, Some(b), None) => match b.expr() {
222             Some(expr) => Some(FlowKind::BreakValue(expr)),
223             None => Some(FlowKind::Break),
224         },
225         (None, None, None, Some(_)) => Some(FlowKind::Continue),
226         (None, None, None, None) => None,
227     };
228
229     Some(ControlFlow { kind })
230 }
231
232 /// Checks is expr is `Err(_)` or `None`
233 fn expr_err_kind(expr: &ast::Expr, ctx: &AssistContext) -> Option<TryKind> {
234     let func_name = match expr {
235         ast::Expr::CallExpr(call_expr) => call_expr.expr()?,
236         ast::Expr::PathExpr(_) => expr.clone(),
237         _ => return None,
238     };
239     let text = func_name.syntax().text();
240
241     if text == "Err" {
242         Some(TryKind::Result { ty: ctx.sema.type_of_expr(expr)? })
243     } else if text == "None" {
244         Some(TryKind::Option)
245     } else {
246         None
247     }
248 }
249
250 #[derive(Debug)]
251 struct Function {
252     name: String,
253     self_param: Option<ast::SelfParam>,
254     params: Vec<Param>,
255     control_flow: ControlFlow,
256     ret_ty: RetType,
257     body: FunctionBody,
258     vars_defined_in_body_and_outlive: Vec<Local>,
259 }
260
261 #[derive(Debug)]
262 struct Param {
263     var: Local,
264     ty: hir::Type,
265     has_usages_afterwards: bool,
266     has_mut_inside_body: bool,
267     is_copy: bool,
268 }
269
270 #[derive(Debug)]
271 struct ControlFlow {
272     kind: Option<FlowKind>,
273 }
274
275 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
276 enum ParamKind {
277     Value,
278     MutValue,
279     SharedRef,
280     MutRef,
281 }
282
283 #[derive(Debug, Eq, PartialEq)]
284 enum FunType {
285     Unit,
286     Single(hir::Type),
287     Tuple(Vec<hir::Type>),
288 }
289
290 impl Function {
291     fn return_type(&self, ctx: &AssistContext) -> FunType {
292         match &self.ret_ty {
293             RetType::Expr(ty) if ty.is_unit() => FunType::Unit,
294             RetType::Expr(ty) => FunType::Single(ty.clone()),
295             RetType::Stmt => match self.vars_defined_in_body_and_outlive.as_slice() {
296                 [] => FunType::Unit,
297                 [var] => FunType::Single(var.ty(ctx.db())),
298                 vars => {
299                     let types = vars.iter().map(|v| v.ty(ctx.db())).collect();
300                     FunType::Tuple(types)
301                 }
302             },
303         }
304     }
305 }
306
307 impl ParamKind {
308     fn is_ref(&self) -> bool {
309         matches!(self, ParamKind::SharedRef | ParamKind::MutRef)
310     }
311 }
312
313 impl Param {
314     fn kind(&self) -> ParamKind {
315         match (self.has_usages_afterwards, self.has_mut_inside_body, self.is_copy) {
316             (true, true, _) => ParamKind::MutRef,
317             (true, false, false) => ParamKind::SharedRef,
318             (false, true, _) => ParamKind::MutValue,
319             (true, false, true) | (false, false, _) => ParamKind::Value,
320         }
321     }
322
323     fn to_arg(&self, ctx: &AssistContext) -> ast::Expr {
324         let var = path_expr_from_local(ctx, self.var);
325         match self.kind() {
326             ParamKind::Value | ParamKind::MutValue => var,
327             ParamKind::SharedRef => make::expr_ref(var, false),
328             ParamKind::MutRef => make::expr_ref(var, true),
329         }
330     }
331
332     fn to_param(&self, ctx: &AssistContext, module: hir::Module) -> ast::Param {
333         let var = self.var.name(ctx.db()).unwrap().to_string();
334         let var_name = make::name(&var);
335         let pat = match self.kind() {
336             ParamKind::MutValue => make::ident_mut_pat(var_name),
337             ParamKind::Value | ParamKind::SharedRef | ParamKind::MutRef => {
338                 make::ident_pat(var_name)
339             }
340         };
341
342         let ty = make_ty(&self.ty, ctx, module);
343         let ty = match self.kind() {
344             ParamKind::Value | ParamKind::MutValue => ty,
345             ParamKind::SharedRef => make::ty_ref(ty, false),
346             ParamKind::MutRef => make::ty_ref(ty, true),
347         };
348
349         make::param(pat.into(), ty)
350     }
351 }
352
353 /// Control flow that is exported from extracted function
354 ///
355 /// E.g.:
356 /// ```rust,no_run
357 /// loop {
358 ///     $0
359 ///     if 42 == 42 {
360 ///         break;
361 ///     }
362 ///     $0
363 /// }
364 /// ```
365 #[derive(Debug, Clone)]
366 enum FlowKind {
367     /// Return without value (`return;`)
368     Return,
369     /// Return with value (`return $expr;`)
370     ReturnValue(ast::Expr),
371     Try {
372         kind: TryKind,
373     },
374     TryReturn {
375         expr: ast::Expr,
376         kind: TryKind,
377     },
378     /// Break without value (`return;`)
379     Break,
380     /// Break with value (`break $expr;`)
381     BreakValue(ast::Expr),
382     /// Continue
383     Continue,
384 }
385
386 #[derive(Debug, Clone)]
387 enum TryKind {
388     Option,
389     Result { ty: hir::Type },
390 }
391
392 impl FlowKind {
393     fn make_result_handler(&self, expr: Option<ast::Expr>) -> ast::Expr {
394         match self {
395             FlowKind::Return | FlowKind::ReturnValue(_) => make::expr_return(expr),
396             FlowKind::Break | FlowKind::BreakValue(_) => make::expr_break(expr),
397             FlowKind::Try { .. } | FlowKind::TryReturn { .. } => {
398                 stdx::never!("cannot have result handler with try");
399                 expr.unwrap_or_else(|| make::expr_return(None))
400             }
401             FlowKind::Continue => {
402                 stdx::always!(expr.is_none(), "continue with value is not possible");
403                 make::expr_continue()
404             }
405         }
406     }
407
408     fn expr_ty(&self, ctx: &AssistContext) -> Option<hir::Type> {
409         match self {
410             FlowKind::ReturnValue(expr)
411             | FlowKind::BreakValue(expr)
412             | FlowKind::TryReturn { expr, .. } => ctx.sema.type_of_expr(expr),
413             FlowKind::Try { .. } => {
414                 stdx::never!("try does not have defined expr_ty");
415                 None
416             }
417             FlowKind::Return | FlowKind::Break | FlowKind::Continue => None,
418         }
419     }
420 }
421
422 fn try_kind_of_ty(ty: hir::Type, ctx: &AssistContext) -> Option<TryKind> {
423     if ty.is_unknown() {
424         // We favour Result for `expr?`
425         return Some(TryKind::Result { ty });
426     }
427     let adt = ty.as_adt()?;
428     let name = adt.name(ctx.db());
429     // FIXME: use lang items to determine if it is std type or user defined
430     //        E.g. if user happens to define type named `Option`, we would have false positive
431     match name.to_string().as_str() {
432         "Option" => Some(TryKind::Option),
433         "Result" => Some(TryKind::Result { ty }),
434         _ => None,
435     }
436 }
437
438 #[derive(Debug)]
439 enum RetType {
440     Expr(hir::Type),
441     Stmt,
442 }
443
444 impl RetType {
445     fn is_unit(&self) -> bool {
446         match self {
447             RetType::Expr(ty) => ty.is_unit(),
448             RetType::Stmt => true,
449         }
450     }
451 }
452
453 /// Semantically same as `ast::Expr`, but preserves identity when using only part of the Block
454 #[derive(Debug)]
455 enum FunctionBody {
456     Expr(ast::Expr),
457     Span { parent: ast::BlockExpr, text_range: TextRange },
458 }
459
460 impl FunctionBody {
461     fn from_whole_node(node: SyntaxNode) -> Option<Self> {
462         match node.kind() {
463             PATH_EXPR => None,
464             BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()).map(Self::Expr),
465             RETURN_EXPR => ast::ReturnExpr::cast(node).and_then(|e| e.expr()).map(Self::Expr),
466             BLOCK_EXPR => ast::BlockExpr::cast(node)
467                 .filter(|it| it.is_standalone())
468                 .map(Into::into)
469                 .map(Self::Expr),
470             _ => ast::Expr::cast(node).map(Self::Expr),
471         }
472     }
473
474     fn from_range(node: SyntaxNode, text_range: TextRange) -> Option<FunctionBody> {
475         let block = ast::BlockExpr::cast(node)?;
476         Some(Self::Span { parent: block, text_range })
477     }
478
479     fn indent_level(&self) -> IndentLevel {
480         match &self {
481             FunctionBody::Expr(expr) => IndentLevel::from_node(expr.syntax()),
482             FunctionBody::Span { parent, .. } => IndentLevel::from_node(parent.syntax()) + 1,
483         }
484     }
485
486     fn tail_expr(&self) -> Option<ast::Expr> {
487         match &self {
488             FunctionBody::Expr(expr) => Some(expr.clone()),
489             FunctionBody::Span { parent, text_range } => {
490                 let tail_expr = parent.tail_expr()?;
491                 if text_range.contains_range(tail_expr.syntax().text_range()) {
492                     Some(tail_expr)
493                 } else {
494                     None
495                 }
496             }
497         }
498     }
499
500     fn descendants(&self) -> impl Iterator<Item = SyntaxNode> + '_ {
501         match self {
502             FunctionBody::Expr(expr) => Either::Right(expr.syntax().descendants()),
503             FunctionBody::Span { parent, text_range } => Either::Left(
504                 parent
505                     .syntax()
506                     .descendants()
507                     .filter(move |it| text_range.contains_range(it.text_range())),
508             ),
509         }
510     }
511
512     fn text_range(&self) -> TextRange {
513         match self {
514             FunctionBody::Expr(expr) => expr.syntax().text_range(),
515             FunctionBody::Span { parent: _, text_range } => *text_range,
516         }
517     }
518
519     fn contains_range(&self, range: TextRange) -> bool {
520         self.text_range().contains_range(range)
521     }
522
523     fn preceedes_range(&self, range: TextRange) -> bool {
524         self.text_range().end() <= range.start()
525     }
526
527     fn contains_node(&self, node: &SyntaxNode) -> bool {
528         self.contains_range(node.text_range())
529     }
530 }
531
532 impl HasTokenAtOffset for FunctionBody {
533     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
534         match self {
535             FunctionBody::Expr(expr) => expr.syntax().token_at_offset(offset),
536             FunctionBody::Span { parent, text_range } => {
537                 match parent.syntax().token_at_offset(offset) {
538                     TokenAtOffset::None => TokenAtOffset::None,
539                     TokenAtOffset::Single(t) => {
540                         if text_range.contains_range(t.text_range()) {
541                             TokenAtOffset::Single(t)
542                         } else {
543                             TokenAtOffset::None
544                         }
545                     }
546                     TokenAtOffset::Between(a, b) => {
547                         match (
548                             text_range.contains_range(a.text_range()),
549                             text_range.contains_range(b.text_range()),
550                         ) {
551                             (true, true) => TokenAtOffset::Between(a, b),
552                             (true, false) => TokenAtOffset::Single(a),
553                             (false, true) => TokenAtOffset::Single(b),
554                             (false, false) => TokenAtOffset::None,
555                         }
556                     }
557                 }
558             }
559         }
560     }
561 }
562
563 /// node or token's parent
564 fn element_to_node(node: SyntaxElement) -> SyntaxNode {
565     match node {
566         syntax::NodeOrToken::Node(n) => n,
567         syntax::NodeOrToken::Token(t) => t.parent(),
568     }
569 }
570
571 /// Try to guess what user wants to extract
572 ///
573 /// We have basically have two cases:
574 /// * We want whole node, like `loop {}`, `2 + 2`, `{ let n = 1; }` exprs.
575 ///   Then we can use `ast::Expr`
576 /// * We want a few statements for a block. E.g.
577 ///   ```rust,no_run
578 ///   fn foo() -> i32 {
579 ///     let m = 1;
580 ///     $0
581 ///     let n = 2;
582 ///     let k = 3;
583 ///     k + n
584 ///     $0
585 ///   }
586 ///   ```
587 ///
588 fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<FunctionBody> {
589     // we have selected exactly the expr node
590     // wrap it before anything else
591     if node.text_range() == selection_range {
592         let body = FunctionBody::from_whole_node(node.clone());
593         if body.is_some() {
594             return body;
595         }
596     }
597
598     // we have selected a few statements in a block
599     // so covering_element returns the whole block
600     if node.kind() == BLOCK_EXPR {
601         let body = FunctionBody::from_range(node.clone(), selection_range);
602         if body.is_some() {
603             return body;
604         }
605     }
606
607     // we have selected single statement
608     // `from_whole_node` failed because (let) statement is not and expression
609     // so we try to expand covering_element to parent and repeat the previous
610     if let Some(parent) = node.parent() {
611         if parent.kind() == BLOCK_EXPR {
612             let body = FunctionBody::from_range(parent, selection_range);
613             if body.is_some() {
614                 return body;
615             }
616         }
617     }
618
619     // select the closest containing expr (both ifs are used)
620     std::iter::once(node.clone()).chain(node.ancestors()).find_map(FunctionBody::from_whole_node)
621 }
622
623 /// list local variables that are referenced in `body`
624 fn vars_used_in_body(ctx: &AssistContext, body: &FunctionBody) -> Vec<Local> {
625     // FIXME: currently usages inside macros are not found
626     body.descendants()
627         .filter_map(ast::NameRef::cast)
628         .filter_map(|name_ref| NameRefClass::classify(&ctx.sema, &name_ref))
629         .map(|name_kind| name_kind.referenced(ctx.db()))
630         .filter_map(|definition| match definition {
631             Definition::Local(local) => Some(local),
632             _ => None,
633         })
634         .unique()
635         .collect()
636 }
637
638 /// find `self` param, that was not defined inside `body`
639 ///
640 /// It should skip `self` params from impls inside `body`
641 fn self_param_from_usages(
642     ctx: &AssistContext,
643     body: &FunctionBody,
644     vars_used_in_body: &[Local],
645 ) -> Option<(Local, ast::SelfParam)> {
646     let mut iter = vars_used_in_body
647         .iter()
648         .filter(|var| var.is_self(ctx.db()))
649         .map(|var| (var, var.source(ctx.db())))
650         .filter(|(_, src)| is_defined_before(ctx, body, src))
651         .filter_map(|(&node, src)| match src.value {
652             Either::Right(it) => Some((node, it)),
653             Either::Left(_) => {
654                 stdx::never!(false, "Local::is_self returned true, but source is IdentPat");
655                 None
656             }
657         });
658
659     let self_param = iter.next();
660     stdx::always!(
661         iter.next().is_none(),
662         "body references two different self params, both defined outside"
663     );
664
665     self_param
666 }
667
668 /// find variables that should be extracted as params
669 ///
670 /// Computes additional info that affects param type and mutability
671 fn extracted_function_params(
672     ctx: &AssistContext,
673     body: &FunctionBody,
674     vars_used_in_body: &[Local],
675 ) -> Vec<Param> {
676     vars_used_in_body
677         .iter()
678         .filter(|var| !var.is_self(ctx.db()))
679         .map(|node| (node, node.source(ctx.db())))
680         .filter(|(_, src)| is_defined_before(ctx, body, src))
681         .filter_map(|(&node, src)| {
682             if src.value.is_left() {
683                 Some(node)
684             } else {
685                 stdx::never!(false, "Local::is_self returned false, but source is SelfParam");
686                 None
687             }
688         })
689         .map(|var| {
690             let usages = LocalUsages::find(ctx, var);
691             let ty = var.ty(ctx.db());
692             let is_copy = ty.is_copy(ctx.db());
693             Param {
694                 var,
695                 ty,
696                 has_usages_afterwards: has_usages_after_body(&usages, body),
697                 has_mut_inside_body: has_exclusive_usages(ctx, &usages, body),
698                 is_copy,
699             }
700         })
701         .collect()
702 }
703
704 fn has_usages_after_body(usages: &LocalUsages, body: &FunctionBody) -> bool {
705     usages.iter().any(|reference| body.preceedes_range(reference.range))
706 }
707
708 /// checks if relevant var is used with `&mut` access inside body
709 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
710     usages
711         .iter()
712         .filter(|reference| body.contains_range(reference.range))
713         .any(|reference| reference_is_exclusive(reference, body, ctx))
714 }
715
716 /// checks if this reference requires `&mut` access inside body
717 fn reference_is_exclusive(
718     reference: &FileReference,
719     body: &FunctionBody,
720     ctx: &AssistContext,
721 ) -> bool {
722     // we directly modify variable with set: `n = 0`, `n += 1`
723     if reference.access == Some(ReferenceAccess::Write) {
724         return true;
725     }
726
727     // we take `&mut` reference to variable: `&mut v`
728     let path = match path_element_of_reference(body, reference) {
729         Some(path) => path,
730         None => return false,
731     };
732
733     expr_require_exclusive_access(ctx, &path).unwrap_or(false)
734 }
735
736 /// checks if this expr requires `&mut` access, recurses on field access
737 fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
738     let parent = expr.syntax().parent()?;
739
740     if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
741         if bin_expr.op_kind()?.is_assignment() {
742             return Some(bin_expr.lhs()?.syntax() == expr.syntax());
743         }
744         return Some(false);
745     }
746
747     if let Some(ref_expr) = ast::RefExpr::cast(parent.clone()) {
748         return Some(ref_expr.mut_token().is_some());
749     }
750
751     if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
752         let func = ctx.sema.resolve_method_call(&method_call)?;
753         let self_param = func.self_param(ctx.db())?;
754         let access = self_param.access(ctx.db());
755
756         return Some(matches!(access, hir::Access::Exclusive));
757     }
758
759     if let Some(field) = ast::FieldExpr::cast(parent) {
760         return expr_require_exclusive_access(ctx, &field.into());
761     }
762
763     Some(false)
764 }
765
766 /// Container of local varaible usages
767 ///
768 /// Semanticall same as `UsageSearchResult`, but provides more convenient interface
769 struct LocalUsages(ide_db::search::UsageSearchResult);
770
771 impl LocalUsages {
772     fn find(ctx: &AssistContext, var: Local) -> Self {
773         Self(
774             Definition::Local(var)
775                 .usages(&ctx.sema)
776                 .in_scope(SearchScope::single_file(ctx.frange.file_id))
777                 .all(),
778         )
779     }
780
781     fn iter(&self) -> impl Iterator<Item = &FileReference> + '_ {
782         self.0.iter().flat_map(|(_, rs)| rs.iter())
783     }
784 }
785
786 trait HasTokenAtOffset {
787     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken>;
788 }
789
790 impl HasTokenAtOffset for SyntaxNode {
791     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
792         SyntaxNode::token_at_offset(&self, offset)
793     }
794 }
795
796 /// find relevant `ast::PathExpr` for reference
797 ///
798 /// # Preconditions
799 ///
800 /// `node` must cover `reference`, that is `node.text_range().contains_range(reference.range)`
801 fn path_element_of_reference(
802     node: &dyn HasTokenAtOffset,
803     reference: &FileReference,
804 ) -> Option<ast::Expr> {
805     let token = node.token_at_offset(reference.range.start()).right_biased().or_else(|| {
806         stdx::never!(false, "cannot find token at variable usage: {:?}", reference);
807         None
808     })?;
809     let path = token.ancestors().find_map(ast::Expr::cast).or_else(|| {
810         stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
811         None
812     })?;
813     stdx::always!(matches!(path, ast::Expr::PathExpr(_)));
814     Some(path)
815 }
816
817 /// list local variables defined inside `body`
818 fn vars_defined_in_body(body: &FunctionBody, ctx: &AssistContext) -> Vec<Local> {
819     // FIXME: this doesn't work well with macros
820     //        see https://github.com/rust-analyzer/rust-analyzer/pull/7535#discussion_r570048550
821     body.descendants()
822         .filter_map(ast::IdentPat::cast)
823         .filter_map(|let_stmt| ctx.sema.to_def(&let_stmt))
824         .unique()
825         .collect()
826 }
827
828 /// list local variables defined inside `body` that should be returned from extracted function
829 fn vars_defined_in_body_and_outlive(ctx: &AssistContext, body: &FunctionBody) -> Vec<Local> {
830     let mut vars_defined_in_body = vars_defined_in_body(&body, ctx);
831     vars_defined_in_body.retain(|var| var_outlives_body(ctx, body, var));
832     vars_defined_in_body
833 }
834
835 /// checks if the relevant local was defined before(outside of) body
836 fn is_defined_before(
837     ctx: &AssistContext,
838     body: &FunctionBody,
839     src: &hir::InFile<Either<ast::IdentPat, ast::SelfParam>>,
840 ) -> bool {
841     src.file_id.original_file(ctx.db()) == ctx.frange.file_id
842         && !body.contains_node(&either_syntax(&src.value))
843 }
844
845 fn either_syntax(value: &Either<ast::IdentPat, ast::SelfParam>) -> &SyntaxNode {
846     match value {
847         Either::Left(pat) => pat.syntax(),
848         Either::Right(it) => it.syntax(),
849     }
850 }
851
852 /// checks if local variable is used after(outside of) body
853 fn var_outlives_body(ctx: &AssistContext, body: &FunctionBody, var: &Local) -> bool {
854     let usages = LocalUsages::find(ctx, *var);
855     let has_usages = usages.iter().any(|reference| body.preceedes_range(reference.range));
856     has_usages
857 }
858
859 fn body_return_ty(ctx: &AssistContext, body: &FunctionBody) -> Option<RetType> {
860     match body.tail_expr() {
861         Some(expr) => {
862             let ty = ctx.sema.type_of_expr(&expr)?;
863             Some(RetType::Expr(ty))
864         }
865         None => Some(RetType::Stmt),
866     }
867 }
868 /// Where to put extracted function definition
869 #[derive(Debug)]
870 enum Anchor {
871     /// Extract free function and put right after current top-level function
872     Freestanding,
873     /// Extract method and put right after current function in the impl-block
874     Method,
875 }
876
877 /// find where to put extracted function definition
878 ///
879 /// Function should be put right after returned node
880 fn scope_for_fn_insertion(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNode> {
881     match body {
882         FunctionBody::Expr(e) => scope_for_fn_insertion_node(e.syntax(), anchor),
883         FunctionBody::Span { parent, .. } => scope_for_fn_insertion_node(parent.syntax(), anchor),
884     }
885 }
886
887 fn scope_for_fn_insertion_node(node: &SyntaxNode, anchor: Anchor) -> Option<SyntaxNode> {
888     let mut ancestors = node.ancestors().peekable();
889     let mut last_ancestor = None;
890     while let Some(next_ancestor) = ancestors.next() {
891         match next_ancestor.kind() {
892             SyntaxKind::SOURCE_FILE => break,
893             SyntaxKind::ITEM_LIST => {
894                 if !matches!(anchor, Anchor::Freestanding) {
895                     continue;
896                 }
897                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
898                     break;
899                 }
900             }
901             SyntaxKind::ASSOC_ITEM_LIST => {
902                 if !matches!(anchor, Anchor::Method) {
903                     continue;
904                 }
905                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::IMPL) {
906                     break;
907                 }
908             }
909             _ => {}
910         }
911         last_ancestor = Some(next_ancestor);
912     }
913     last_ancestor
914 }
915
916 fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel) -> String {
917     let ret_ty = fun.return_type(ctx);
918
919     let args = fun.params.iter().map(|param| param.to_arg(ctx));
920     let args = make::arg_list(args);
921     let call_expr = if fun.self_param.is_some() {
922         let self_arg = make::expr_path(make_path_from_text("self"));
923         make::expr_method_call(self_arg, &fun.name, args)
924     } else {
925         let func = make::expr_path(make_path_from_text(&fun.name));
926         make::expr_call(func, args)
927     };
928
929     let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
930
931     let expr = handler.make_call_expr(call_expr).indent(indent);
932
933     let mut buf = String::new();
934     match fun.vars_defined_in_body_and_outlive.as_slice() {
935         [] => {}
936         [var] => format_to!(buf, "let {} = ", var.name(ctx.db()).unwrap()),
937         [v0, vs @ ..] => {
938             buf.push_str("let (");
939             format_to!(buf, "{}", v0.name(ctx.db()).unwrap());
940             for var in vs {
941                 format_to!(buf, ", {}", var.name(ctx.db()).unwrap());
942             }
943             buf.push_str(") = ");
944         }
945     }
946     format_to!(buf, "{}", expr);
947     if fun.ret_ty.is_unit()
948         && (!fun.vars_defined_in_body_and_outlive.is_empty() || !expr.is_block_like())
949     {
950         buf.push(';');
951     }
952     buf
953 }
954
955 enum FlowHandler {
956     None,
957     Try { kind: TryKind },
958     If { action: FlowKind },
959     IfOption { action: FlowKind },
960     MatchOption { none: FlowKind },
961     MatchResult { err: FlowKind },
962 }
963
964 impl FlowHandler {
965     fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
966         match &fun.control_flow.kind {
967             None => FlowHandler::None,
968             Some(flow_kind) => {
969                 let action = flow_kind.clone();
970                 if *ret_ty == FunType::Unit {
971                     match flow_kind {
972                         FlowKind::Return | FlowKind::Break | FlowKind::Continue => {
973                             FlowHandler::If { action }
974                         }
975                         FlowKind::ReturnValue(_) | FlowKind::BreakValue(_) => {
976                             FlowHandler::IfOption { action }
977                         }
978                         FlowKind::Try { kind } | FlowKind::TryReturn { kind, .. } => {
979                             FlowHandler::Try { kind: kind.clone() }
980                         }
981                     }
982                 } else {
983                     match flow_kind {
984                         FlowKind::Return | FlowKind::Break | FlowKind::Continue => {
985                             FlowHandler::MatchOption { none: action }
986                         }
987                         FlowKind::ReturnValue(_) | FlowKind::BreakValue(_) => {
988                             FlowHandler::MatchResult { err: action }
989                         }
990                         FlowKind::Try { kind } | FlowKind::TryReturn { kind, .. } => {
991                             FlowHandler::Try { kind: kind.clone() }
992                         }
993                     }
994                 }
995             }
996         }
997     }
998
999     fn make_call_expr(&self, call_expr: ast::Expr) -> ast::Expr {
1000         match self {
1001             FlowHandler::None => call_expr,
1002             FlowHandler::Try { kind: _ } => make::expr_try(call_expr),
1003             FlowHandler::If { action } => {
1004                 let action = action.make_result_handler(None);
1005                 let stmt = make::expr_stmt(action);
1006                 let block = make::block_expr(iter::once(stmt.into()), None);
1007                 let condition = make::condition(call_expr, None);
1008                 make::expr_if(condition, block, None)
1009             }
1010             FlowHandler::IfOption { action } => {
1011                 let path = make_path_from_text("Some");
1012                 let value_pat = make::ident_pat(make::name("value"));
1013                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1014                 let cond = make::condition(call_expr, Some(pattern.into()));
1015                 let value = make::expr_path(make_path_from_text("value"));
1016                 let action_expr = action.make_result_handler(Some(value));
1017                 let action_stmt = make::expr_stmt(action_expr);
1018                 let then = make::block_expr(iter::once(action_stmt.into()), None);
1019                 make::expr_if(cond, then, None)
1020             }
1021             FlowHandler::MatchOption { none } => {
1022                 let some_name = "value";
1023
1024                 let some_arm = {
1025                     let path = make_path_from_text("Some");
1026                     let value_pat = make::ident_pat(make::name(some_name));
1027                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1028                     let value = make::expr_path(make_path_from_text(some_name));
1029                     make::match_arm(iter::once(pat.into()), value)
1030                 };
1031                 let none_arm = {
1032                     let path = make_path_from_text("None");
1033                     let pat = make::path_pat(path);
1034                     make::match_arm(iter::once(pat), none.make_result_handler(None))
1035                 };
1036                 let arms = make::match_arm_list(vec![some_arm, none_arm]);
1037                 make::expr_match(call_expr, arms)
1038             }
1039             FlowHandler::MatchResult { err } => {
1040                 let ok_name = "value";
1041                 let err_name = "value";
1042
1043                 let ok_arm = {
1044                     let path = make_path_from_text("Ok");
1045                     let value_pat = make::ident_pat(make::name(ok_name));
1046                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1047                     let value = make::expr_path(make_path_from_text(ok_name));
1048                     make::match_arm(iter::once(pat.into()), value)
1049                 };
1050                 let err_arm = {
1051                     let path = make_path_from_text("Err");
1052                     let value_pat = make::ident_pat(make::name(err_name));
1053                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1054                     let value = make::expr_path(make_path_from_text(err_name));
1055                     make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value)))
1056                 };
1057                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1058                 make::expr_match(call_expr, arms)
1059             }
1060         }
1061     }
1062 }
1063
1064 fn make_path_from_text(text: &str) -> ast::Path {
1065     make::path_unqualified(make::path_segment(make::name_ref(text)))
1066 }
1067
1068 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1069     let name = var.name(ctx.db()).unwrap().to_string();
1070     make::expr_path(make_path_from_text(&name))
1071 }
1072
1073 fn format_function(
1074     ctx: &AssistContext,
1075     module: hir::Module,
1076     fun: &Function,
1077     old_indent: IndentLevel,
1078     new_indent: IndentLevel,
1079 ) -> String {
1080     let mut fn_def = String::new();
1081     let params = make_param_list(ctx, module, fun);
1082     let ret_ty = make_ret_ty(ctx, module, fun);
1083     let body = make_body(ctx, old_indent, new_indent, fun);
1084     match ctx.config.snippet_cap {
1085         Some(_) => format_to!(fn_def, "\n\n{}fn $0{}{}", new_indent, fun.name, params),
1086         None => format_to!(fn_def, "\n\n{}fn {}{}", new_indent, fun.name, params),
1087     }
1088     if let Some(ret_ty) = ret_ty {
1089         format_to!(fn_def, " {}", ret_ty);
1090     }
1091     format_to!(fn_def, " {}", body);
1092
1093     fn_def
1094 }
1095
1096 fn make_param_list(ctx: &AssistContext, module: hir::Module, fun: &Function) -> ast::ParamList {
1097     let self_param = fun.self_param.clone();
1098     let params = fun.params.iter().map(|param| param.to_param(ctx, module));
1099     make::param_list(self_param, params)
1100 }
1101
1102 impl FunType {
1103     fn make_ty(&self, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1104         match self {
1105             FunType::Unit => make::ty_unit(),
1106             FunType::Single(ty) => make_ty(ty, ctx, module),
1107             FunType::Tuple(types) => match types.as_slice() {
1108                 [] => {
1109                     stdx::never!("tuple type with 0 elements");
1110                     make::ty_unit()
1111                 }
1112                 [ty] => {
1113                     stdx::never!("tuple type with 1 element");
1114                     make_ty(ty, ctx, module)
1115                 }
1116                 types => {
1117                     let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1118                     make::ty_tuple(types)
1119                 }
1120             },
1121         }
1122     }
1123 }
1124
1125 fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Option<ast::RetType> {
1126     let fun_ty = fun.return_type(ctx);
1127     let handler = FlowHandler::from_ret_ty(fun, &fun_ty);
1128     let ret_ty = match &handler {
1129         FlowHandler::None => {
1130             if matches!(fun_ty, FunType::Unit) {
1131                 return None;
1132             }
1133             fun_ty.make_ty(ctx, module)
1134         }
1135         FlowHandler::Try { kind: TryKind::Option } => {
1136             make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module)))
1137         }
1138         FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1139             let handler_ty = parent_ret_ty
1140                 .type_parameters()
1141                 .nth(1)
1142                 .map(|ty| make_ty(&ty, ctx, module))
1143                 .unwrap_or_else(make::ty_unit);
1144             make::ty_generic(
1145                 make::name_ref("Result"),
1146                 vec![fun_ty.make_ty(ctx, module), handler_ty],
1147             )
1148         }
1149         FlowHandler::If { .. } => make::ty("bool"),
1150         FlowHandler::IfOption { action } => {
1151             let handler_ty = action
1152                 .expr_ty(ctx)
1153                 .map(|ty| make_ty(&ty, ctx, module))
1154                 .unwrap_or_else(make::ty_unit);
1155             make::ty_generic(make::name_ref("Option"), iter::once(handler_ty))
1156         }
1157         FlowHandler::MatchOption { .. } => {
1158             make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module)))
1159         }
1160         FlowHandler::MatchResult { err } => {
1161             let handler_ty =
1162                 err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit);
1163             make::ty_generic(
1164                 make::name_ref("Result"),
1165                 vec![fun_ty.make_ty(ctx, module), handler_ty],
1166             )
1167         }
1168     };
1169     Some(make::ret_type(ret_ty))
1170 }
1171
1172 fn make_body(
1173     ctx: &AssistContext,
1174     old_indent: IndentLevel,
1175     new_indent: IndentLevel,
1176     fun: &Function,
1177 ) -> ast::BlockExpr {
1178     let ret_ty = fun.return_type(ctx);
1179     let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1180     let block = match &fun.body {
1181         FunctionBody::Expr(expr) => {
1182             let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1183             let expr = ast::Expr::cast(expr).unwrap();
1184             let expr = expr.dedent(old_indent).indent(IndentLevel(1));
1185
1186             make::block_expr(Vec::new(), Some(expr))
1187         }
1188         FunctionBody::Span { parent, text_range } => {
1189             let mut elements: Vec<_> = parent
1190                 .syntax()
1191                 .children()
1192                 .filter(|it| text_range.contains_range(it.text_range()))
1193                 .map(|it| rewrite_body_segment(ctx, &fun.params, &handler, &it))
1194                 .collect();
1195
1196             let mut tail_expr = match elements.pop() {
1197                 Some(node) => ast::Expr::cast(node.clone()).or_else(|| {
1198                     elements.push(node);
1199                     None
1200                 }),
1201                 None => None,
1202             };
1203
1204             if tail_expr.is_none() {
1205                 match fun.vars_defined_in_body_and_outlive.as_slice() {
1206                     [] => {}
1207                     [var] => {
1208                         tail_expr = Some(path_expr_from_local(ctx, *var));
1209                     }
1210                     vars => {
1211                         let exprs = vars.iter().map(|var| path_expr_from_local(ctx, *var));
1212                         let expr = make::expr_tuple(exprs);
1213                         tail_expr = Some(expr);
1214                     }
1215                 }
1216             }
1217
1218             let elements = elements.into_iter().filter_map(|node| match ast::Stmt::cast(node) {
1219                 Some(stmt) => Some(stmt),
1220                 None => {
1221                     stdx::never!("block contains non-statement");
1222                     None
1223                 }
1224             });
1225
1226             let body_indent = IndentLevel(1);
1227             let elements = elements.map(|stmt| stmt.dedent(old_indent).indent(body_indent));
1228             let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
1229
1230             make::block_expr(elements, tail_expr)
1231         }
1232     };
1233
1234     let block = match &handler {
1235         FlowHandler::None => block,
1236         FlowHandler::Try { kind } => {
1237             let block = with_default_tail_expr(block, make::expr_unit());
1238             map_tail_expr(block, |tail_expr| {
1239                 let constructor = match kind {
1240                     TryKind::Option => "Some",
1241                     TryKind::Result { .. } => "Ok",
1242                 };
1243                 let func = make::expr_path(make_path_from_text(constructor));
1244                 let args = make::arg_list(iter::once(tail_expr));
1245                 make::expr_call(func, args)
1246             })
1247         }
1248         FlowHandler::If { .. } => {
1249             let lit_false = ast::Literal::cast(make::tokens::literal("false").parent()).unwrap();
1250             with_tail_expr(block, lit_false.into())
1251         }
1252         FlowHandler::IfOption { .. } => {
1253             let none = make::expr_path(make_path_from_text("None"));
1254             with_tail_expr(block, none)
1255         }
1256         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1257             let some = make::expr_path(make_path_from_text("Some"));
1258             let args = make::arg_list(iter::once(tail_expr));
1259             make::expr_call(some, args)
1260         }),
1261         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1262             let ok = make::expr_path(make_path_from_text("Ok"));
1263             let args = make::arg_list(iter::once(tail_expr));
1264             make::expr_call(ok, args)
1265         }),
1266     };
1267
1268     block.indent(new_indent)
1269 }
1270
1271 fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1272     let tail_expr = match block.tail_expr() {
1273         Some(tail_expr) => tail_expr,
1274         None => return block,
1275     };
1276     make::block_expr(block.statements(), Some(f(tail_expr)))
1277 }
1278
1279 fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1280     match block.tail_expr() {
1281         Some(_) => block,
1282         None => make::block_expr(block.statements(), Some(tail_expr)),
1283     }
1284 }
1285
1286 fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1287     let stmt_tail = block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1288     let stmts = block.statements().chain(stmt_tail);
1289     make::block_expr(stmts, Some(tail_expr))
1290 }
1291
1292 fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String {
1293     ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "()".to_string())
1294 }
1295
1296 fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1297     let ty_str = format_type(ty, ctx, module);
1298     make::ty(&ty_str)
1299 }
1300
1301 fn rewrite_body_segment(
1302     ctx: &AssistContext,
1303     params: &[Param],
1304     handler: &FlowHandler,
1305     syntax: &SyntaxNode,
1306 ) -> SyntaxNode {
1307     let syntax = fix_param_usages(ctx, params, syntax);
1308     update_external_control_flow(handler, &syntax)
1309 }
1310
1311 /// change all usages to account for added `&`/`&mut` for some params
1312 fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode {
1313     let mut rewriter = SyntaxRewriter::default();
1314     for param in params {
1315         if !param.kind().is_ref() {
1316             continue;
1317         }
1318
1319         let usages = LocalUsages::find(ctx, param.var);
1320         let usages = usages
1321             .iter()
1322             .filter(|reference| syntax.text_range().contains_range(reference.range))
1323             .filter_map(|reference| path_element_of_reference(syntax, reference));
1324         for path in usages {
1325             match path.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
1326                 Some(ast::Expr::MethodCallExpr(_)) | Some(ast::Expr::FieldExpr(_)) => {
1327                     // do nothing
1328                 }
1329                 Some(ast::Expr::RefExpr(node))
1330                     if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
1331                 {
1332                     rewriter.replace_ast(&node.clone().into(), &node.expr().unwrap());
1333                 }
1334                 Some(ast::Expr::RefExpr(node))
1335                     if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
1336                 {
1337                     rewriter.replace_ast(&node.clone().into(), &node.expr().unwrap());
1338                 }
1339                 Some(_) | None => {
1340                     rewriter.replace_ast(&path, &make::expr_prefix(T![*], path.clone()));
1341                 }
1342             };
1343         }
1344     }
1345
1346     rewriter.rewrite(syntax)
1347 }
1348
1349 fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) -> SyntaxNode {
1350     let mut rewriter = SyntaxRewriter::default();
1351
1352     let mut nested_loop = None;
1353     let mut nested_scope = None;
1354     for event in syntax.preorder() {
1355         let node = match event {
1356             WalkEvent::Enter(e) => {
1357                 match e.kind() {
1358                     SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
1359                         if nested_loop.is_none() {
1360                             nested_loop = Some(e.clone());
1361                         }
1362                     }
1363                     SyntaxKind::FN
1364                     | SyntaxKind::CONST
1365                     | SyntaxKind::STATIC
1366                     | SyntaxKind::IMPL
1367                     | SyntaxKind::MODULE => {
1368                         if nested_scope.is_none() {
1369                             nested_scope = Some(e.clone());
1370                         }
1371                     }
1372                     _ => {}
1373                 }
1374                 e
1375             }
1376             WalkEvent::Leave(e) => {
1377                 if nested_loop.as_ref() == Some(&e) {
1378                     nested_loop = None;
1379                 }
1380                 if nested_scope.as_ref() == Some(&e) {
1381                     nested_scope = None;
1382                 }
1383                 continue;
1384             }
1385         };
1386         if nested_scope.is_some() {
1387             continue;
1388         }
1389         let expr = match ast::Expr::cast(node) {
1390             Some(e) => e,
1391             None => continue,
1392         };
1393         match expr {
1394             ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => {
1395                 let expr = return_expr.expr();
1396                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1397                     rewriter.replace_ast(&return_expr.into(), &replacement);
1398                 }
1399             }
1400             ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
1401                 let expr = break_expr.expr();
1402                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1403                     rewriter.replace_ast(&break_expr.into(), &replacement);
1404                 }
1405             }
1406             ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
1407                 if let Some(replacement) = make_rewritten_flow(handler, None) {
1408                     rewriter.replace_ast(&continue_expr.into(), &replacement);
1409                 }
1410             }
1411             _ => {
1412                 // do nothing
1413             }
1414         }
1415     }
1416
1417     rewriter.rewrite(syntax)
1418 }
1419
1420 fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1421     let value = match handler {
1422         FlowHandler::None | FlowHandler::Try { .. } => return None,
1423         FlowHandler::If { .. } => {
1424             ast::Literal::cast(make::tokens::literal("true").parent()).unwrap().into()
1425         }
1426         FlowHandler::IfOption { .. } => {
1427             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1428             let args = make::arg_list(iter::once(expr));
1429             make::expr_call(make::expr_path(make_path_from_text("Some")), args)
1430         }
1431         FlowHandler::MatchOption { .. } => make::expr_path(make_path_from_text("None")),
1432         FlowHandler::MatchResult { .. } => {
1433             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1434             let args = make::arg_list(iter::once(expr));
1435             make::expr_call(make::expr_path(make_path_from_text("Err")), args)
1436         }
1437     };
1438     Some(make::expr_return(Some(value)))
1439 }
1440
1441 #[cfg(test)]
1442 mod tests {
1443     use crate::tests::{check_assist, check_assist_not_applicable};
1444
1445     use super::*;
1446
1447     #[test]
1448     fn no_args_from_binary_expr() {
1449         check_assist(
1450             extract_function,
1451             r#"
1452 fn foo() {
1453     foo($01 + 1$0);
1454 }"#,
1455             r#"
1456 fn foo() {
1457     foo(fun_name());
1458 }
1459
1460 fn $0fun_name() -> i32 {
1461     1 + 1
1462 }"#,
1463         );
1464     }
1465
1466     #[test]
1467     fn no_args_from_binary_expr_in_module() {
1468         check_assist(
1469             extract_function,
1470             r#"
1471 mod bar {
1472     fn foo() {
1473         foo($01 + 1$0);
1474     }
1475 }"#,
1476             r#"
1477 mod bar {
1478     fn foo() {
1479         foo(fun_name());
1480     }
1481
1482     fn $0fun_name() -> i32 {
1483         1 + 1
1484     }
1485 }"#,
1486         );
1487     }
1488
1489     #[test]
1490     fn no_args_from_binary_expr_indented() {
1491         check_assist(
1492             extract_function,
1493             r#"
1494 fn foo() {
1495     $0{ 1 + 1 }$0;
1496 }"#,
1497             r#"
1498 fn foo() {
1499     fun_name();
1500 }
1501
1502 fn $0fun_name() -> i32 {
1503     { 1 + 1 }
1504 }"#,
1505         );
1506     }
1507
1508     #[test]
1509     fn no_args_from_stmt_with_last_expr() {
1510         check_assist(
1511             extract_function,
1512             r#"
1513 fn foo() -> i32 {
1514     let k = 1;
1515     $0let m = 1;
1516     m + 1$0
1517 }"#,
1518             r#"
1519 fn foo() -> i32 {
1520     let k = 1;
1521     fun_name()
1522 }
1523
1524 fn $0fun_name() -> i32 {
1525     let m = 1;
1526     m + 1
1527 }"#,
1528         );
1529     }
1530
1531     #[test]
1532     fn no_args_from_stmt_unit() {
1533         check_assist(
1534             extract_function,
1535             r#"
1536 fn foo() {
1537     let k = 3;
1538     $0let m = 1;
1539     let n = m + 1;$0
1540     let g = 5;
1541 }"#,
1542             r#"
1543 fn foo() {
1544     let k = 3;
1545     fun_name();
1546     let g = 5;
1547 }
1548
1549 fn $0fun_name() {
1550     let m = 1;
1551     let n = m + 1;
1552 }"#,
1553         );
1554     }
1555
1556     #[test]
1557     fn no_args_if() {
1558         check_assist(
1559             extract_function,
1560             r#"
1561 fn foo() {
1562     $0if true { }$0
1563 }"#,
1564             r#"
1565 fn foo() {
1566     fun_name();
1567 }
1568
1569 fn $0fun_name() {
1570     if true { }
1571 }"#,
1572         );
1573     }
1574
1575     #[test]
1576     fn no_args_if_else() {
1577         check_assist(
1578             extract_function,
1579             r#"
1580 fn foo() -> i32 {
1581     $0if true { 1 } else { 2 }$0
1582 }"#,
1583             r#"
1584 fn foo() -> i32 {
1585     fun_name()
1586 }
1587
1588 fn $0fun_name() -> i32 {
1589     if true { 1 } else { 2 }
1590 }"#,
1591         );
1592     }
1593
1594     #[test]
1595     fn no_args_if_let_else() {
1596         check_assist(
1597             extract_function,
1598             r#"
1599 fn foo() -> i32 {
1600     $0if let true = false { 1 } else { 2 }$0
1601 }"#,
1602             r#"
1603 fn foo() -> i32 {
1604     fun_name()
1605 }
1606
1607 fn $0fun_name() -> i32 {
1608     if let true = false { 1 } else { 2 }
1609 }"#,
1610         );
1611     }
1612
1613     #[test]
1614     fn no_args_match() {
1615         check_assist(
1616             extract_function,
1617             r#"
1618 fn foo() -> i32 {
1619     $0match true {
1620         true => 1,
1621         false => 2,
1622     }$0
1623 }"#,
1624             r#"
1625 fn foo() -> i32 {
1626     fun_name()
1627 }
1628
1629 fn $0fun_name() -> i32 {
1630     match true {
1631         true => 1,
1632         false => 2,
1633     }
1634 }"#,
1635         );
1636     }
1637
1638     #[test]
1639     fn no_args_while() {
1640         check_assist(
1641             extract_function,
1642             r#"
1643 fn foo() {
1644     $0while true { }$0
1645 }"#,
1646             r#"
1647 fn foo() {
1648     fun_name();
1649 }
1650
1651 fn $0fun_name() {
1652     while true { }
1653 }"#,
1654         );
1655     }
1656
1657     #[test]
1658     fn no_args_for() {
1659         check_assist(
1660             extract_function,
1661             r#"
1662 fn foo() {
1663     $0for v in &[0, 1] { }$0
1664 }"#,
1665             r#"
1666 fn foo() {
1667     fun_name();
1668 }
1669
1670 fn $0fun_name() {
1671     for v in &[0, 1] { }
1672 }"#,
1673         );
1674     }
1675
1676     #[test]
1677     fn no_args_from_loop_unit() {
1678         check_assist(
1679             extract_function,
1680             r#"
1681 fn foo() {
1682     $0loop {
1683         let m = 1;
1684     }$0
1685 }"#,
1686             r#"
1687 fn foo() {
1688     fun_name()
1689 }
1690
1691 fn $0fun_name() -> ! {
1692     loop {
1693         let m = 1;
1694     }
1695 }"#,
1696         );
1697     }
1698
1699     #[test]
1700     fn no_args_from_loop_with_return() {
1701         check_assist(
1702             extract_function,
1703             r#"
1704 fn foo() {
1705     let v = $0loop {
1706         let m = 1;
1707         break m;
1708     }$0;
1709 }"#,
1710             r#"
1711 fn foo() {
1712     let v = fun_name();
1713 }
1714
1715 fn $0fun_name() -> i32 {
1716     loop {
1717         let m = 1;
1718         break m;
1719     }
1720 }"#,
1721         );
1722     }
1723
1724     #[test]
1725     fn no_args_from_match() {
1726         check_assist(
1727             extract_function,
1728             r#"
1729 fn foo() {
1730     let v: i32 = $0match Some(1) {
1731         Some(x) => x,
1732         None => 0,
1733     }$0;
1734 }"#,
1735             r#"
1736 fn foo() {
1737     let v: i32 = fun_name();
1738 }
1739
1740 fn $0fun_name() -> i32 {
1741     match Some(1) {
1742         Some(x) => x,
1743         None => 0,
1744     }
1745 }"#,
1746         );
1747     }
1748
1749     #[test]
1750     fn argument_form_expr() {
1751         check_assist(
1752             extract_function,
1753             r"
1754 fn foo() -> u32 {
1755     let n = 2;
1756     $0n+2$0
1757 }",
1758             r"
1759 fn foo() -> u32 {
1760     let n = 2;
1761     fun_name(n)
1762 }
1763
1764 fn $0fun_name(n: u32) -> u32 {
1765     n+2
1766 }",
1767         )
1768     }
1769
1770     #[test]
1771     fn argument_used_twice_form_expr() {
1772         check_assist(
1773             extract_function,
1774             r"
1775 fn foo() -> u32 {
1776     let n = 2;
1777     $0n+n$0
1778 }",
1779             r"
1780 fn foo() -> u32 {
1781     let n = 2;
1782     fun_name(n)
1783 }
1784
1785 fn $0fun_name(n: u32) -> u32 {
1786     n+n
1787 }",
1788         )
1789     }
1790
1791     #[test]
1792     fn two_arguments_form_expr() {
1793         check_assist(
1794             extract_function,
1795             r"
1796 fn foo() -> u32 {
1797     let n = 2;
1798     let m = 3;
1799     $0n+n*m$0
1800 }",
1801             r"
1802 fn foo() -> u32 {
1803     let n = 2;
1804     let m = 3;
1805     fun_name(n, m)
1806 }
1807
1808 fn $0fun_name(n: u32, m: u32) -> u32 {
1809     n+n*m
1810 }",
1811         )
1812     }
1813
1814     #[test]
1815     fn argument_and_locals() {
1816         check_assist(
1817             extract_function,
1818             r"
1819 fn foo() -> u32 {
1820     let n = 2;
1821     $0let m = 1;
1822     n + m$0
1823 }",
1824             r"
1825 fn foo() -> u32 {
1826     let n = 2;
1827     fun_name(n)
1828 }
1829
1830 fn $0fun_name(n: u32) -> u32 {
1831     let m = 1;
1832     n + m
1833 }",
1834         )
1835     }
1836
1837     #[test]
1838     fn in_comment_is_not_applicable() {
1839         cov_mark::check!(extract_function_in_comment_is_not_applicable);
1840         check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
1841     }
1842
1843     #[test]
1844     fn part_of_expr_stmt() {
1845         check_assist(
1846             extract_function,
1847             "
1848 fn foo() {
1849     $01$0 + 1;
1850 }",
1851             "
1852 fn foo() {
1853     fun_name() + 1;
1854 }
1855
1856 fn $0fun_name() -> i32 {
1857     1
1858 }",
1859         );
1860     }
1861
1862     #[test]
1863     fn function_expr() {
1864         check_assist(
1865             extract_function,
1866             r#"
1867 fn foo() {
1868     $0bar(1 + 1)$0
1869 }"#,
1870             r#"
1871 fn foo() {
1872     fun_name();
1873 }
1874
1875 fn $0fun_name() {
1876     bar(1 + 1)
1877 }"#,
1878         )
1879     }
1880
1881     #[test]
1882     fn extract_from_nested() {
1883         check_assist(
1884             extract_function,
1885             r"
1886 fn main() {
1887     let x = true;
1888     let tuple = match x {
1889         true => ($02 + 2$0, true)
1890         _ => (0, false)
1891     };
1892 }",
1893             r"
1894 fn main() {
1895     let x = true;
1896     let tuple = match x {
1897         true => (fun_name(), true)
1898         _ => (0, false)
1899     };
1900 }
1901
1902 fn $0fun_name() -> i32 {
1903     2 + 2
1904 }",
1905         );
1906     }
1907
1908     #[test]
1909     fn param_from_closure() {
1910         check_assist(
1911             extract_function,
1912             r"
1913 fn main() {
1914     let lambda = |x: u32| $0x * 2$0;
1915 }",
1916             r"
1917 fn main() {
1918     let lambda = |x: u32| fun_name(x);
1919 }
1920
1921 fn $0fun_name(x: u32) -> u32 {
1922     x * 2
1923 }",
1924         );
1925     }
1926
1927     #[test]
1928     fn extract_return_stmt() {
1929         check_assist(
1930             extract_function,
1931             r"
1932 fn foo() -> u32 {
1933     $0return 2 + 2$0;
1934 }",
1935             r"
1936 fn foo() -> u32 {
1937     return fun_name();
1938 }
1939
1940 fn $0fun_name() -> u32 {
1941     2 + 2
1942 }",
1943         );
1944     }
1945
1946     #[test]
1947     fn does_not_add_extra_whitespace() {
1948         check_assist(
1949             extract_function,
1950             r"
1951 fn foo() -> u32 {
1952
1953
1954     $0return 2 + 2$0;
1955 }",
1956             r"
1957 fn foo() -> u32 {
1958
1959
1960     return fun_name();
1961 }
1962
1963 fn $0fun_name() -> u32 {
1964     2 + 2
1965 }",
1966         );
1967     }
1968
1969     #[test]
1970     fn break_stmt() {
1971         check_assist(
1972             extract_function,
1973             r"
1974 fn main() {
1975     let result = loop {
1976         $0break 2 + 2$0;
1977     };
1978 }",
1979             r"
1980 fn main() {
1981     let result = loop {
1982         break fun_name();
1983     };
1984 }
1985
1986 fn $0fun_name() -> i32 {
1987     2 + 2
1988 }",
1989         );
1990     }
1991
1992     #[test]
1993     fn extract_cast() {
1994         check_assist(
1995             extract_function,
1996             r"
1997 fn main() {
1998     let v = $00f32 as u32$0;
1999 }",
2000             r"
2001 fn main() {
2002     let v = fun_name();
2003 }
2004
2005 fn $0fun_name() -> u32 {
2006     0f32 as u32
2007 }",
2008         );
2009     }
2010
2011     #[test]
2012     fn return_not_applicable() {
2013         check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2014     }
2015
2016     #[test]
2017     fn method_to_freestanding() {
2018         check_assist(
2019             extract_function,
2020             r"
2021 struct S;
2022
2023 impl S {
2024     fn foo(&self) -> i32 {
2025         $01+1$0
2026     }
2027 }",
2028             r"
2029 struct S;
2030
2031 impl S {
2032     fn foo(&self) -> i32 {
2033         fun_name()
2034     }
2035 }
2036
2037 fn $0fun_name() -> i32 {
2038     1+1
2039 }",
2040         );
2041     }
2042
2043     #[test]
2044     fn method_with_reference() {
2045         check_assist(
2046             extract_function,
2047             r"
2048 struct S { f: i32 };
2049
2050 impl S {
2051     fn foo(&self) -> i32 {
2052         $01+self.f$0
2053     }
2054 }",
2055             r"
2056 struct S { f: i32 };
2057
2058 impl S {
2059     fn foo(&self) -> i32 {
2060         self.fun_name()
2061     }
2062
2063     fn $0fun_name(&self) -> i32 {
2064         1+self.f
2065     }
2066 }",
2067         );
2068     }
2069
2070     #[test]
2071     fn method_with_mut() {
2072         check_assist(
2073             extract_function,
2074             r"
2075 struct S { f: i32 };
2076
2077 impl S {
2078     fn foo(&mut self) {
2079         $0self.f += 1;$0
2080     }
2081 }",
2082             r"
2083 struct S { f: i32 };
2084
2085 impl S {
2086     fn foo(&mut self) {
2087         self.fun_name();
2088     }
2089
2090     fn $0fun_name(&mut self) {
2091         self.f += 1;
2092     }
2093 }",
2094         );
2095     }
2096
2097     #[test]
2098     fn variable_defined_inside_and_used_after_no_ret() {
2099         check_assist(
2100             extract_function,
2101             r"
2102 fn foo() {
2103     let n = 1;
2104     $0let k = n * n;$0
2105     let m = k + 1;
2106 }",
2107             r"
2108 fn foo() {
2109     let n = 1;
2110     let k = fun_name(n);
2111     let m = k + 1;
2112 }
2113
2114 fn $0fun_name(n: i32) -> i32 {
2115     let k = n * n;
2116     k
2117 }",
2118         );
2119     }
2120
2121     #[test]
2122     fn two_variables_defined_inside_and_used_after_no_ret() {
2123         check_assist(
2124             extract_function,
2125             r"
2126 fn foo() {
2127     let n = 1;
2128     $0let k = n * n;
2129     let m = k + 2;$0
2130     let h = k + m;
2131 }",
2132             r"
2133 fn foo() {
2134     let n = 1;
2135     let (k, m) = fun_name(n);
2136     let h = k + m;
2137 }
2138
2139 fn $0fun_name(n: i32) -> (i32, i32) {
2140     let k = n * n;
2141     let m = k + 2;
2142     (k, m)
2143 }",
2144         );
2145     }
2146
2147     #[test]
2148     fn nontrivial_patterns_define_variables() {
2149         check_assist(
2150             extract_function,
2151             r"
2152 struct Counter(i32);
2153 fn foo() {
2154     $0let Counter(n) = Counter(0);$0
2155     let m = n;
2156 }",
2157             r"
2158 struct Counter(i32);
2159 fn foo() {
2160     let n = fun_name();
2161     let m = n;
2162 }
2163
2164 fn $0fun_name() -> i32 {
2165     let Counter(n) = Counter(0);
2166     n
2167 }",
2168         );
2169     }
2170
2171     #[test]
2172     fn struct_with_two_fields_pattern_define_variables() {
2173         check_assist(
2174             extract_function,
2175             r"
2176 struct Counter { n: i32, m: i32 };
2177 fn foo() {
2178     $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
2179     let h = n + k;
2180 }",
2181             r"
2182 struct Counter { n: i32, m: i32 };
2183 fn foo() {
2184     let (n, k) = fun_name();
2185     let h = n + k;
2186 }
2187
2188 fn $0fun_name() -> (i32, i32) {
2189     let Counter { n, m: k } = Counter { n: 1, m: 2 };
2190     (n, k)
2191 }",
2192         );
2193     }
2194
2195     #[test]
2196     fn mut_var_from_outer_scope() {
2197         check_assist(
2198             extract_function,
2199             r"
2200 fn foo() {
2201     let mut n = 1;
2202     $0n += 1;$0
2203     let m = n + 1;
2204 }",
2205             r"
2206 fn foo() {
2207     let mut n = 1;
2208     fun_name(&mut n);
2209     let m = n + 1;
2210 }
2211
2212 fn $0fun_name(n: &mut i32) {
2213     *n += 1;
2214 }",
2215         );
2216     }
2217
2218     #[test]
2219     fn mut_field_from_outer_scope() {
2220         check_assist(
2221             extract_function,
2222             r"
2223 struct C { n: i32 }
2224 fn foo() {
2225     let mut c = C { n: 0 };
2226     $0c.n += 1;$0
2227     let m = c.n + 1;
2228 }",
2229             r"
2230 struct C { n: i32 }
2231 fn foo() {
2232     let mut c = C { n: 0 };
2233     fun_name(&mut c);
2234     let m = c.n + 1;
2235 }
2236
2237 fn $0fun_name(c: &mut C) {
2238     c.n += 1;
2239 }",
2240         );
2241     }
2242
2243     #[test]
2244     fn mut_nested_field_from_outer_scope() {
2245         check_assist(
2246             extract_function,
2247             r"
2248 struct P { n: i32}
2249 struct C { p: P }
2250 fn foo() {
2251     let mut c = C { p: P { n: 0 } };
2252     let mut v = C { p: P { n: 0 } };
2253     let u = C { p: P { n: 0 } };
2254     $0c.p.n += u.p.n;
2255     let r = &mut v.p.n;$0
2256     let m = c.p.n + v.p.n + u.p.n;
2257 }",
2258             r"
2259 struct P { n: i32}
2260 struct C { p: P }
2261 fn foo() {
2262     let mut c = C { p: P { n: 0 } };
2263     let mut v = C { p: P { n: 0 } };
2264     let u = C { p: P { n: 0 } };
2265     fun_name(&mut c, &u, &mut v);
2266     let m = c.p.n + v.p.n + u.p.n;
2267 }
2268
2269 fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
2270     c.p.n += u.p.n;
2271     let r = &mut v.p.n;
2272 }",
2273         );
2274     }
2275
2276     #[test]
2277     fn mut_param_many_usages_stmt() {
2278         check_assist(
2279             extract_function,
2280             r"
2281 fn bar(k: i32) {}
2282 trait I: Copy {
2283     fn succ(&self) -> Self;
2284     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2285 }
2286 impl I for i32 {
2287     fn succ(&self) -> Self { *self + 1 }
2288 }
2289 fn foo() {
2290     let mut n = 1;
2291     $0n += n;
2292     bar(n);
2293     bar(n+1);
2294     bar(n*n);
2295     bar(&n);
2296     n.inc();
2297     let v = &mut n;
2298     *v = v.succ();
2299     n.succ();$0
2300     let m = n + 1;
2301 }",
2302             r"
2303 fn bar(k: i32) {}
2304 trait I: Copy {
2305     fn succ(&self) -> Self;
2306     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2307 }
2308 impl I for i32 {
2309     fn succ(&self) -> Self { *self + 1 }
2310 }
2311 fn foo() {
2312     let mut n = 1;
2313     fun_name(&mut n);
2314     let m = n + 1;
2315 }
2316
2317 fn $0fun_name(n: &mut i32) {
2318     *n += *n;
2319     bar(*n);
2320     bar(*n+1);
2321     bar(*n**n);
2322     bar(&*n);
2323     n.inc();
2324     let v = n;
2325     *v = v.succ();
2326     n.succ();
2327 }",
2328         );
2329     }
2330
2331     #[test]
2332     fn mut_param_many_usages_expr() {
2333         check_assist(
2334             extract_function,
2335             r"
2336 fn bar(k: i32) {}
2337 trait I: Copy {
2338     fn succ(&self) -> Self;
2339     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2340 }
2341 impl I for i32 {
2342     fn succ(&self) -> Self { *self + 1 }
2343 }
2344 fn foo() {
2345     let mut n = 1;
2346     $0{
2347         n += n;
2348         bar(n);
2349         bar(n+1);
2350         bar(n*n);
2351         bar(&n);
2352         n.inc();
2353         let v = &mut n;
2354         *v = v.succ();
2355         n.succ();
2356     }$0
2357     let m = n + 1;
2358 }",
2359             r"
2360 fn bar(k: i32) {}
2361 trait I: Copy {
2362     fn succ(&self) -> Self;
2363     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2364 }
2365 impl I for i32 {
2366     fn succ(&self) -> Self { *self + 1 }
2367 }
2368 fn foo() {
2369     let mut n = 1;
2370     fun_name(&mut n);
2371     let m = n + 1;
2372 }
2373
2374 fn $0fun_name(n: &mut i32) {
2375     {
2376         *n += *n;
2377         bar(*n);
2378         bar(*n+1);
2379         bar(*n**n);
2380         bar(&*n);
2381         n.inc();
2382         let v = n;
2383         *v = v.succ();
2384         n.succ();
2385     }
2386 }",
2387         );
2388     }
2389
2390     #[test]
2391     fn mut_param_by_value() {
2392         check_assist(
2393             extract_function,
2394             r"
2395 fn foo() {
2396     let mut n = 1;
2397     $0n += 1;$0
2398 }",
2399             r"
2400 fn foo() {
2401     let mut n = 1;
2402     fun_name(n);
2403 }
2404
2405 fn $0fun_name(mut n: i32) {
2406     n += 1;
2407 }",
2408         );
2409     }
2410
2411     #[test]
2412     fn mut_param_because_of_mut_ref() {
2413         check_assist(
2414             extract_function,
2415             r"
2416 fn foo() {
2417     let mut n = 1;
2418     $0let v = &mut n;
2419     *v += 1;$0
2420     let k = n;
2421 }",
2422             r"
2423 fn foo() {
2424     let mut n = 1;
2425     fun_name(&mut n);
2426     let k = n;
2427 }
2428
2429 fn $0fun_name(n: &mut i32) {
2430     let v = n;
2431     *v += 1;
2432 }",
2433         );
2434     }
2435
2436     #[test]
2437     fn mut_param_by_value_because_of_mut_ref() {
2438         check_assist(
2439             extract_function,
2440             r"
2441 fn foo() {
2442     let mut n = 1;
2443     $0let v = &mut n;
2444     *v += 1;$0
2445 }",
2446             r"
2447 fn foo() {
2448     let mut n = 1;
2449     fun_name(n);
2450 }
2451
2452 fn $0fun_name(mut n: i32) {
2453     let v = &mut n;
2454     *v += 1;
2455 }",
2456         );
2457     }
2458
2459     #[test]
2460     fn mut_method_call() {
2461         check_assist(
2462             extract_function,
2463             r"
2464 trait I {
2465     fn inc(&mut self);
2466 }
2467 impl I for i32 {
2468     fn inc(&mut self) { *self += 1 }
2469 }
2470 fn foo() {
2471     let mut n = 1;
2472     $0n.inc();$0
2473 }",
2474             r"
2475 trait I {
2476     fn inc(&mut self);
2477 }
2478 impl I for i32 {
2479     fn inc(&mut self) { *self += 1 }
2480 }
2481 fn foo() {
2482     let mut n = 1;
2483     fun_name(n);
2484 }
2485
2486 fn $0fun_name(mut n: i32) {
2487     n.inc();
2488 }",
2489         );
2490     }
2491
2492     #[test]
2493     fn shared_method_call() {
2494         check_assist(
2495             extract_function,
2496             r"
2497 trait I {
2498     fn succ(&self);
2499 }
2500 impl I for i32 {
2501     fn succ(&self) { *self + 1 }
2502 }
2503 fn foo() {
2504     let mut n = 1;
2505     $0n.succ();$0
2506 }",
2507             r"
2508 trait I {
2509     fn succ(&self);
2510 }
2511 impl I for i32 {
2512     fn succ(&self) { *self + 1 }
2513 }
2514 fn foo() {
2515     let mut n = 1;
2516     fun_name(n);
2517 }
2518
2519 fn $0fun_name(n: i32) {
2520     n.succ();
2521 }",
2522         );
2523     }
2524
2525     #[test]
2526     fn mut_method_call_with_other_receiver() {
2527         check_assist(
2528             extract_function,
2529             r"
2530 trait I {
2531     fn inc(&mut self, n: i32);
2532 }
2533 impl I for i32 {
2534     fn inc(&mut self, n: i32) { *self += n }
2535 }
2536 fn foo() {
2537     let mut n = 1;
2538     $0let mut m = 2;
2539     m.inc(n);$0
2540 }",
2541             r"
2542 trait I {
2543     fn inc(&mut self, n: i32);
2544 }
2545 impl I for i32 {
2546     fn inc(&mut self, n: i32) { *self += n }
2547 }
2548 fn foo() {
2549     let mut n = 1;
2550     fun_name(n);
2551 }
2552
2553 fn $0fun_name(n: i32) {
2554     let mut m = 2;
2555     m.inc(n);
2556 }",
2557         );
2558     }
2559
2560     #[test]
2561     fn non_copy_without_usages_after() {
2562         check_assist(
2563             extract_function,
2564             r"
2565 struct Counter(i32);
2566 fn foo() {
2567     let c = Counter(0);
2568     $0let n = c.0;$0
2569 }",
2570             r"
2571 struct Counter(i32);
2572 fn foo() {
2573     let c = Counter(0);
2574     fun_name(c);
2575 }
2576
2577 fn $0fun_name(c: Counter) {
2578     let n = c.0;
2579 }",
2580         );
2581     }
2582
2583     #[test]
2584     fn non_copy_used_after() {
2585         check_assist(
2586             extract_function,
2587             r"
2588 struct Counter(i32);
2589 fn foo() {
2590     let c = Counter(0);
2591     $0let n = c.0;$0
2592     let m = c.0;
2593 }",
2594             r"
2595 struct Counter(i32);
2596 fn foo() {
2597     let c = Counter(0);
2598     fun_name(&c);
2599     let m = c.0;
2600 }
2601
2602 fn $0fun_name(c: &Counter) {
2603     let n = c.0;
2604 }",
2605         );
2606     }
2607
2608     #[test]
2609     fn copy_used_after() {
2610         check_assist(
2611             extract_function,
2612             r##"
2613 #[lang = "copy"]
2614 pub trait Copy {}
2615 impl Copy for i32 {}
2616 fn foo() {
2617     let n = 0;
2618     $0let m = n;$0
2619     let k = n;
2620 }"##,
2621             r##"
2622 #[lang = "copy"]
2623 pub trait Copy {}
2624 impl Copy for i32 {}
2625 fn foo() {
2626     let n = 0;
2627     fun_name(n);
2628     let k = n;
2629 }
2630
2631 fn $0fun_name(n: i32) {
2632     let m = n;
2633 }"##,
2634         )
2635     }
2636
2637     #[test]
2638     fn copy_custom_used_after() {
2639         check_assist(
2640             extract_function,
2641             r##"
2642 #[lang = "copy"]
2643 pub trait Copy {}
2644 struct Counter(i32);
2645 impl Copy for Counter {}
2646 fn foo() {
2647     let c = Counter(0);
2648     $0let n = c.0;$0
2649     let m = c.0;
2650 }"##,
2651             r##"
2652 #[lang = "copy"]
2653 pub trait Copy {}
2654 struct Counter(i32);
2655 impl Copy for Counter {}
2656 fn foo() {
2657     let c = Counter(0);
2658     fun_name(c);
2659     let m = c.0;
2660 }
2661
2662 fn $0fun_name(c: Counter) {
2663     let n = c.0;
2664 }"##,
2665         );
2666     }
2667
2668     #[test]
2669     fn indented_stmts() {
2670         check_assist(
2671             extract_function,
2672             r"
2673 fn foo() {
2674     if true {
2675         loop {
2676             $0let n = 1;
2677             let m = 2;$0
2678         }
2679     }
2680 }",
2681             r"
2682 fn foo() {
2683     if true {
2684         loop {
2685             fun_name();
2686         }
2687     }
2688 }
2689
2690 fn $0fun_name() {
2691     let n = 1;
2692     let m = 2;
2693 }",
2694         );
2695     }
2696
2697     #[test]
2698     fn indented_stmts_inside_mod() {
2699         check_assist(
2700             extract_function,
2701             r"
2702 mod bar {
2703     fn foo() {
2704         if true {
2705             loop {
2706                 $0let n = 1;
2707                 let m = 2;$0
2708             }
2709         }
2710     }
2711 }",
2712             r"
2713 mod bar {
2714     fn foo() {
2715         if true {
2716             loop {
2717                 fun_name();
2718             }
2719         }
2720     }
2721
2722     fn $0fun_name() {
2723         let n = 1;
2724         let m = 2;
2725     }
2726 }",
2727         );
2728     }
2729
2730     #[test]
2731     fn break_loop() {
2732         check_assist(
2733             extract_function,
2734             r##"
2735 enum Option<T> {
2736     #[lang = "None"] None,
2737     #[lang = "Some"] Some(T),
2738 }
2739 use Option::*;
2740 fn foo() {
2741     loop {
2742         let n = 1;
2743         $0let m = n + 1;
2744         break;
2745         let k = 2;$0
2746         let h = 1 + k;
2747     }
2748 }"##,
2749             r##"
2750 enum Option<T> {
2751     #[lang = "None"] None,
2752     #[lang = "Some"] Some(T),
2753 }
2754 use Option::*;
2755 fn foo() {
2756     loop {
2757         let n = 1;
2758         let k = match fun_name(n) {
2759             Some(value) => value,
2760             None => break,
2761         };
2762         let h = 1 + k;
2763     }
2764 }
2765
2766 fn $0fun_name(n: i32) -> Option<i32> {
2767     let m = n + 1;
2768     return None;
2769     let k = 2;
2770     Some(k)
2771 }"##,
2772         );
2773     }
2774
2775     #[test]
2776     fn return_to_parent() {
2777         check_assist(
2778             extract_function,
2779             r##"
2780 #[lang = "copy"]
2781 pub trait Copy {}
2782 impl Copy for i32 {}
2783 enum Result<T, E> {
2784     #[lang = "Ok"] Ok(T),
2785     #[lang = "Err"] Err(E),
2786 }
2787 use Result::*;
2788 fn foo() -> i64 {
2789     let n = 1;
2790     $0let m = n + 1;
2791     return 1;
2792     let k = 2;$0
2793     (n + k) as i64
2794 }"##,
2795             r##"
2796 #[lang = "copy"]
2797 pub trait Copy {}
2798 impl Copy for i32 {}
2799 enum Result<T, E> {
2800     #[lang = "Ok"] Ok(T),
2801     #[lang = "Err"] Err(E),
2802 }
2803 use Result::*;
2804 fn foo() -> i64 {
2805     let n = 1;
2806     let k = match fun_name(n) {
2807         Ok(value) => value,
2808         Err(value) => return value,
2809     };
2810     (n + k) as i64
2811 }
2812
2813 fn $0fun_name(n: i32) -> Result<i32, i64> {
2814     let m = n + 1;
2815     return Err(1);
2816     let k = 2;
2817     Ok(k)
2818 }"##,
2819         );
2820     }
2821
2822     #[test]
2823     fn break_and_continue() {
2824         cov_mark::check!(external_control_flow_break_and_continue);
2825         check_assist_not_applicable(
2826             extract_function,
2827             r##"
2828 fn foo() {
2829     loop {
2830         let n = 1;
2831         $0let m = n + 1;
2832         break;
2833         let k = 2;
2834         continue;
2835         let k = k + 1;$0
2836         let r = n + k;
2837     }
2838 }"##,
2839         );
2840     }
2841
2842     #[test]
2843     fn return_and_break() {
2844         cov_mark::check!(external_control_flow_return_and_bc);
2845         check_assist_not_applicable(
2846             extract_function,
2847             r##"
2848 fn foo() {
2849     loop {
2850         let n = 1;
2851         $0let m = n + 1;
2852         break;
2853         let k = 2;
2854         return;
2855         let k = k + 1;$0
2856         let r = n + k;
2857     }
2858 }"##,
2859         );
2860     }
2861
2862     #[test]
2863     fn break_loop_with_if() {
2864         check_assist(
2865             extract_function,
2866             r##"
2867 fn foo() {
2868     loop {
2869         let mut n = 1;
2870         $0let m = n + 1;
2871         break;
2872         n += m;$0
2873         let h = 1 + n;
2874     }
2875 }"##,
2876             r##"
2877 fn foo() {
2878     loop {
2879         let mut n = 1;
2880         if fun_name(&mut n) {
2881             break;
2882         }
2883         let h = 1 + n;
2884     }
2885 }
2886
2887 fn $0fun_name(n: &mut i32) -> bool {
2888     let m = *n + 1;
2889     return true;
2890     *n += m;
2891     false
2892 }"##,
2893         );
2894     }
2895
2896     #[test]
2897     fn break_loop_nested() {
2898         check_assist(
2899             extract_function,
2900             r##"
2901 fn foo() {
2902     loop {
2903         let mut n = 1;
2904         $0let m = n + 1;
2905         if m == 42 {
2906             break;
2907         }$0
2908         let h = 1;
2909     }
2910 }"##,
2911             r##"
2912 fn foo() {
2913     loop {
2914         let mut n = 1;
2915         if fun_name(n) {
2916             break;
2917         }
2918         let h = 1;
2919     }
2920 }
2921
2922 fn $0fun_name(n: i32) -> bool {
2923     let m = n + 1;
2924     if m == 42 {
2925         return true;
2926     }
2927     false
2928 }"##,
2929         );
2930     }
2931
2932     #[test]
2933     fn return_from_nested_loop() {
2934         check_assist(
2935             extract_function,
2936             r##"
2937 fn foo() {
2938     loop {
2939         let n = 1;
2940         $0
2941         let k = 1;
2942         loop {
2943             return;
2944         }
2945         let m = k + 1;$0
2946         let h = 1 + m;
2947     }
2948 }"##,
2949             r##"
2950 fn foo() {
2951     loop {
2952         let n = 1;
2953         let m = match fun_name() {
2954             Some(value) => value,
2955             None => return,
2956         };
2957         let h = 1 + m;
2958     }
2959 }
2960
2961 fn $0fun_name() -> Option<i32> {
2962     let k = 1;
2963     loop {
2964         return None;
2965     }
2966     let m = k + 1;
2967     Some(m)
2968 }"##,
2969         );
2970     }
2971
2972     #[test]
2973     fn break_from_nested_loop() {
2974         check_assist(
2975             extract_function,
2976             r##"
2977 fn foo() {
2978     loop {
2979         let n = 1;
2980         $0let k = 1;
2981         loop {
2982             break;
2983         }
2984         let m = k + 1;$0
2985         let h = 1 + m;
2986     }
2987 }"##,
2988             r##"
2989 fn foo() {
2990     loop {
2991         let n = 1;
2992         let m = fun_name();
2993         let h = 1 + m;
2994     }
2995 }
2996
2997 fn $0fun_name() -> i32 {
2998     let k = 1;
2999     loop {
3000         break;
3001     }
3002     let m = k + 1;
3003     m
3004 }"##,
3005         );
3006     }
3007
3008     #[test]
3009     fn break_from_nested_and_outer_loops() {
3010         check_assist(
3011             extract_function,
3012             r##"
3013 fn foo() {
3014     loop {
3015         let n = 1;
3016         $0let k = 1;
3017         loop {
3018             break;
3019         }
3020         if k == 42 {
3021             break;
3022         }
3023         let m = k + 1;$0
3024         let h = 1 + m;
3025     }
3026 }"##,
3027             r##"
3028 fn foo() {
3029     loop {
3030         let n = 1;
3031         let m = match fun_name() {
3032             Some(value) => value,
3033             None => break,
3034         };
3035         let h = 1 + m;
3036     }
3037 }
3038
3039 fn $0fun_name() -> Option<i32> {
3040     let k = 1;
3041     loop {
3042         break;
3043     }
3044     if k == 42 {
3045         return None;
3046     }
3047     let m = k + 1;
3048     Some(m)
3049 }"##,
3050         );
3051     }
3052
3053     #[test]
3054     fn return_from_nested_fn() {
3055         check_assist(
3056             extract_function,
3057             r##"
3058 fn foo() {
3059     loop {
3060         let n = 1;
3061         $0let k = 1;
3062         fn test() {
3063             return;
3064         }
3065         let m = k + 1;$0
3066         let h = 1 + m;
3067     }
3068 }"##,
3069             r##"
3070 fn foo() {
3071     loop {
3072         let n = 1;
3073         let m = fun_name();
3074         let h = 1 + m;
3075     }
3076 }
3077
3078 fn $0fun_name() -> i32 {
3079     let k = 1;
3080     fn test() {
3081         return;
3082     }
3083     let m = k + 1;
3084     m
3085 }"##,
3086         );
3087     }
3088
3089     #[test]
3090     fn break_with_value() {
3091         check_assist(
3092             extract_function,
3093             r##"
3094 fn foo() -> i32 {
3095     loop {
3096         let n = 1;
3097         $0let k = 1;
3098         if k == 42 {
3099             break 3;
3100         }
3101         let m = k + 1;$0
3102         let h = 1;
3103     }
3104 }"##,
3105             r##"
3106 fn foo() -> i32 {
3107     loop {
3108         let n = 1;
3109         if let Some(value) = fun_name() {
3110             break value;
3111         }
3112         let h = 1;
3113     }
3114 }
3115
3116 fn $0fun_name() -> Option<i32> {
3117     let k = 1;
3118     if k == 42 {
3119         return Some(3);
3120     }
3121     let m = k + 1;
3122     None
3123 }"##,
3124         );
3125     }
3126
3127     #[test]
3128     fn break_with_value_and_return() {
3129         check_assist(
3130             extract_function,
3131             r##"
3132 fn foo() -> i64 {
3133     loop {
3134         let n = 1;
3135         $0
3136         let k = 1;
3137         if k == 42 {
3138             break 3;
3139         }
3140         let m = k + 1;$0
3141         let h = 1 + m;
3142     }
3143 }"##,
3144             r##"
3145 fn foo() -> i64 {
3146     loop {
3147         let n = 1;
3148         let m = match fun_name() {
3149             Ok(value) => value,
3150             Err(value) => break value,
3151         };
3152         let h = 1 + m;
3153     }
3154 }
3155
3156 fn $0fun_name() -> Result<i32, i64> {
3157     let k = 1;
3158     if k == 42 {
3159         return Err(3);
3160     }
3161     let m = k + 1;
3162     Ok(m)
3163 }"##,
3164         );
3165     }
3166
3167     #[test]
3168     fn try_option() {
3169         check_assist(
3170             extract_function,
3171             r##"
3172 enum Option<T> { None, Some(T), }
3173 use Option::*;
3174 fn bar() -> Option<i32> { None }
3175 fn foo() -> Option<()> {
3176     let n = bar()?;
3177     $0let k = foo()?;
3178     let m = k + 1;$0
3179     let h = 1 + m;
3180     Some(())
3181 }"##,
3182             r##"
3183 enum Option<T> { None, Some(T), }
3184 use Option::*;
3185 fn bar() -> Option<i32> { None }
3186 fn foo() -> Option<()> {
3187     let n = bar()?;
3188     let m = fun_name()?;
3189     let h = 1 + m;
3190     Some(())
3191 }
3192
3193 fn $0fun_name() -> Option<i32> {
3194     let k = foo()?;
3195     let m = k + 1;
3196     Some(m)
3197 }"##,
3198         );
3199     }
3200
3201     #[test]
3202     fn try_option_unit() {
3203         check_assist(
3204             extract_function,
3205             r##"
3206 enum Option<T> { None, Some(T), }
3207 use Option::*;
3208 fn foo() -> Option<()> {
3209     let n = 1;
3210     $0let k = foo()?;
3211     let m = k + 1;$0
3212     let h = 1 + n;
3213     Some(())
3214 }"##,
3215             r##"
3216 enum Option<T> { None, Some(T), }
3217 use Option::*;
3218 fn foo() -> Option<()> {
3219     let n = 1;
3220     fun_name()?;
3221     let h = 1 + n;
3222     Some(())
3223 }
3224
3225 fn $0fun_name() -> Option<()> {
3226     let k = foo()?;
3227     let m = k + 1;
3228     Some(())
3229 }"##,
3230         );
3231     }
3232
3233     #[test]
3234     fn try_result() {
3235         check_assist(
3236             extract_function,
3237             r##"
3238 enum Result<T, E> { Ok(T), Err(E), }
3239 use Result::*;
3240 fn foo() -> Result<(), i64> {
3241     let n = 1;
3242     $0let k = foo()?;
3243     let m = k + 1;$0
3244     let h = 1 + m;
3245     Ok(())
3246 }"##,
3247             r##"
3248 enum Result<T, E> { Ok(T), Err(E), }
3249 use Result::*;
3250 fn foo() -> Result<(), i64> {
3251     let n = 1;
3252     let m = fun_name()?;
3253     let h = 1 + m;
3254     Ok(())
3255 }
3256
3257 fn $0fun_name() -> Result<i32, i64> {
3258     let k = foo()?;
3259     let m = k + 1;
3260     Ok(m)
3261 }"##,
3262         );
3263     }
3264
3265     #[test]
3266     fn try_option_with_return() {
3267         check_assist(
3268             extract_function,
3269             r##"
3270 enum Option<T> { None, Some(T) }
3271 use Option::*;
3272 fn foo() -> Option<()> {
3273     let n = 1;
3274     $0let k = foo()?;
3275     if k == 42 {
3276         return None;
3277     }
3278     let m = k + 1;$0
3279     let h = 1 + m;
3280     Some(())
3281 }"##,
3282             r##"
3283 enum Option<T> { None, Some(T) }
3284 use Option::*;
3285 fn foo() -> Option<()> {
3286     let n = 1;
3287     let m = fun_name()?;
3288     let h = 1 + m;
3289     Some(())
3290 }
3291
3292 fn $0fun_name() -> Option<i32> {
3293     let k = foo()?;
3294     if k == 42 {
3295         return None;
3296     }
3297     let m = k + 1;
3298     Some(m)
3299 }"##,
3300         );
3301     }
3302
3303     #[test]
3304     fn try_result_with_return() {
3305         check_assist(
3306             extract_function,
3307             r##"
3308 enum Result<T, E> { Ok(T), Err(E), }
3309 use Result::*;
3310 fn foo() -> Result<(), i64> {
3311     let n = 1;
3312     $0let k = foo()?;
3313     if k == 42 {
3314         return Err(1);
3315     }
3316     let m = k + 1;$0
3317     let h = 1 + m;
3318     Ok(())
3319 }"##,
3320             r##"
3321 enum Result<T, E> { Ok(T), Err(E), }
3322 use Result::*;
3323 fn foo() -> Result<(), i64> {
3324     let n = 1;
3325     let m = fun_name()?;
3326     let h = 1 + m;
3327     Ok(())
3328 }
3329
3330 fn $0fun_name() -> Result<i32, i64> {
3331     let k = foo()?;
3332     if k == 42 {
3333         return Err(1);
3334     }
3335     let m = k + 1;
3336     Ok(m)
3337 }"##,
3338         );
3339     }
3340
3341     #[test]
3342     fn try_and_break() {
3343         cov_mark::check!(external_control_flow_try_and_bc);
3344         check_assist_not_applicable(
3345             extract_function,
3346             r##"
3347 enum Option<T> { None, Some(T) }
3348 use Option::*;
3349 fn foo() -> Option<()> {
3350     loop {
3351         let n = Some(1);
3352         $0let m = n? + 1;
3353         break;
3354         let k = 2;
3355         let k = k + 1;$0
3356         let r = n + k;
3357     }
3358     Some(())
3359 }"##,
3360         );
3361     }
3362
3363     #[test]
3364     fn try_and_return_ok() {
3365         cov_mark::check!(external_control_flow_try_and_return_non_err);
3366         check_assist_not_applicable(
3367             extract_function,
3368             r##"
3369 enum Result<T, E> { Ok(T), Err(E), }
3370 use Result::*;
3371 fn foo() -> Result<(), i64> {
3372     let n = 1;
3373     $0let k = foo()?;
3374     if k == 42 {
3375         return Ok(1);
3376     }
3377     let m = k + 1;$0
3378     let h = 1 + m;
3379     Ok(())
3380 }"##,
3381         );
3382     }
3383 }