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