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