]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/extract_function.rs
63b0a91ce5a9a8a0c7e48737dff4f4e412148c45
[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, InFile, Local, ModuleDef, Semantics, TypeInfo};
6 use ide_db::{
7     defs::{Definition, NameRefClass},
8     helpers::{
9         insert_use::{insert_use, ImportScope},
10         mod_path_to_ast,
11         node_ext::{preorder_expr, walk_expr, walk_pat, walk_patterns_in_expr},
12         FamousDefs,
13     },
14     search::{FileReference, ReferenceCategory, SearchScope},
15     FxIndexSet, RootDatabase,
16 };
17 use itertools::Itertools;
18 use stdx::format_to;
19 use syntax::{
20     ast::{
21         self,
22         edit::{AstNodeEdit, IndentLevel},
23         AstNode,
24     },
25     match_ast, ted, SyntaxElement,
26     SyntaxKind::{self, COMMENT},
27     SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T,
28 };
29
30 use crate::{
31     assist_context::{AssistContext, Assists, TreeMutator},
32     AssistId,
33 };
34
35 // Assist: extract_function
36 //
37 // Extracts selected statements into new function.
38 //
39 // ```
40 // fn main() {
41 //     let n = 1;
42 //     $0let m = n + 2;
43 //     let k = m + n;$0
44 //     let g = 3;
45 // }
46 // ```
47 // ->
48 // ```
49 // fn main() {
50 //     let n = 1;
51 //     fun_name(n);
52 //     let g = 3;
53 // }
54 //
55 // fn $0fun_name(n: i32) {
56 //     let m = n + 2;
57 //     let k = m + n;
58 // }
59 // ```
60 pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
61     let range = ctx.selection_trimmed();
62     if range.is_empty() {
63         return None;
64     }
65
66     let node = ctx.covering_element();
67     if node.kind() == COMMENT {
68         cov_mark::hit!(extract_function_in_comment_is_not_applicable);
69         return None;
70     }
71
72     let node = match node {
73         syntax::NodeOrToken::Node(n) => n,
74         syntax::NodeOrToken::Token(t) => t.parent()?,
75     };
76     let body = extraction_target(&node, range)?;
77     let container_info = body.analyze_container(&ctx.sema)?;
78
79     let (locals_used, self_param) = body.analyze(&ctx.sema);
80
81     let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding };
82     let insert_after = node_to_insert_after(&body, anchor)?;
83     let module = ctx.sema.scope(&insert_after).module()?;
84
85     let ret_ty = body.return_ty(ctx)?;
86     let control_flow = body.external_control_flow(ctx, &container_info)?;
87     let ret_values = body.ret_values(ctx, node.parent().as_ref().unwrap_or(&node));
88
89     let target_range = body.text_range();
90
91     let scope = ImportScope::find_insert_use_container(&node, &ctx.sema)?;
92
93     acc.add(
94         AssistId("extract_function", crate::AssistKind::RefactorExtract),
95         "Extract into function",
96         target_range,
97         move |builder| {
98             let outliving_locals: Vec<_> = ret_values.collect();
99             if stdx::never!(!outliving_locals.is_empty() && !ret_ty.is_unit()) {
100                 // We should not have variables that outlive body if we have expression block
101                 return;
102             }
103
104             let params =
105                 body.extracted_function_params(ctx, &container_info, locals_used.iter().copied());
106
107             let fun = Function {
108                 name: make::name_ref("fun_name"),
109                 self_param,
110                 params,
111                 control_flow,
112                 ret_ty,
113                 body,
114                 outliving_locals,
115                 mods: container_info,
116             };
117
118             let new_indent = IndentLevel::from_node(&insert_after);
119             let old_indent = fun.body.indent_level();
120
121             builder.replace(target_range, make_call(ctx, &fun, old_indent));
122
123             let fn_def = format_function(ctx, module, &fun, old_indent, new_indent);
124             let insert_offset = insert_after.text_range().end();
125
126             if fn_def.contains("ControlFlow") {
127                 let scope = match scope {
128                     ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
129                     ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
130                     ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
131                 };
132
133                 let control_flow_enum =
134                     FamousDefs(&ctx.sema, Some(module.krate())).core_ops_ControlFlow();
135
136                 if let Some(control_flow_enum) = control_flow_enum {
137                     let mod_path = module.find_use_path_prefixed(
138                         ctx.sema.db,
139                         ModuleDef::from(control_flow_enum),
140                         ctx.config.insert_use.prefix_kind,
141                     );
142
143                     if let Some(mod_path) = mod_path {
144                         insert_use(&scope, mod_path_to_ast(&mod_path), &ctx.config.insert_use);
145                     }
146                 }
147             }
148
149             match ctx.config.snippet_cap {
150                 Some(cap) => builder.insert_snippet(cap, insert_offset, fn_def),
151                 None => builder.insert(insert_offset, fn_def),
152             };
153         },
154     )
155 }
156
157 /// Try to guess what user wants to extract
158 ///
159 /// We have basically have two cases:
160 /// * We want whole node, like `loop {}`, `2 + 2`, `{ let n = 1; }` exprs.
161 ///   Then we can use `ast::Expr`
162 /// * We want a few statements for a block. E.g.
163 ///   ```rust,no_run
164 ///   fn foo() -> i32 {
165 ///     let m = 1;
166 ///     $0
167 ///     let n = 2;
168 ///     let k = 3;
169 ///     k + n
170 ///     $0
171 ///   }
172 ///   ```
173 ///
174 fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<FunctionBody> {
175     if let Some(stmt) = ast::Stmt::cast(node.clone()) {
176         return match stmt {
177             ast::Stmt::Item(_) => None,
178             ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => Some(FunctionBody::from_range(
179                 node.parent().and_then(ast::StmtList::cast)?,
180                 node.text_range(),
181             )),
182         };
183     }
184
185     // Covering element returned the parent block of one or multiple statements that have been selected
186     if let Some(stmt_list) = ast::StmtList::cast(node.clone()) {
187         if let Some(block_expr) = stmt_list.syntax().parent().and_then(ast::BlockExpr::cast) {
188             if block_expr.syntax().text_range() == selection_range {
189                 return FunctionBody::from_expr(block_expr.into());
190             }
191         }
192
193         // Extract the full statements.
194         return Some(FunctionBody::from_range(stmt_list, selection_range));
195     }
196
197     let expr = ast::Expr::cast(node.clone())?;
198     // A node got selected fully
199     if node.text_range() == selection_range {
200         return FunctionBody::from_expr(expr);
201     }
202
203     node.ancestors().find_map(ast::Expr::cast).and_then(FunctionBody::from_expr)
204 }
205
206 #[derive(Debug)]
207 struct Function {
208     name: ast::NameRef,
209     self_param: Option<ast::SelfParam>,
210     params: Vec<Param>,
211     control_flow: ControlFlow,
212     ret_ty: RetType,
213     body: FunctionBody,
214     outliving_locals: Vec<OutlivedLocal>,
215     mods: ContainerInfo,
216 }
217
218 #[derive(Debug)]
219 struct Param {
220     var: Local,
221     ty: hir::Type,
222     move_local: bool,
223     requires_mut: bool,
224     is_copy: bool,
225 }
226
227 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
228 enum ParamKind {
229     Value,
230     MutValue,
231     SharedRef,
232     MutRef,
233 }
234
235 #[derive(Debug, Eq, PartialEq)]
236 enum FunType {
237     Unit,
238     Single(hir::Type),
239     Tuple(Vec<hir::Type>),
240 }
241
242 /// Where to put extracted function definition
243 #[derive(Debug)]
244 enum Anchor {
245     /// Extract free function and put right after current top-level function
246     Freestanding,
247     /// Extract method and put right after current function in the impl-block
248     Method,
249 }
250
251 // FIXME: ControlFlow and ContainerInfo both track some function modifiers, feels like these two should
252 // probably be merged somehow.
253 #[derive(Debug)]
254 struct ControlFlow {
255     kind: Option<FlowKind>,
256     is_async: bool,
257     is_unsafe: bool,
258 }
259
260 /// The thing whose expression we are extracting from. Can be a function, const, static, const arg, ...
261 #[derive(Clone, Debug)]
262 struct ContainerInfo {
263     is_const: bool,
264     is_in_tail: bool,
265     parent_loop: Option<SyntaxNode>,
266     /// The function's return type, const's type etc.
267     ret_type: Option<hir::Type>,
268 }
269
270 /// Control flow that is exported from extracted function
271 ///
272 /// E.g.:
273 /// ```rust,no_run
274 /// loop {
275 ///     $0
276 ///     if 42 == 42 {
277 ///         break;
278 ///     }
279 ///     $0
280 /// }
281 /// ```
282 #[derive(Debug, Clone)]
283 enum FlowKind {
284     /// Return with value (`return $expr;`)
285     Return(Option<ast::Expr>),
286     Try {
287         kind: TryKind,
288     },
289     /// Break with value (`break $expr;`)
290     Break(Option<ast::Expr>),
291     /// Continue
292     Continue,
293 }
294
295 #[derive(Debug, Clone)]
296 enum TryKind {
297     Option,
298     Result { ty: hir::Type },
299 }
300
301 #[derive(Debug)]
302 enum RetType {
303     Expr(hir::Type),
304     Stmt,
305 }
306
307 impl RetType {
308     fn is_unit(&self) -> bool {
309         match self {
310             RetType::Expr(ty) => ty.is_unit(),
311             RetType::Stmt => true,
312         }
313     }
314 }
315
316 /// Semantically same as `ast::Expr`, but preserves identity when using only part of the Block
317 /// This is the future function body, the part that is being extracted.
318 #[derive(Debug)]
319 enum FunctionBody {
320     Expr(ast::Expr),
321     Span { parent: ast::StmtList, text_range: TextRange },
322 }
323
324 #[derive(Debug)]
325 struct OutlivedLocal {
326     local: Local,
327     mut_usage_outside_body: bool,
328 }
329
330 /// Container of local variable usages
331 ///
332 /// Semanticall same as `UsageSearchResult`, but provides more convenient interface
333 struct LocalUsages(ide_db::search::UsageSearchResult);
334
335 impl LocalUsages {
336     fn find_local_usages(ctx: &AssistContext, var: Local) -> Self {
337         Self(
338             Definition::Local(var)
339                 .usages(&ctx.sema)
340                 .in_scope(SearchScope::single_file(ctx.file_id()))
341                 .all(),
342         )
343     }
344
345     fn iter(&self) -> impl Iterator<Item = &FileReference> + '_ {
346         self.0.iter().flat_map(|(_, rs)| rs)
347     }
348 }
349
350 impl Function {
351     fn return_type(&self, ctx: &AssistContext) -> FunType {
352         match &self.ret_ty {
353             RetType::Expr(ty) if ty.is_unit() => FunType::Unit,
354             RetType::Expr(ty) => FunType::Single(ty.clone()),
355             RetType::Stmt => match self.outliving_locals.as_slice() {
356                 [] => FunType::Unit,
357                 [var] => FunType::Single(var.local.ty(ctx.db())),
358                 vars => {
359                     let types = vars.iter().map(|v| v.local.ty(ctx.db())).collect();
360                     FunType::Tuple(types)
361                 }
362             },
363         }
364     }
365 }
366
367 impl ParamKind {
368     fn is_ref(&self) -> bool {
369         matches!(self, ParamKind::SharedRef | ParamKind::MutRef)
370     }
371 }
372
373 impl Param {
374     fn kind(&self) -> ParamKind {
375         match (self.move_local, self.requires_mut, self.is_copy) {
376             (false, true, _) => ParamKind::MutRef,
377             (false, false, false) => ParamKind::SharedRef,
378             (true, true, _) => ParamKind::MutValue,
379             (_, false, _) => ParamKind::Value,
380         }
381     }
382
383     fn to_arg(&self, ctx: &AssistContext) -> ast::Expr {
384         let var = path_expr_from_local(ctx, self.var);
385         match self.kind() {
386             ParamKind::Value | ParamKind::MutValue => var,
387             ParamKind::SharedRef => make::expr_ref(var, false),
388             ParamKind::MutRef => make::expr_ref(var, true),
389         }
390     }
391
392     fn to_param(&self, ctx: &AssistContext, module: hir::Module) -> ast::Param {
393         let var = self.var.name(ctx.db()).unwrap().to_string();
394         let var_name = make::name(&var);
395         let pat = match self.kind() {
396             ParamKind::MutValue => make::ident_pat(false, true, var_name),
397             ParamKind::Value | ParamKind::SharedRef | ParamKind::MutRef => {
398                 make::ext::simple_ident_pat(var_name)
399             }
400         };
401
402         let ty = make_ty(&self.ty, ctx, module);
403         let ty = match self.kind() {
404             ParamKind::Value | ParamKind::MutValue => ty,
405             ParamKind::SharedRef => make::ty_ref(ty, false),
406             ParamKind::MutRef => make::ty_ref(ty, true),
407         };
408
409         make::param(pat.into(), ty)
410     }
411 }
412
413 impl TryKind {
414     fn of_ty(ty: hir::Type, ctx: &AssistContext) -> Option<TryKind> {
415         if ty.is_unknown() {
416             // We favour Result for `expr?`
417             return Some(TryKind::Result { ty });
418         }
419         let adt = ty.as_adt()?;
420         let name = adt.name(ctx.db());
421         // FIXME: use lang items to determine if it is std type or user defined
422         //        E.g. if user happens to define type named `Option`, we would have false positive
423         match name.to_string().as_str() {
424             "Option" => Some(TryKind::Option),
425             "Result" => Some(TryKind::Result { ty }),
426             _ => None,
427         }
428     }
429 }
430
431 impl FlowKind {
432     fn make_result_handler(&self, expr: Option<ast::Expr>) -> ast::Expr {
433         match self {
434             FlowKind::Return(_) => make::expr_return(expr),
435             FlowKind::Break(_) => make::expr_break(expr),
436             FlowKind::Try { .. } => {
437                 stdx::never!("cannot have result handler with try");
438                 expr.unwrap_or_else(|| make::expr_return(None))
439             }
440             FlowKind::Continue => {
441                 stdx::always!(expr.is_none(), "continue with value is not possible");
442                 make::expr_continue()
443             }
444         }
445     }
446
447     fn expr_ty(&self, ctx: &AssistContext) -> Option<hir::Type> {
448         match self {
449             FlowKind::Return(Some(expr)) | FlowKind::Break(Some(expr)) => {
450                 ctx.sema.type_of_expr(expr).map(TypeInfo::adjusted)
451             }
452             FlowKind::Try { .. } => {
453                 stdx::never!("try does not have defined expr_ty");
454                 None
455             }
456             _ => None,
457         }
458     }
459 }
460
461 impl FunctionBody {
462     fn parent(&self) -> Option<SyntaxNode> {
463         match self {
464             FunctionBody::Expr(expr) => expr.syntax().parent(),
465             FunctionBody::Span { parent, .. } => Some(parent.syntax().clone()),
466         }
467     }
468
469     fn from_expr(expr: ast::Expr) -> Option<Self> {
470         match expr {
471             ast::Expr::BreakExpr(it) => it.expr().map(Self::Expr),
472             ast::Expr::ReturnExpr(it) => it.expr().map(Self::Expr),
473             ast::Expr::BlockExpr(it) if !it.is_standalone() => None,
474             expr => Some(Self::Expr(expr)),
475         }
476     }
477
478     fn from_range(parent: ast::StmtList, selected: TextRange) -> FunctionBody {
479         let mut text_range = parent
480             .statements()
481             .map(|stmt| stmt.syntax().text_range())
482             .filter(|&stmt| selected.intersect(stmt).filter(|it| !it.is_empty()).is_some())
483             .reduce(|acc, stmt| acc.cover(stmt));
484         if let Some(tail_range) = parent
485             .tail_expr()
486             .map(|it| it.syntax().text_range())
487             .filter(|&it| selected.intersect(it).is_some())
488         {
489             text_range = Some(match text_range {
490                 Some(text_range) => text_range.cover(tail_range),
491                 None => tail_range,
492             });
493         }
494         Self::Span { parent, text_range: text_range.unwrap_or(selected) }
495     }
496
497     fn indent_level(&self) -> IndentLevel {
498         match &self {
499             FunctionBody::Expr(expr) => IndentLevel::from_node(expr.syntax()),
500             FunctionBody::Span { parent, .. } => IndentLevel::from_node(parent.syntax()) + 1,
501         }
502     }
503
504     fn tail_expr(&self) -> Option<ast::Expr> {
505         match &self {
506             FunctionBody::Expr(expr) => Some(expr.clone()),
507             FunctionBody::Span { parent, text_range } => {
508                 let tail_expr = parent.tail_expr()?;
509                 text_range.contains_range(tail_expr.syntax().text_range()).then(|| tail_expr)
510             }
511         }
512     }
513
514     fn walk_expr(&self, cb: &mut dyn FnMut(ast::Expr)) {
515         match self {
516             FunctionBody::Expr(expr) => walk_expr(expr, cb),
517             FunctionBody::Span { parent, text_range } => {
518                 parent
519                     .statements()
520                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
521                     .filter_map(|stmt| match stmt {
522                         ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(),
523                         ast::Stmt::Item(_) => None,
524                         ast::Stmt::LetStmt(stmt) => stmt.initializer(),
525                     })
526                     .for_each(|expr| walk_expr(&expr, cb));
527                 if let Some(expr) = parent
528                     .tail_expr()
529                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
530                 {
531                     walk_expr(&expr, cb);
532                 }
533             }
534         }
535     }
536
537     fn preorder_expr(&self, cb: &mut dyn FnMut(WalkEvent<ast::Expr>) -> bool) {
538         match self {
539             FunctionBody::Expr(expr) => preorder_expr(expr, cb),
540             FunctionBody::Span { parent, text_range } => {
541                 parent
542                     .statements()
543                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
544                     .filter_map(|stmt| match stmt {
545                         ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(),
546                         ast::Stmt::Item(_) => None,
547                         ast::Stmt::LetStmt(stmt) => stmt.initializer(),
548                     })
549                     .for_each(|expr| preorder_expr(&expr, cb));
550                 if let Some(expr) = parent
551                     .tail_expr()
552                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
553                 {
554                     preorder_expr(&expr, cb);
555                 }
556             }
557         }
558     }
559
560     fn walk_pat(&self, cb: &mut dyn FnMut(ast::Pat)) {
561         match self {
562             FunctionBody::Expr(expr) => walk_patterns_in_expr(expr, cb),
563             FunctionBody::Span { parent, text_range } => {
564                 parent
565                     .statements()
566                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
567                     .for_each(|stmt| match stmt {
568                         ast::Stmt::ExprStmt(expr_stmt) => {
569                             if let Some(expr) = expr_stmt.expr() {
570                                 walk_patterns_in_expr(&expr, cb)
571                             }
572                         }
573                         ast::Stmt::Item(_) => (),
574                         ast::Stmt::LetStmt(stmt) => {
575                             if let Some(pat) = stmt.pat() {
576                                 walk_pat(&pat, cb);
577                             }
578                             if let Some(expr) = stmt.initializer() {
579                                 walk_patterns_in_expr(&expr, cb);
580                             }
581                         }
582                     });
583                 if let Some(expr) = parent
584                     .tail_expr()
585                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
586                 {
587                     walk_patterns_in_expr(&expr, cb);
588                 }
589             }
590         }
591     }
592
593     fn text_range(&self) -> TextRange {
594         match self {
595             FunctionBody::Expr(expr) => expr.syntax().text_range(),
596             &FunctionBody::Span { text_range, .. } => text_range,
597         }
598     }
599
600     fn contains_range(&self, range: TextRange) -> bool {
601         self.text_range().contains_range(range)
602     }
603
604     fn precedes_range(&self, range: TextRange) -> bool {
605         self.text_range().end() <= range.start()
606     }
607
608     fn contains_node(&self, node: &SyntaxNode) -> bool {
609         self.contains_range(node.text_range())
610     }
611 }
612
613 impl FunctionBody {
614     /// Analyzes a function body, returning the used local variables that are referenced in it as well as
615     /// whether it contains an await expression.
616     fn analyze(
617         &self,
618         sema: &Semantics<RootDatabase>,
619     ) -> (FxIndexSet<Local>, Option<ast::SelfParam>) {
620         let mut self_param = None;
621         let mut res = FxIndexSet::default();
622         let mut cb = |name_ref: Option<_>| {
623             let local_ref =
624                 match name_ref.and_then(|name_ref| NameRefClass::classify(sema, &name_ref)) {
625                     Some(
626                         NameRefClass::Definition(Definition::Local(local_ref))
627                         | NameRefClass::FieldShorthand { local_ref, field_ref: _ },
628                     ) => local_ref,
629                     _ => return,
630                 };
631             let InFile { file_id, value } = local_ref.source(sema.db);
632             // locals defined inside macros are not relevant to us
633             if !file_id.is_macro() {
634                 match value {
635                     Either::Right(it) => {
636                         self_param.replace(it);
637                     }
638                     Either::Left(_) => {
639                         res.insert(local_ref);
640                     }
641                 }
642             }
643         };
644         self.walk_expr(&mut |expr| match expr {
645             ast::Expr::PathExpr(path_expr) => {
646                 cb(path_expr.path().and_then(|it| it.as_single_name_ref()))
647             }
648             ast::Expr::MacroCall(call) => {
649                 if let Some(tt) = call.token_tree() {
650                     tt.syntax()
651                         .children_with_tokens()
652                         .flat_map(SyntaxElement::into_token)
653                         .filter(|it| it.kind() == SyntaxKind::IDENT)
654                         .flat_map(|t| sema.descend_into_macros(t))
655                         .for_each(|t| cb(t.parent().and_then(ast::NameRef::cast)));
656                 }
657             }
658             _ => (),
659         });
660         (res, self_param)
661     }
662
663     fn analyze_container(&self, sema: &Semantics<RootDatabase>) -> Option<ContainerInfo> {
664         let mut ancestors = self.parent()?.ancestors();
665         let infer_expr_opt = |expr| sema.type_of_expr(&expr?).map(TypeInfo::adjusted);
666         let mut parent_loop = None;
667         let mut set_parent_loop = |loop_: &dyn ast::HasLoopBody| {
668             if loop_
669                 .loop_body()
670                 .map_or(false, |it| it.syntax().text_range().contains_range(self.text_range()))
671             {
672                 parent_loop.get_or_insert(loop_.syntax().clone());
673             }
674         };
675         let (is_const, expr, ty) = loop {
676             let anc = ancestors.next()?;
677             break match_ast! {
678                 match anc {
679                     ast::ClosureExpr(closure) => (false, closure.body(), infer_expr_opt(closure.body())),
680                     ast::BlockExpr(block_expr) => {
681                         let (constness, block) = match block_expr.modifier() {
682                             Some(ast::BlockModifier::Const(_)) => (true, block_expr),
683                             Some(ast::BlockModifier::Try(_)) => (false, block_expr),
684                             Some(ast::BlockModifier::Label(label)) if label.lifetime().is_some() => (false, block_expr),
685                             _ => continue,
686                         };
687                         let expr = Some(ast::Expr::BlockExpr(block));
688                         (constness, expr.clone(), infer_expr_opt(expr))
689                     },
690                     ast::Fn(fn_) => {
691                         (fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(sema.to_def(&fn_)?.ret_type(sema.db)))
692                     },
693                     ast::Static(statik) => {
694                         (true, statik.body(), Some(sema.to_def(&statik)?.ty(sema.db)))
695                     },
696                     ast::ConstArg(ca) => {
697                         (true, ca.expr(), infer_expr_opt(ca.expr()))
698                     },
699                     ast::Const(konst) => {
700                         (true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db)))
701                     },
702                     ast::ConstParam(cp) => {
703                         (true, cp.default_val(), Some(sema.to_def(&cp)?.ty(sema.db)))
704                     },
705                     ast::ConstBlockPat(cbp) => {
706                         let expr = cbp.block_expr().map(ast::Expr::BlockExpr);
707                         (true, expr.clone(), infer_expr_opt(expr))
708                     },
709                     ast::Variant(__) => return None,
710                     ast::Meta(__) => return None,
711                     ast::LoopExpr(it) => {
712                         set_parent_loop(&it);
713                         continue;
714                     },
715                     ast::ForExpr(it) => {
716                         set_parent_loop(&it);
717                         continue;
718                     },
719                     ast::WhileExpr(it) => {
720                         set_parent_loop(&it);
721                         continue;
722                     },
723                     _ => continue,
724                 }
725             };
726         };
727         let container_tail = match expr? {
728             ast::Expr::BlockExpr(block) => block.tail_expr(),
729             expr => Some(expr),
730         };
731         let is_in_tail =
732             container_tail.zip(self.tail_expr()).map_or(false, |(container_tail, body_tail)| {
733                 container_tail.syntax().text_range().contains_range(body_tail.syntax().text_range())
734             });
735         Some(ContainerInfo { is_in_tail, is_const, parent_loop, ret_type: ty })
736     }
737
738     fn return_ty(&self, ctx: &AssistContext) -> Option<RetType> {
739         match self.tail_expr() {
740             Some(expr) => ctx.sema.type_of_expr(&expr).map(TypeInfo::original).map(RetType::Expr),
741             None => Some(RetType::Stmt),
742         }
743     }
744
745     /// Local variables defined inside `body` that are accessed outside of it
746     fn ret_values<'a>(
747         &self,
748         ctx: &'a AssistContext,
749         parent: &SyntaxNode,
750     ) -> impl Iterator<Item = OutlivedLocal> + 'a {
751         let parent = parent.clone();
752         let range = self.text_range();
753         locals_defined_in_body(&ctx.sema, self)
754             .into_iter()
755             .filter_map(move |local| local_outlives_body(ctx, range, local, &parent))
756     }
757
758     /// Analyses the function body for external control flow.
759     fn external_control_flow(
760         &self,
761         ctx: &AssistContext,
762         container_info: &ContainerInfo,
763     ) -> Option<ControlFlow> {
764         let mut ret_expr = None;
765         let mut try_expr = None;
766         let mut break_expr = None;
767         let mut continue_expr = None;
768         let mut is_async = false;
769         let mut _is_unsafe = false;
770
771         let mut unsafe_depth = 0;
772         let mut loop_depth = 0;
773
774         self.preorder_expr(&mut |expr| {
775             let expr = match expr {
776                 WalkEvent::Enter(e) => e,
777                 WalkEvent::Leave(expr) => {
778                     match expr {
779                         ast::Expr::LoopExpr(_)
780                         | ast::Expr::ForExpr(_)
781                         | ast::Expr::WhileExpr(_) => loop_depth -= 1,
782                         ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
783                             unsafe_depth -= 1
784                         }
785                         _ => (),
786                     }
787                     return false;
788                 }
789             };
790             match expr {
791                 ast::Expr::LoopExpr(_) | ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) => {
792                     loop_depth += 1;
793                 }
794                 ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
795                     unsafe_depth += 1
796                 }
797                 ast::Expr::ReturnExpr(it) => {
798                     ret_expr = Some(it);
799                 }
800                 ast::Expr::TryExpr(it) => {
801                     try_expr = Some(it);
802                 }
803                 ast::Expr::BreakExpr(it) if loop_depth == 0 => {
804                     break_expr = Some(it);
805                 }
806                 ast::Expr::ContinueExpr(it) if loop_depth == 0 => {
807                     continue_expr = Some(it);
808                 }
809                 ast::Expr::AwaitExpr(_) => is_async = true,
810                 // FIXME: Do unsafe analysis on expression, sem highlighting knows this so we should be able
811                 // to just lift that out of there
812                 // expr if unsafe_depth ==0 && expr.is_unsafe => is_unsafe = true,
813                 _ => {}
814             }
815             false
816         });
817
818         let kind = match (try_expr, ret_expr, break_expr, continue_expr) {
819             (Some(_), _, None, None) => {
820                 let ret_ty = container_info.ret_type.clone()?;
821                 let kind = TryKind::of_ty(ret_ty, ctx)?;
822
823                 Some(FlowKind::Try { kind })
824             }
825             (Some(_), _, _, _) => {
826                 cov_mark::hit!(external_control_flow_try_and_bc);
827                 return None;
828             }
829             (None, Some(r), None, None) => Some(FlowKind::Return(r.expr())),
830             (None, Some(_), _, _) => {
831                 cov_mark::hit!(external_control_flow_return_and_bc);
832                 return None;
833             }
834             (None, None, Some(_), Some(_)) => {
835                 cov_mark::hit!(external_control_flow_break_and_continue);
836                 return None;
837             }
838             (None, None, Some(b), None) => Some(FlowKind::Break(b.expr())),
839             (None, None, None, Some(_)) => Some(FlowKind::Continue),
840             (None, None, None, None) => None,
841         };
842
843         Some(ControlFlow { kind, is_async, is_unsafe: _is_unsafe })
844     }
845
846     /// find variables that should be extracted as params
847     ///
848     /// Computes additional info that affects param type and mutability
849     fn extracted_function_params(
850         &self,
851         ctx: &AssistContext,
852         container_info: &ContainerInfo,
853         locals: impl Iterator<Item = Local>,
854     ) -> Vec<Param> {
855         locals
856             .map(|local| (local, local.source(ctx.db())))
857             .filter(|(_, src)| is_defined_outside_of_body(ctx, self, src))
858             .filter_map(|(local, src)| match src.value {
859                 Either::Left(src) => Some((local, src)),
860                 Either::Right(_) => {
861                     stdx::never!(false, "Local::is_self returned false, but source is SelfParam");
862                     None
863                 }
864             })
865             .map(|(var, src)| {
866                 let usages = LocalUsages::find_local_usages(ctx, var);
867                 let ty = var.ty(ctx.db());
868
869                 let defined_outside_parent_loop = container_info
870                     .parent_loop
871                     .as_ref()
872                     .map_or(true, |it| it.text_range().contains_range(src.syntax().text_range()));
873
874                 let is_copy = ty.is_copy(ctx.db());
875                 let has_usages = self.has_usages_after_body(&usages);
876                 let requires_mut =
877                     !ty.is_mutable_reference() && has_exclusive_usages(ctx, &usages, self);
878                 // We can move the value into the function call if it's not used after the call,
879                 // if the var is not used but defined outside a loop we are extracting from we can't move it either
880                 // as the function will reuse it in the next iteration.
881                 let move_local = !has_usages && defined_outside_parent_loop;
882                 Param { var, ty, move_local, requires_mut, is_copy }
883             })
884             .collect()
885     }
886
887     fn has_usages_after_body(&self, usages: &LocalUsages) -> bool {
888         usages.iter().any(|reference| self.precedes_range(reference.range))
889     }
890 }
891
892 /// checks if relevant var is used with `&mut` access inside body
893 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
894     usages
895         .iter()
896         .filter(|reference| body.contains_range(reference.range))
897         .any(|reference| reference_is_exclusive(reference, body, ctx))
898 }
899
900 /// checks if this reference requires `&mut` access inside node
901 fn reference_is_exclusive(
902     reference: &FileReference,
903     node: &dyn HasTokenAtOffset,
904     ctx: &AssistContext,
905 ) -> bool {
906     // we directly modify variable with set: `n = 0`, `n += 1`
907     if reference.category == Some(ReferenceCategory::Write) {
908         return true;
909     }
910
911     // we take `&mut` reference to variable: `&mut v`
912     let path = match path_element_of_reference(node, reference) {
913         Some(path) => path,
914         None => return false,
915     };
916
917     expr_require_exclusive_access(ctx, &path).unwrap_or(false)
918 }
919
920 /// checks if this expr requires `&mut` access, recurses on field access
921 fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
922     if let ast::Expr::MacroCall(_) = expr {
923         // FIXME: expand macro and check output for mutable usages of the variable?
924         return None;
925     }
926
927     let parent = expr.syntax().parent()?;
928
929     if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
930         if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
931             return Some(bin_expr.lhs()?.syntax() == expr.syntax());
932         }
933         return Some(false);
934     }
935
936     if let Some(ref_expr) = ast::RefExpr::cast(parent.clone()) {
937         return Some(ref_expr.mut_token().is_some());
938     }
939
940     if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
941         let func = ctx.sema.resolve_method_call(&method_call)?;
942         let self_param = func.self_param(ctx.db())?;
943         let access = self_param.access(ctx.db());
944
945         return Some(matches!(access, hir::Access::Exclusive));
946     }
947
948     if let Some(field) = ast::FieldExpr::cast(parent) {
949         return expr_require_exclusive_access(ctx, &field.into());
950     }
951
952     Some(false)
953 }
954
955 trait HasTokenAtOffset {
956     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken>;
957 }
958
959 impl HasTokenAtOffset for SyntaxNode {
960     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
961         SyntaxNode::token_at_offset(self, offset)
962     }
963 }
964
965 impl HasTokenAtOffset for FunctionBody {
966     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
967         match self {
968             FunctionBody::Expr(expr) => expr.syntax().token_at_offset(offset),
969             FunctionBody::Span { parent, text_range } => {
970                 match parent.syntax().token_at_offset(offset) {
971                     TokenAtOffset::None => TokenAtOffset::None,
972                     TokenAtOffset::Single(t) => {
973                         if text_range.contains_range(t.text_range()) {
974                             TokenAtOffset::Single(t)
975                         } else {
976                             TokenAtOffset::None
977                         }
978                     }
979                     TokenAtOffset::Between(a, b) => {
980                         match (
981                             text_range.contains_range(a.text_range()),
982                             text_range.contains_range(b.text_range()),
983                         ) {
984                             (true, true) => TokenAtOffset::Between(a, b),
985                             (true, false) => TokenAtOffset::Single(a),
986                             (false, true) => TokenAtOffset::Single(b),
987                             (false, false) => TokenAtOffset::None,
988                         }
989                     }
990                 }
991             }
992         }
993     }
994 }
995
996 /// find relevant `ast::Expr` for reference
997 ///
998 /// # Preconditions
999 ///
1000 /// `node` must cover `reference`, that is `node.text_range().contains_range(reference.range)`
1001 fn path_element_of_reference(
1002     node: &dyn HasTokenAtOffset,
1003     reference: &FileReference,
1004 ) -> Option<ast::Expr> {
1005     let token = node.token_at_offset(reference.range.start()).right_biased().or_else(|| {
1006         stdx::never!(false, "cannot find token at variable usage: {:?}", reference);
1007         None
1008     })?;
1009     let path = token.ancestors().find_map(ast::Expr::cast).or_else(|| {
1010         stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
1011         None
1012     })?;
1013     stdx::always!(
1014         matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
1015         "unexpected expression type for variable usage: {:?}",
1016         path
1017     );
1018     Some(path)
1019 }
1020
1021 /// list local variables defined inside `body`
1022 fn locals_defined_in_body(
1023     sema: &Semantics<RootDatabase>,
1024     body: &FunctionBody,
1025 ) -> FxIndexSet<Local> {
1026     // FIXME: this doesn't work well with macros
1027     //        see https://github.com/rust-analyzer/rust-analyzer/pull/7535#discussion_r570048550
1028     let mut res = FxIndexSet::default();
1029     body.walk_pat(&mut |pat| {
1030         if let ast::Pat::IdentPat(pat) = pat {
1031             if let Some(local) = sema.to_def(&pat) {
1032                 res.insert(local);
1033             }
1034         }
1035     });
1036     res
1037 }
1038
1039 /// Returns usage details if local variable is used after(outside of) body
1040 fn local_outlives_body(
1041     ctx: &AssistContext,
1042     body_range: TextRange,
1043     local: Local,
1044     parent: &SyntaxNode,
1045 ) -> Option<OutlivedLocal> {
1046     let usages = LocalUsages::find_local_usages(ctx, local);
1047     let mut has_mut_usages = false;
1048     let mut any_outlives = false;
1049     for usage in usages.iter() {
1050         if body_range.end() <= usage.range.start() {
1051             has_mut_usages |= reference_is_exclusive(usage, parent, ctx);
1052             any_outlives |= true;
1053             if has_mut_usages {
1054                 break; // no need to check more elements we have all the info we wanted
1055             }
1056         }
1057     }
1058     if !any_outlives {
1059         return None;
1060     }
1061     Some(OutlivedLocal { local, mut_usage_outside_body: has_mut_usages })
1062 }
1063
1064 /// checks if the relevant local was defined before(outside of) body
1065 fn is_defined_outside_of_body(
1066     ctx: &AssistContext,
1067     body: &FunctionBody,
1068     src: &hir::InFile<Either<ast::IdentPat, ast::SelfParam>>,
1069 ) -> bool {
1070     src.file_id.original_file(ctx.db()) == ctx.file_id()
1071         && !body.contains_node(either_syntax(&src.value))
1072 }
1073
1074 fn either_syntax(value: &Either<ast::IdentPat, ast::SelfParam>) -> &SyntaxNode {
1075     match value {
1076         Either::Left(pat) => pat.syntax(),
1077         Either::Right(it) => it.syntax(),
1078     }
1079 }
1080
1081 /// find where to put extracted function definition
1082 ///
1083 /// Function should be put right after returned node
1084 fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNode> {
1085     let node = match body {
1086         FunctionBody::Expr(e) => e.syntax(),
1087         FunctionBody::Span { parent, .. } => parent.syntax(),
1088     };
1089     let mut ancestors = node.ancestors().peekable();
1090     let mut last_ancestor = None;
1091     while let Some(next_ancestor) = ancestors.next() {
1092         match next_ancestor.kind() {
1093             SyntaxKind::SOURCE_FILE => break,
1094             SyntaxKind::ITEM_LIST if !matches!(anchor, Anchor::Freestanding) => continue,
1095             SyntaxKind::ITEM_LIST => {
1096                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
1097                     break;
1098                 }
1099             }
1100             SyntaxKind::ASSOC_ITEM_LIST if !matches!(anchor, Anchor::Method) => {
1101                 continue;
1102             }
1103             SyntaxKind::ASSOC_ITEM_LIST => {
1104                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::IMPL) {
1105                     break;
1106                 }
1107             }
1108             _ => (),
1109         }
1110         last_ancestor = Some(next_ancestor);
1111     }
1112     last_ancestor
1113 }
1114
1115 fn make_call(ctx: &AssistContext, fun: &Function, indent: IndentLevel) -> String {
1116     let ret_ty = fun.return_type(ctx);
1117
1118     let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx)));
1119     let name = fun.name.clone();
1120     let mut call_expr = if fun.self_param.is_some() {
1121         let self_arg = make::expr_path(make::ext::ident_path("self"));
1122         make::expr_method_call(self_arg, name, args)
1123     } else {
1124         let func = make::expr_path(make::path_unqualified(make::path_segment(name)));
1125         make::expr_call(func, args)
1126     };
1127
1128     let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1129
1130     if fun.control_flow.is_async {
1131         call_expr = make::expr_await(call_expr);
1132     }
1133     let expr = handler.make_call_expr(call_expr).indent(indent);
1134
1135     let mut_modifier = |var: &OutlivedLocal| if var.mut_usage_outside_body { "mut " } else { "" };
1136
1137     let mut buf = String::new();
1138     match fun.outliving_locals.as_slice() {
1139         [] => {}
1140         [var] => {
1141             format_to!(buf, "let {}{} = ", mut_modifier(var), var.local.name(ctx.db()).unwrap())
1142         }
1143         vars => {
1144             buf.push_str("let (");
1145             let bindings = vars.iter().format_with(", ", |local, f| {
1146                 f(&format_args!("{}{}", mut_modifier(local), local.local.name(ctx.db()).unwrap()))
1147             });
1148             format_to!(buf, "{}", bindings);
1149             buf.push_str(") = ");
1150         }
1151     }
1152
1153     format_to!(buf, "{}", expr);
1154     let insert_comma = fun
1155         .body
1156         .parent()
1157         .and_then(ast::MatchArm::cast)
1158         .map_or(false, |it| it.comma_token().is_none());
1159     if insert_comma {
1160         buf.push(',');
1161     } else if fun.ret_ty.is_unit() && (!fun.outliving_locals.is_empty() || !expr.is_block_like()) {
1162         buf.push(';');
1163     }
1164     buf
1165 }
1166
1167 enum FlowHandler {
1168     None,
1169     Try { kind: TryKind },
1170     If { action: FlowKind },
1171     IfOption { action: FlowKind },
1172     MatchOption { none: FlowKind },
1173     MatchResult { err: FlowKind },
1174 }
1175
1176 impl FlowHandler {
1177     fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
1178         match &fun.control_flow.kind {
1179             None => FlowHandler::None,
1180             Some(flow_kind) => {
1181                 let action = flow_kind.clone();
1182                 if *ret_ty == FunType::Unit {
1183                     match flow_kind {
1184                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1185                             FlowHandler::If { action }
1186                         }
1187                         FlowKind::Return(_) | FlowKind::Break(_) => {
1188                             FlowHandler::IfOption { action }
1189                         }
1190                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1191                     }
1192                 } else {
1193                     match flow_kind {
1194                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1195                             FlowHandler::MatchOption { none: action }
1196                         }
1197                         FlowKind::Return(_) | FlowKind::Break(_) => {
1198                             FlowHandler::MatchResult { err: action }
1199                         }
1200                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1201                     }
1202                 }
1203             }
1204         }
1205     }
1206
1207     fn make_call_expr(&self, call_expr: ast::Expr) -> ast::Expr {
1208         match self {
1209             FlowHandler::None => call_expr,
1210             FlowHandler::Try { kind: _ } => make::expr_try(call_expr),
1211             FlowHandler::If { action } => {
1212                 let action = action.make_result_handler(None);
1213                 let stmt = make::expr_stmt(action);
1214                 let block = make::block_expr(iter::once(stmt.into()), None);
1215                 let controlflow_break_path = make::path_from_text("ControlFlow::Break");
1216                 let condition = make::condition(
1217                     call_expr,
1218                     Some(
1219                         make::tuple_struct_pat(
1220                             controlflow_break_path,
1221                             iter::once(make::wildcard_pat().into()),
1222                         )
1223                         .into(),
1224                     ),
1225                 );
1226                 make::expr_if(condition, block, None)
1227             }
1228             FlowHandler::IfOption { action } => {
1229                 let path = make::ext::ident_path("Some");
1230                 let value_pat = make::ext::simple_ident_pat(make::name("value"));
1231                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1232                 let cond = make::condition(call_expr, Some(pattern.into()));
1233                 let value = make::expr_path(make::ext::ident_path("value"));
1234                 let action_expr = action.make_result_handler(Some(value));
1235                 let action_stmt = make::expr_stmt(action_expr);
1236                 let then = make::block_expr(iter::once(action_stmt.into()), None);
1237                 make::expr_if(cond, then, None)
1238             }
1239             FlowHandler::MatchOption { none } => {
1240                 let some_name = "value";
1241
1242                 let some_arm = {
1243                     let path = make::ext::ident_path("Some");
1244                     let value_pat = make::ext::simple_ident_pat(make::name(some_name));
1245                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1246                     let value = make::expr_path(make::ext::ident_path(some_name));
1247                     make::match_arm(iter::once(pat.into()), None, value)
1248                 };
1249                 let none_arm = {
1250                     let path = make::ext::ident_path("None");
1251                     let pat = make::path_pat(path);
1252                     make::match_arm(iter::once(pat), None, none.make_result_handler(None))
1253                 };
1254                 let arms = make::match_arm_list(vec![some_arm, none_arm]);
1255                 make::expr_match(call_expr, arms)
1256             }
1257             FlowHandler::MatchResult { err } => {
1258                 let ok_name = "value";
1259                 let err_name = "value";
1260
1261                 let ok_arm = {
1262                     let path = make::ext::ident_path("Ok");
1263                     let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
1264                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1265                     let value = make::expr_path(make::ext::ident_path(ok_name));
1266                     make::match_arm(iter::once(pat.into()), None, value)
1267                 };
1268                 let err_arm = {
1269                     let path = make::ext::ident_path("Err");
1270                     let value_pat = make::ext::simple_ident_pat(make::name(err_name));
1271                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1272                     let value = make::expr_path(make::ext::ident_path(err_name));
1273                     make::match_arm(
1274                         iter::once(pat.into()),
1275                         None,
1276                         err.make_result_handler(Some(value)),
1277                     )
1278                 };
1279                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1280                 make::expr_match(call_expr, arms)
1281             }
1282         }
1283     }
1284 }
1285
1286 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1287     let name = var.name(ctx.db()).unwrap().to_string();
1288     make::expr_path(make::ext::ident_path(&name))
1289 }
1290
1291 fn format_function(
1292     ctx: &AssistContext,
1293     module: hir::Module,
1294     fun: &Function,
1295     old_indent: IndentLevel,
1296     new_indent: IndentLevel,
1297 ) -> String {
1298     let mut fn_def = String::new();
1299     let params = fun.make_param_list(ctx, module);
1300     let ret_ty = fun.make_ret_ty(ctx, module);
1301     let body = make_body(ctx, old_indent, new_indent, fun);
1302     let const_kw = if fun.mods.is_const { "const " } else { "" };
1303     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
1304     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
1305     match ctx.config.snippet_cap {
1306         Some(_) => format_to!(
1307             fn_def,
1308             "\n\n{}{}{}{}fn $0{}{}",
1309             new_indent,
1310             const_kw,
1311             async_kw,
1312             unsafe_kw,
1313             fun.name,
1314             params
1315         ),
1316         None => format_to!(
1317             fn_def,
1318             "\n\n{}{}{}{}fn {}{}",
1319             new_indent,
1320             const_kw,
1321             async_kw,
1322             unsafe_kw,
1323             fun.name,
1324             params
1325         ),
1326     }
1327     if let Some(ret_ty) = ret_ty {
1328         format_to!(fn_def, " {}", ret_ty);
1329     }
1330     format_to!(fn_def, " {}", body);
1331
1332     fn_def
1333 }
1334
1335 impl Function {
1336     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
1337         let self_param = self.self_param.clone();
1338         let params = self.params.iter().map(|param| param.to_param(ctx, module));
1339         make::param_list(self_param, params)
1340     }
1341
1342     fn make_ret_ty(&self, ctx: &AssistContext, module: hir::Module) -> Option<ast::RetType> {
1343         let fun_ty = self.return_type(ctx);
1344         let handler = if self.mods.is_in_tail {
1345             FlowHandler::None
1346         } else {
1347             FlowHandler::from_ret_ty(self, &fun_ty)
1348         };
1349         let ret_ty = match &handler {
1350             FlowHandler::None => {
1351                 if matches!(fun_ty, FunType::Unit) {
1352                     return None;
1353                 }
1354                 fun_ty.make_ty(ctx, module)
1355             }
1356             FlowHandler::Try { kind: TryKind::Option } => {
1357                 make::ext::ty_option(fun_ty.make_ty(ctx, module))
1358             }
1359             FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1360                 let handler_ty = parent_ret_ty
1361                     .type_arguments()
1362                     .nth(1)
1363                     .map(|ty| make_ty(&ty, ctx, module))
1364                     .unwrap_or_else(make::ty_placeholder);
1365                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1366             }
1367             FlowHandler::If { .. } => make::ty("ControlFlow<()>"),
1368             FlowHandler::IfOption { action } => {
1369                 let handler_ty = action
1370                     .expr_ty(ctx)
1371                     .map(|ty| make_ty(&ty, ctx, module))
1372                     .unwrap_or_else(make::ty_placeholder);
1373                 make::ext::ty_option(handler_ty)
1374             }
1375             FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1376             FlowHandler::MatchResult { err } => {
1377                 let handler_ty = err
1378                     .expr_ty(ctx)
1379                     .map(|ty| make_ty(&ty, ctx, module))
1380                     .unwrap_or_else(make::ty_placeholder);
1381                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1382             }
1383         };
1384         Some(make::ret_type(ret_ty))
1385     }
1386 }
1387
1388 impl FunType {
1389     fn make_ty(&self, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1390         match self {
1391             FunType::Unit => make::ty_unit(),
1392             FunType::Single(ty) => make_ty(ty, ctx, module),
1393             FunType::Tuple(types) => match types.as_slice() {
1394                 [] => {
1395                     stdx::never!("tuple type with 0 elements");
1396                     make::ty_unit()
1397                 }
1398                 [ty] => {
1399                     stdx::never!("tuple type with 1 element");
1400                     make_ty(ty, ctx, module)
1401                 }
1402                 types => {
1403                     let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1404                     make::ty_tuple(types)
1405                 }
1406             },
1407         }
1408     }
1409 }
1410
1411 fn make_body(
1412     ctx: &AssistContext,
1413     old_indent: IndentLevel,
1414     new_indent: IndentLevel,
1415     fun: &Function,
1416 ) -> ast::BlockExpr {
1417     let ret_ty = fun.return_type(ctx);
1418     let handler = if fun.mods.is_in_tail {
1419         FlowHandler::None
1420     } else {
1421         FlowHandler::from_ret_ty(fun, &ret_ty)
1422     };
1423     let block = match &fun.body {
1424         FunctionBody::Expr(expr) => {
1425             let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1426             let expr = ast::Expr::cast(expr).unwrap();
1427             match expr {
1428                 ast::Expr::BlockExpr(block) => {
1429                     // If the extracted expression is itself a block, there is no need to wrap it inside another block.
1430                     let block = block.dedent(old_indent);
1431                     // Recreate the block for formatting consistency with other extracted functions.
1432                     make::block_expr(block.statements(), block.tail_expr())
1433                 }
1434                 _ => {
1435                     let expr = expr.dedent(old_indent).indent(IndentLevel(1));
1436
1437                     make::block_expr(Vec::new(), Some(expr))
1438                 }
1439             }
1440         }
1441         FunctionBody::Span { parent, text_range } => {
1442             let mut elements: Vec<_> = parent
1443                 .syntax()
1444                 .children()
1445                 .filter(|it| text_range.contains_range(it.text_range()))
1446                 .map(|it| rewrite_body_segment(ctx, &fun.params, &handler, &it))
1447                 .collect();
1448
1449             let mut tail_expr = match elements.pop() {
1450                 Some(node) => ast::Expr::cast(node.clone()).or_else(|| {
1451                     elements.push(node);
1452                     None
1453                 }),
1454                 None => None,
1455             };
1456
1457             if tail_expr.is_none() {
1458                 match fun.outliving_locals.as_slice() {
1459                     [] => {}
1460                     [var] => {
1461                         tail_expr = Some(path_expr_from_local(ctx, var.local));
1462                     }
1463                     vars => {
1464                         let exprs = vars.iter().map(|var| path_expr_from_local(ctx, var.local));
1465                         let expr = make::expr_tuple(exprs);
1466                         tail_expr = Some(expr);
1467                     }
1468                 }
1469             }
1470
1471             let elements = elements.into_iter().filter_map(|node| match ast::Stmt::cast(node) {
1472                 Some(stmt) => Some(stmt),
1473                 None => {
1474                     stdx::never!("block contains non-statement");
1475                     None
1476                 }
1477             });
1478
1479             let body_indent = IndentLevel(1);
1480             let elements = elements.map(|stmt| stmt.dedent(old_indent).indent(body_indent));
1481             let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
1482
1483             make::block_expr(elements, tail_expr)
1484         }
1485     };
1486
1487     let block = match &handler {
1488         FlowHandler::None => block,
1489         FlowHandler::Try { kind } => {
1490             let block = with_default_tail_expr(block, make::expr_unit());
1491             map_tail_expr(block, |tail_expr| {
1492                 let constructor = match kind {
1493                     TryKind::Option => "Some",
1494                     TryKind::Result { .. } => "Ok",
1495                 };
1496                 let func = make::expr_path(make::ext::ident_path(constructor));
1497                 let args = make::arg_list(iter::once(tail_expr));
1498                 make::expr_call(func, args)
1499             })
1500         }
1501         FlowHandler::If { .. } => {
1502             let controlflow_continue = make::expr_call(
1503                 make::expr_path(make::path_from_text("ControlFlow::Continue")),
1504                 make::arg_list(iter::once(make::expr_unit())),
1505             );
1506             with_tail_expr(block, controlflow_continue.into())
1507         }
1508         FlowHandler::IfOption { .. } => {
1509             let none = make::expr_path(make::ext::ident_path("None"));
1510             with_tail_expr(block, none)
1511         }
1512         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1513             let some = make::expr_path(make::ext::ident_path("Some"));
1514             let args = make::arg_list(iter::once(tail_expr));
1515             make::expr_call(some, args)
1516         }),
1517         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1518             let ok = make::expr_path(make::ext::ident_path("Ok"));
1519             let args = make::arg_list(iter::once(tail_expr));
1520             make::expr_call(ok, args)
1521         }),
1522     };
1523
1524     block.indent(new_indent)
1525 }
1526
1527 fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1528     let tail_expr = match block.tail_expr() {
1529         Some(tail_expr) => tail_expr,
1530         None => return block,
1531     };
1532     make::block_expr(block.statements(), Some(f(tail_expr)))
1533 }
1534
1535 fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1536     match block.tail_expr() {
1537         Some(_) => block,
1538         None => make::block_expr(block.statements(), Some(tail_expr)),
1539     }
1540 }
1541
1542 fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1543     let stmt_tail = block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1544     let stmts = block.statements().chain(stmt_tail);
1545     make::block_expr(stmts, Some(tail_expr))
1546 }
1547
1548 fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String {
1549     ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string())
1550 }
1551
1552 fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1553     let ty_str = format_type(ty, ctx, module);
1554     make::ty(&ty_str)
1555 }
1556
1557 fn rewrite_body_segment(
1558     ctx: &AssistContext,
1559     params: &[Param],
1560     handler: &FlowHandler,
1561     syntax: &SyntaxNode,
1562 ) -> SyntaxNode {
1563     let syntax = fix_param_usages(ctx, params, syntax);
1564     update_external_control_flow(handler, &syntax);
1565     syntax
1566 }
1567
1568 /// change all usages to account for added `&`/`&mut` for some params
1569 fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode {
1570     let mut usages_for_param: Vec<(&Param, Vec<ast::Expr>)> = Vec::new();
1571
1572     let tm = TreeMutator::new(syntax);
1573
1574     for param in params {
1575         if !param.kind().is_ref() {
1576             continue;
1577         }
1578
1579         let usages = LocalUsages::find_local_usages(ctx, param.var);
1580         let usages = usages
1581             .iter()
1582             .filter(|reference| syntax.text_range().contains_range(reference.range))
1583             .filter_map(|reference| path_element_of_reference(syntax, reference))
1584             .map(|expr| tm.make_mut(&expr));
1585
1586         usages_for_param.push((param, usages.collect()));
1587     }
1588
1589     let res = tm.make_syntax_mut(syntax);
1590
1591     for (param, usages) in usages_for_param {
1592         for usage in usages {
1593             match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
1594                 Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
1595                     // do nothing
1596                 }
1597                 Some(ast::Expr::RefExpr(node))
1598                     if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
1599                 {
1600                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1601                 }
1602                 Some(ast::Expr::RefExpr(node))
1603                     if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
1604                 {
1605                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1606                 }
1607                 Some(_) | None => {
1608                     let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update();
1609                     ted::replace(usage.syntax(), p.syntax())
1610                 }
1611             }
1612         }
1613     }
1614
1615     res
1616 }
1617
1618 fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) {
1619     let mut nested_loop = None;
1620     let mut nested_scope = None;
1621     for event in syntax.preorder() {
1622         match event {
1623             WalkEvent::Enter(e) => match e.kind() {
1624                 SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
1625                     if nested_loop.is_none() {
1626                         nested_loop = Some(e.clone());
1627                     }
1628                 }
1629                 SyntaxKind::FN
1630                 | SyntaxKind::CONST
1631                 | SyntaxKind::STATIC
1632                 | SyntaxKind::IMPL
1633                 | SyntaxKind::MODULE => {
1634                     if nested_scope.is_none() {
1635                         nested_scope = Some(e.clone());
1636                     }
1637                 }
1638                 _ => {}
1639             },
1640             WalkEvent::Leave(e) => {
1641                 if nested_scope.is_none() {
1642                     if let Some(expr) = ast::Expr::cast(e.clone()) {
1643                         match expr {
1644                             ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => {
1645                                 let expr = return_expr.expr();
1646                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1647                                     ted::replace(return_expr.syntax(), replacement.syntax())
1648                                 }
1649                             }
1650                             ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
1651                                 let expr = break_expr.expr();
1652                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1653                                     ted::replace(break_expr.syntax(), replacement.syntax())
1654                                 }
1655                             }
1656                             ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
1657                                 if let Some(replacement) = make_rewritten_flow(handler, None) {
1658                                     ted::replace(continue_expr.syntax(), replacement.syntax())
1659                                 }
1660                             }
1661                             _ => {
1662                                 // do nothing
1663                             }
1664                         }
1665                     }
1666                 }
1667
1668                 if nested_loop.as_ref() == Some(&e) {
1669                     nested_loop = None;
1670                 }
1671                 if nested_scope.as_ref() == Some(&e) {
1672                     nested_scope = None;
1673                 }
1674             }
1675         };
1676     }
1677 }
1678
1679 fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1680     let value = match handler {
1681         FlowHandler::None | FlowHandler::Try { .. } => return None,
1682         FlowHandler::If { .. } => make::expr_call(
1683             make::expr_path(make::path_from_text("ControlFlow::Break")),
1684             make::arg_list(iter::once(make::expr_unit())),
1685         ),
1686         FlowHandler::IfOption { .. } => {
1687             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1688             let args = make::arg_list(iter::once(expr));
1689             make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
1690         }
1691         FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
1692         FlowHandler::MatchResult { .. } => {
1693             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1694             let args = make::arg_list(iter::once(expr));
1695             make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
1696         }
1697     };
1698     Some(make::expr_return(Some(value)).clone_for_update())
1699 }
1700
1701 #[cfg(test)]
1702 mod tests {
1703     use crate::tests::{check_assist, check_assist_not_applicable};
1704
1705     use super::*;
1706
1707     #[test]
1708     fn no_args_from_binary_expr() {
1709         check_assist(
1710             extract_function,
1711             r#"
1712 fn foo() {
1713     foo($01 + 1$0);
1714 }
1715 "#,
1716             r#"
1717 fn foo() {
1718     foo(fun_name());
1719 }
1720
1721 fn $0fun_name() -> i32 {
1722     1 + 1
1723 }
1724 "#,
1725         );
1726     }
1727
1728     #[test]
1729     fn no_args_from_binary_expr_in_module() {
1730         check_assist(
1731             extract_function,
1732             r#"
1733 mod bar {
1734     fn foo() {
1735         foo($01 + 1$0);
1736     }
1737 }
1738 "#,
1739             r#"
1740 mod bar {
1741     fn foo() {
1742         foo(fun_name());
1743     }
1744
1745     fn $0fun_name() -> i32 {
1746         1 + 1
1747     }
1748 }
1749 "#,
1750         );
1751     }
1752
1753     #[test]
1754     fn no_args_from_binary_expr_indented() {
1755         check_assist(
1756             extract_function,
1757             r#"
1758 fn foo() {
1759     $0{ 1 + 1 }$0;
1760 }
1761 "#,
1762             r#"
1763 fn foo() {
1764     fun_name();
1765 }
1766
1767 fn $0fun_name() -> i32 {
1768     1 + 1
1769 }
1770 "#,
1771         );
1772     }
1773
1774     #[test]
1775     fn no_args_from_stmt_with_last_expr() {
1776         check_assist(
1777             extract_function,
1778             r#"
1779 fn foo() -> i32 {
1780     let k = 1;
1781     $0let m = 1;
1782     m + 1$0
1783 }
1784 "#,
1785             r#"
1786 fn foo() -> i32 {
1787     let k = 1;
1788     fun_name()
1789 }
1790
1791 fn $0fun_name() -> i32 {
1792     let m = 1;
1793     m + 1
1794 }
1795 "#,
1796         );
1797     }
1798
1799     #[test]
1800     fn no_args_from_stmt_unit() {
1801         check_assist(
1802             extract_function,
1803             r#"
1804 fn foo() {
1805     let k = 3;
1806     $0let m = 1;
1807     let n = m + 1;$0
1808     let g = 5;
1809 }
1810 "#,
1811             r#"
1812 fn foo() {
1813     let k = 3;
1814     fun_name();
1815     let g = 5;
1816 }
1817
1818 fn $0fun_name() {
1819     let m = 1;
1820     let n = m + 1;
1821 }
1822 "#,
1823         );
1824     }
1825
1826     #[test]
1827     fn no_args_if() {
1828         check_assist(
1829             extract_function,
1830             r#"
1831 fn foo() {
1832     $0if true { }$0
1833 }
1834 "#,
1835             r#"
1836 fn foo() {
1837     fun_name();
1838 }
1839
1840 fn $0fun_name() {
1841     if true { }
1842 }
1843 "#,
1844         );
1845     }
1846
1847     #[test]
1848     fn no_args_if_else() {
1849         check_assist(
1850             extract_function,
1851             r#"
1852 fn foo() -> i32 {
1853     $0if true { 1 } else { 2 }$0
1854 }
1855 "#,
1856             r#"
1857 fn foo() -> i32 {
1858     fun_name()
1859 }
1860
1861 fn $0fun_name() -> i32 {
1862     if true { 1 } else { 2 }
1863 }
1864 "#,
1865         );
1866     }
1867
1868     #[test]
1869     fn no_args_if_let_else() {
1870         check_assist(
1871             extract_function,
1872             r#"
1873 fn foo() -> i32 {
1874     $0if let true = false { 1 } else { 2 }$0
1875 }
1876 "#,
1877             r#"
1878 fn foo() -> i32 {
1879     fun_name()
1880 }
1881
1882 fn $0fun_name() -> i32 {
1883     if let true = false { 1 } else { 2 }
1884 }
1885 "#,
1886         );
1887     }
1888
1889     #[test]
1890     fn no_args_match() {
1891         check_assist(
1892             extract_function,
1893             r#"
1894 fn foo() -> i32 {
1895     $0match true {
1896         true => 1,
1897         false => 2,
1898     }$0
1899 }
1900 "#,
1901             r#"
1902 fn foo() -> i32 {
1903     fun_name()
1904 }
1905
1906 fn $0fun_name() -> i32 {
1907     match true {
1908         true => 1,
1909         false => 2,
1910     }
1911 }
1912 "#,
1913         );
1914     }
1915
1916     #[test]
1917     fn no_args_while() {
1918         check_assist(
1919             extract_function,
1920             r#"
1921 fn foo() {
1922     $0while true { }$0
1923 }
1924 "#,
1925             r#"
1926 fn foo() {
1927     fun_name();
1928 }
1929
1930 fn $0fun_name() {
1931     while true { }
1932 }
1933 "#,
1934         );
1935     }
1936
1937     #[test]
1938     fn no_args_for() {
1939         check_assist(
1940             extract_function,
1941             r#"
1942 fn foo() {
1943     $0for v in &[0, 1] { }$0
1944 }
1945 "#,
1946             r#"
1947 fn foo() {
1948     fun_name();
1949 }
1950
1951 fn $0fun_name() {
1952     for v in &[0, 1] { }
1953 }
1954 "#,
1955         );
1956     }
1957
1958     #[test]
1959     fn no_args_from_loop_unit() {
1960         check_assist(
1961             extract_function,
1962             r#"
1963 fn foo() {
1964     $0loop {
1965         let m = 1;
1966     }$0
1967 }
1968 "#,
1969             r#"
1970 fn foo() {
1971     fun_name()
1972 }
1973
1974 fn $0fun_name() -> ! {
1975     loop {
1976         let m = 1;
1977     }
1978 }
1979 "#,
1980         );
1981     }
1982
1983     #[test]
1984     fn no_args_from_loop_with_return() {
1985         check_assist(
1986             extract_function,
1987             r#"
1988 fn foo() {
1989     let v = $0loop {
1990         let m = 1;
1991         break m;
1992     }$0;
1993 }
1994 "#,
1995             r#"
1996 fn foo() {
1997     let v = fun_name();
1998 }
1999
2000 fn $0fun_name() -> i32 {
2001     loop {
2002         let m = 1;
2003         break m;
2004     }
2005 }
2006 "#,
2007         );
2008     }
2009
2010     #[test]
2011     fn no_args_from_match() {
2012         check_assist(
2013             extract_function,
2014             r#"
2015 fn foo() {
2016     let v: i32 = $0match Some(1) {
2017         Some(x) => x,
2018         None => 0,
2019     }$0;
2020 }
2021 "#,
2022             r#"
2023 fn foo() {
2024     let v: i32 = fun_name();
2025 }
2026
2027 fn $0fun_name() -> i32 {
2028     match Some(1) {
2029         Some(x) => x,
2030         None => 0,
2031     }
2032 }
2033 "#,
2034         );
2035     }
2036
2037     #[test]
2038     fn extract_partial_block_single_line() {
2039         check_assist(
2040             extract_function,
2041             r#"
2042 fn foo() {
2043     let n = 1;
2044     let mut v = $0n * n;$0
2045     v += 1;
2046 }
2047 "#,
2048             r#"
2049 fn foo() {
2050     let n = 1;
2051     let mut v = fun_name(n);
2052     v += 1;
2053 }
2054
2055 fn $0fun_name(n: i32) -> i32 {
2056     let mut v = n * n;
2057     v
2058 }
2059 "#,
2060         );
2061     }
2062
2063     #[test]
2064     fn extract_partial_block() {
2065         check_assist(
2066             extract_function,
2067             r#"
2068 fn foo() {
2069     let m = 2;
2070     let n = 1;
2071     let mut v = m $0* n;
2072     let mut w = 3;$0
2073     v += 1;
2074     w += 1;
2075 }
2076 "#,
2077             r#"
2078 fn foo() {
2079     let m = 2;
2080     let n = 1;
2081     let (mut v, mut w) = fun_name(m, n);
2082     v += 1;
2083     w += 1;
2084 }
2085
2086 fn $0fun_name(m: i32, n: i32) -> (i32, i32) {
2087     let mut v = m * n;
2088     let mut w = 3;
2089     (v, w)
2090 }
2091 "#,
2092         );
2093     }
2094
2095     #[test]
2096     fn argument_form_expr() {
2097         check_assist(
2098             extract_function,
2099             r#"
2100 fn foo() -> u32 {
2101     let n = 2;
2102     $0n+2$0
2103 }
2104 "#,
2105             r#"
2106 fn foo() -> u32 {
2107     let n = 2;
2108     fun_name(n)
2109 }
2110
2111 fn $0fun_name(n: u32) -> u32 {
2112     n+2
2113 }
2114 "#,
2115         )
2116     }
2117
2118     #[test]
2119     fn argument_used_twice_form_expr() {
2120         check_assist(
2121             extract_function,
2122             r#"
2123 fn foo() -> u32 {
2124     let n = 2;
2125     $0n+n$0
2126 }
2127 "#,
2128             r#"
2129 fn foo() -> u32 {
2130     let n = 2;
2131     fun_name(n)
2132 }
2133
2134 fn $0fun_name(n: u32) -> u32 {
2135     n+n
2136 }
2137 "#,
2138         )
2139     }
2140
2141     #[test]
2142     fn two_arguments_form_expr() {
2143         check_assist(
2144             extract_function,
2145             r#"
2146 fn foo() -> u32 {
2147     let n = 2;
2148     let m = 3;
2149     $0n+n*m$0
2150 }
2151 "#,
2152             r#"
2153 fn foo() -> u32 {
2154     let n = 2;
2155     let m = 3;
2156     fun_name(n, m)
2157 }
2158
2159 fn $0fun_name(n: u32, m: u32) -> u32 {
2160     n+n*m
2161 }
2162 "#,
2163         )
2164     }
2165
2166     #[test]
2167     fn argument_and_locals() {
2168         check_assist(
2169             extract_function,
2170             r#"
2171 fn foo() -> u32 {
2172     let n = 2;
2173     $0let m = 1;
2174     n + m$0
2175 }
2176 "#,
2177             r#"
2178 fn foo() -> u32 {
2179     let n = 2;
2180     fun_name(n)
2181 }
2182
2183 fn $0fun_name(n: u32) -> u32 {
2184     let m = 1;
2185     n + m
2186 }
2187 "#,
2188         )
2189     }
2190
2191     #[test]
2192     fn in_comment_is_not_applicable() {
2193         cov_mark::check!(extract_function_in_comment_is_not_applicable);
2194         check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
2195     }
2196
2197     #[test]
2198     fn part_of_expr_stmt() {
2199         check_assist(
2200             extract_function,
2201             r#"
2202 fn foo() {
2203     $01$0 + 1;
2204 }
2205 "#,
2206             r#"
2207 fn foo() {
2208     fun_name() + 1;
2209 }
2210
2211 fn $0fun_name() -> i32 {
2212     1
2213 }
2214 "#,
2215         );
2216     }
2217
2218     #[test]
2219     fn function_expr() {
2220         check_assist(
2221             extract_function,
2222             r#"
2223 fn foo() {
2224     $0bar(1 + 1)$0
2225 }
2226 "#,
2227             r#"
2228 fn foo() {
2229     fun_name();
2230 }
2231
2232 fn $0fun_name() {
2233     bar(1 + 1)
2234 }
2235 "#,
2236         )
2237     }
2238
2239     #[test]
2240     fn extract_from_nested() {
2241         check_assist(
2242             extract_function,
2243             r#"
2244 fn main() {
2245     let x = true;
2246     let tuple = match x {
2247         true => ($02 + 2$0, true)
2248         _ => (0, false)
2249     };
2250 }
2251 "#,
2252             r#"
2253 fn main() {
2254     let x = true;
2255     let tuple = match x {
2256         true => (fun_name(), true)
2257         _ => (0, false)
2258     };
2259 }
2260
2261 fn $0fun_name() -> i32 {
2262     2 + 2
2263 }
2264 "#,
2265         );
2266     }
2267
2268     #[test]
2269     fn param_from_closure() {
2270         check_assist(
2271             extract_function,
2272             r#"
2273 fn main() {
2274     let lambda = |x: u32| $0x * 2$0;
2275 }
2276 "#,
2277             r#"
2278 fn main() {
2279     let lambda = |x: u32| fun_name(x);
2280 }
2281
2282 fn $0fun_name(x: u32) -> u32 {
2283     x * 2
2284 }
2285 "#,
2286         );
2287     }
2288
2289     #[test]
2290     fn extract_return_stmt() {
2291         check_assist(
2292             extract_function,
2293             r#"
2294 fn foo() -> u32 {
2295     $0return 2 + 2$0;
2296 }
2297 "#,
2298             r#"
2299 fn foo() -> u32 {
2300     return fun_name();
2301 }
2302
2303 fn $0fun_name() -> u32 {
2304     2 + 2
2305 }
2306 "#,
2307         );
2308     }
2309
2310     #[test]
2311     fn does_not_add_extra_whitespace() {
2312         check_assist(
2313             extract_function,
2314             r#"
2315 fn foo() -> u32 {
2316
2317
2318     $0return 2 + 2$0;
2319 }
2320 "#,
2321             r#"
2322 fn foo() -> u32 {
2323
2324
2325     return fun_name();
2326 }
2327
2328 fn $0fun_name() -> u32 {
2329     2 + 2
2330 }
2331 "#,
2332         );
2333     }
2334
2335     #[test]
2336     fn break_stmt() {
2337         check_assist(
2338             extract_function,
2339             r#"
2340 fn main() {
2341     let result = loop {
2342         $0break 2 + 2$0;
2343     };
2344 }
2345 "#,
2346             r#"
2347 fn main() {
2348     let result = loop {
2349         break fun_name();
2350     };
2351 }
2352
2353 fn $0fun_name() -> i32 {
2354     2 + 2
2355 }
2356 "#,
2357         );
2358     }
2359
2360     #[test]
2361     fn extract_cast() {
2362         check_assist(
2363             extract_function,
2364             r#"
2365 fn main() {
2366     let v = $00f32 as u32$0;
2367 }
2368 "#,
2369             r#"
2370 fn main() {
2371     let v = fun_name();
2372 }
2373
2374 fn $0fun_name() -> u32 {
2375     0f32 as u32
2376 }
2377 "#,
2378         );
2379     }
2380
2381     #[test]
2382     fn return_not_applicable() {
2383         check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2384     }
2385
2386     #[test]
2387     fn method_to_freestanding() {
2388         check_assist(
2389             extract_function,
2390             r#"
2391 struct S;
2392
2393 impl S {
2394     fn foo(&self) -> i32 {
2395         $01+1$0
2396     }
2397 }
2398 "#,
2399             r#"
2400 struct S;
2401
2402 impl S {
2403     fn foo(&self) -> i32 {
2404         fun_name()
2405     }
2406 }
2407
2408 fn $0fun_name() -> i32 {
2409     1+1
2410 }
2411 "#,
2412         );
2413     }
2414
2415     #[test]
2416     fn method_with_reference() {
2417         check_assist(
2418             extract_function,
2419             r#"
2420 struct S { f: i32 };
2421
2422 impl S {
2423     fn foo(&self) -> i32 {
2424         $0self.f+self.f$0
2425     }
2426 }
2427 "#,
2428             r#"
2429 struct S { f: i32 };
2430
2431 impl S {
2432     fn foo(&self) -> i32 {
2433         self.fun_name()
2434     }
2435
2436     fn $0fun_name(&self) -> i32 {
2437         self.f+self.f
2438     }
2439 }
2440 "#,
2441         );
2442     }
2443
2444     #[test]
2445     fn method_with_mut() {
2446         check_assist(
2447             extract_function,
2448             r#"
2449 struct S { f: i32 };
2450
2451 impl S {
2452     fn foo(&mut self) {
2453         $0self.f += 1;$0
2454     }
2455 }
2456 "#,
2457             r#"
2458 struct S { f: i32 };
2459
2460 impl S {
2461     fn foo(&mut self) {
2462         self.fun_name();
2463     }
2464
2465     fn $0fun_name(&mut self) {
2466         self.f += 1;
2467     }
2468 }
2469 "#,
2470         );
2471     }
2472
2473     #[test]
2474     fn variable_defined_inside_and_used_after_no_ret() {
2475         check_assist(
2476             extract_function,
2477             r#"
2478 fn foo() {
2479     let n = 1;
2480     $0let k = n * n;$0
2481     let m = k + 1;
2482 }
2483 "#,
2484             r#"
2485 fn foo() {
2486     let n = 1;
2487     let k = fun_name(n);
2488     let m = k + 1;
2489 }
2490
2491 fn $0fun_name(n: i32) -> i32 {
2492     let k = n * n;
2493     k
2494 }
2495 "#,
2496         );
2497     }
2498
2499     #[test]
2500     fn variable_defined_inside_and_used_after_mutably_no_ret() {
2501         check_assist(
2502             extract_function,
2503             r#"
2504 fn foo() {
2505     let n = 1;
2506     $0let mut k = n * n;$0
2507     k += 1;
2508 }
2509 "#,
2510             r#"
2511 fn foo() {
2512     let n = 1;
2513     let mut k = fun_name(n);
2514     k += 1;
2515 }
2516
2517 fn $0fun_name(n: i32) -> i32 {
2518     let mut k = n * n;
2519     k
2520 }
2521 "#,
2522         );
2523     }
2524
2525     #[test]
2526     fn two_variables_defined_inside_and_used_after_no_ret() {
2527         check_assist(
2528             extract_function,
2529             r#"
2530 fn foo() {
2531     let n = 1;
2532     $0let k = n * n;
2533     let m = k + 2;$0
2534     let h = k + m;
2535 }
2536 "#,
2537             r#"
2538 fn foo() {
2539     let n = 1;
2540     let (k, m) = fun_name(n);
2541     let h = k + m;
2542 }
2543
2544 fn $0fun_name(n: i32) -> (i32, i32) {
2545     let k = n * n;
2546     let m = k + 2;
2547     (k, m)
2548 }
2549 "#,
2550         );
2551     }
2552
2553     #[test]
2554     fn multi_variables_defined_inside_and_used_after_mutably_no_ret() {
2555         check_assist(
2556             extract_function,
2557             r#"
2558 fn foo() {
2559     let n = 1;
2560     $0let mut k = n * n;
2561     let mut m = k + 2;
2562     let mut o = m + 3;
2563     o += 1;$0
2564     k += o;
2565     m = 1;
2566 }
2567 "#,
2568             r#"
2569 fn foo() {
2570     let n = 1;
2571     let (mut k, mut m, o) = fun_name(n);
2572     k += o;
2573     m = 1;
2574 }
2575
2576 fn $0fun_name(n: i32) -> (i32, i32, i32) {
2577     let mut k = n * n;
2578     let mut m = k + 2;
2579     let mut o = m + 3;
2580     o += 1;
2581     (k, m, o)
2582 }
2583 "#,
2584         );
2585     }
2586
2587     #[test]
2588     fn nontrivial_patterns_define_variables() {
2589         check_assist(
2590             extract_function,
2591             r#"
2592 struct Counter(i32);
2593 fn foo() {
2594     $0let Counter(n) = Counter(0);$0
2595     let m = n;
2596 }
2597 "#,
2598             r#"
2599 struct Counter(i32);
2600 fn foo() {
2601     let n = fun_name();
2602     let m = n;
2603 }
2604
2605 fn $0fun_name() -> i32 {
2606     let Counter(n) = Counter(0);
2607     n
2608 }
2609 "#,
2610         );
2611     }
2612
2613     #[test]
2614     fn struct_with_two_fields_pattern_define_variables() {
2615         check_assist(
2616             extract_function,
2617             r#"
2618 struct Counter { n: i32, m: i32 };
2619 fn foo() {
2620     $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
2621     let h = n + k;
2622 }
2623 "#,
2624             r#"
2625 struct Counter { n: i32, m: i32 };
2626 fn foo() {
2627     let (n, k) = fun_name();
2628     let h = n + k;
2629 }
2630
2631 fn $0fun_name() -> (i32, i32) {
2632     let Counter { n, m: k } = Counter { n: 1, m: 2 };
2633     (n, k)
2634 }
2635 "#,
2636         );
2637     }
2638
2639     #[test]
2640     fn mut_var_from_outer_scope() {
2641         check_assist(
2642             extract_function,
2643             r#"
2644 fn foo() {
2645     let mut n = 1;
2646     $0n += 1;$0
2647     let m = n + 1;
2648 }
2649 "#,
2650             r#"
2651 fn foo() {
2652     let mut n = 1;
2653     fun_name(&mut n);
2654     let m = n + 1;
2655 }
2656
2657 fn $0fun_name(n: &mut i32) {
2658     *n += 1;
2659 }
2660 "#,
2661         );
2662     }
2663
2664     #[test]
2665     fn mut_field_from_outer_scope() {
2666         check_assist(
2667             extract_function,
2668             r#"
2669 struct C { n: i32 }
2670 fn foo() {
2671     let mut c = C { n: 0 };
2672     $0c.n += 1;$0
2673     let m = c.n + 1;
2674 }
2675 "#,
2676             r#"
2677 struct C { n: i32 }
2678 fn foo() {
2679     let mut c = C { n: 0 };
2680     fun_name(&mut c);
2681     let m = c.n + 1;
2682 }
2683
2684 fn $0fun_name(c: &mut C) {
2685     c.n += 1;
2686 }
2687 "#,
2688         );
2689     }
2690
2691     #[test]
2692     fn mut_nested_field_from_outer_scope() {
2693         check_assist(
2694             extract_function,
2695             r#"
2696 struct P { n: i32}
2697 struct C { p: P }
2698 fn foo() {
2699     let mut c = C { p: P { n: 0 } };
2700     let mut v = C { p: P { n: 0 } };
2701     let u = C { p: P { n: 0 } };
2702     $0c.p.n += u.p.n;
2703     let r = &mut v.p.n;$0
2704     let m = c.p.n + v.p.n + u.p.n;
2705 }
2706 "#,
2707             r#"
2708 struct P { n: i32}
2709 struct C { p: P }
2710 fn foo() {
2711     let mut c = C { p: P { n: 0 } };
2712     let mut v = C { p: P { n: 0 } };
2713     let u = C { p: P { n: 0 } };
2714     fun_name(&mut c, &u, &mut v);
2715     let m = c.p.n + v.p.n + u.p.n;
2716 }
2717
2718 fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
2719     c.p.n += u.p.n;
2720     let r = &mut v.p.n;
2721 }
2722 "#,
2723         );
2724     }
2725
2726     #[test]
2727     fn mut_param_many_usages_stmt() {
2728         check_assist(
2729             extract_function,
2730             r#"
2731 fn bar(k: i32) {}
2732 trait I: Copy {
2733     fn succ(&self) -> Self;
2734     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2735 }
2736 impl I for i32 {
2737     fn succ(&self) -> Self { *self + 1 }
2738 }
2739 fn foo() {
2740     let mut n = 1;
2741     $0n += n;
2742     bar(n);
2743     bar(n+1);
2744     bar(n*n);
2745     bar(&n);
2746     n.inc();
2747     let v = &mut n;
2748     *v = v.succ();
2749     n.succ();$0
2750     let m = n + 1;
2751 }
2752 "#,
2753             r#"
2754 fn bar(k: i32) {}
2755 trait I: Copy {
2756     fn succ(&self) -> Self;
2757     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2758 }
2759 impl I for i32 {
2760     fn succ(&self) -> Self { *self + 1 }
2761 }
2762 fn foo() {
2763     let mut n = 1;
2764     fun_name(&mut n);
2765     let m = n + 1;
2766 }
2767
2768 fn $0fun_name(n: &mut i32) {
2769     *n += *n;
2770     bar(*n);
2771     bar(*n+1);
2772     bar(*n**n);
2773     bar(&*n);
2774     n.inc();
2775     let v = n;
2776     *v = v.succ();
2777     n.succ();
2778 }
2779 "#,
2780         );
2781     }
2782
2783     #[test]
2784     fn mut_param_many_usages_expr() {
2785         check_assist(
2786             extract_function,
2787             r#"
2788 fn bar(k: i32) {}
2789 trait I: Copy {
2790     fn succ(&self) -> Self;
2791     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2792 }
2793 impl I for i32 {
2794     fn succ(&self) -> Self { *self + 1 }
2795 }
2796 fn foo() {
2797     let mut n = 1;
2798     $0{
2799         n += n;
2800         bar(n);
2801         bar(n+1);
2802         bar(n*n);
2803         bar(&n);
2804         n.inc();
2805         let v = &mut n;
2806         *v = v.succ();
2807         n.succ();
2808     }$0
2809     let m = n + 1;
2810 }
2811 "#,
2812             r#"
2813 fn bar(k: i32) {}
2814 trait I: Copy {
2815     fn succ(&self) -> Self;
2816     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2817 }
2818 impl I for i32 {
2819     fn succ(&self) -> Self { *self + 1 }
2820 }
2821 fn foo() {
2822     let mut n = 1;
2823     fun_name(&mut n);
2824     let m = n + 1;
2825 }
2826
2827 fn $0fun_name(n: &mut i32) {
2828     *n += *n;
2829     bar(*n);
2830     bar(*n+1);
2831     bar(*n**n);
2832     bar(&*n);
2833     n.inc();
2834     let v = n;
2835     *v = v.succ();
2836     n.succ();
2837 }
2838 "#,
2839         );
2840     }
2841
2842     #[test]
2843     fn mut_param_by_value() {
2844         check_assist(
2845             extract_function,
2846             r#"
2847 fn foo() {
2848     let mut n = 1;
2849     $0n += 1;$0
2850 }
2851 "#,
2852             r"
2853 fn foo() {
2854     let mut n = 1;
2855     fun_name(n);
2856 }
2857
2858 fn $0fun_name(mut n: i32) {
2859     n += 1;
2860 }
2861 ",
2862         );
2863     }
2864
2865     #[test]
2866     fn mut_param_because_of_mut_ref() {
2867         check_assist(
2868             extract_function,
2869             r#"
2870 fn foo() {
2871     let mut n = 1;
2872     $0let v = &mut n;
2873     *v += 1;$0
2874     let k = n;
2875 }
2876 "#,
2877             r#"
2878 fn foo() {
2879     let mut n = 1;
2880     fun_name(&mut n);
2881     let k = n;
2882 }
2883
2884 fn $0fun_name(n: &mut i32) {
2885     let v = n;
2886     *v += 1;
2887 }
2888 "#,
2889         );
2890     }
2891
2892     #[test]
2893     fn mut_param_by_value_because_of_mut_ref() {
2894         check_assist(
2895             extract_function,
2896             r"
2897 fn foo() {
2898     let mut n = 1;
2899     $0let v = &mut n;
2900     *v += 1;$0
2901 }
2902 ",
2903             r#"
2904 fn foo() {
2905     let mut n = 1;
2906     fun_name(n);
2907 }
2908
2909 fn $0fun_name(mut n: i32) {
2910     let v = &mut n;
2911     *v += 1;
2912 }
2913 "#,
2914         );
2915     }
2916
2917     #[test]
2918     fn mut_method_call() {
2919         check_assist(
2920             extract_function,
2921             r#"
2922 trait I {
2923     fn inc(&mut self);
2924 }
2925 impl I for i32 {
2926     fn inc(&mut self) { *self += 1 }
2927 }
2928 fn foo() {
2929     let mut n = 1;
2930     $0n.inc();$0
2931 }
2932 "#,
2933             r#"
2934 trait I {
2935     fn inc(&mut self);
2936 }
2937 impl I for i32 {
2938     fn inc(&mut self) { *self += 1 }
2939 }
2940 fn foo() {
2941     let mut n = 1;
2942     fun_name(n);
2943 }
2944
2945 fn $0fun_name(mut n: i32) {
2946     n.inc();
2947 }
2948 "#,
2949         );
2950     }
2951
2952     #[test]
2953     fn shared_method_call() {
2954         check_assist(
2955             extract_function,
2956             r#"
2957 trait I {
2958     fn succ(&self);
2959 }
2960 impl I for i32 {
2961     fn succ(&self) { *self + 1 }
2962 }
2963 fn foo() {
2964     let mut n = 1;
2965     $0n.succ();$0
2966 }
2967 "#,
2968             r"
2969 trait I {
2970     fn succ(&self);
2971 }
2972 impl I for i32 {
2973     fn succ(&self) { *self + 1 }
2974 }
2975 fn foo() {
2976     let mut n = 1;
2977     fun_name(n);
2978 }
2979
2980 fn $0fun_name(n: i32) {
2981     n.succ();
2982 }
2983 ",
2984         );
2985     }
2986
2987     #[test]
2988     fn mut_method_call_with_other_receiver() {
2989         check_assist(
2990             extract_function,
2991             r#"
2992 trait I {
2993     fn inc(&mut self, n: i32);
2994 }
2995 impl I for i32 {
2996     fn inc(&mut self, n: i32) { *self += n }
2997 }
2998 fn foo() {
2999     let mut n = 1;
3000     $0let mut m = 2;
3001     m.inc(n);$0
3002 }
3003 "#,
3004             r"
3005 trait I {
3006     fn inc(&mut self, n: i32);
3007 }
3008 impl I for i32 {
3009     fn inc(&mut self, n: i32) { *self += n }
3010 }
3011 fn foo() {
3012     let mut n = 1;
3013     fun_name(n);
3014 }
3015
3016 fn $0fun_name(n: i32) {
3017     let mut m = 2;
3018     m.inc(n);
3019 }
3020 ",
3021         );
3022     }
3023
3024     #[test]
3025     fn non_copy_without_usages_after() {
3026         check_assist(
3027             extract_function,
3028             r#"
3029 struct Counter(i32);
3030 fn foo() {
3031     let c = Counter(0);
3032     $0let n = c.0;$0
3033 }
3034 "#,
3035             r"
3036 struct Counter(i32);
3037 fn foo() {
3038     let c = Counter(0);
3039     fun_name(c);
3040 }
3041
3042 fn $0fun_name(c: Counter) {
3043     let n = c.0;
3044 }
3045 ",
3046         );
3047     }
3048
3049     #[test]
3050     fn non_copy_used_after() {
3051         check_assist(
3052             extract_function,
3053             r"
3054 struct Counter(i32);
3055 fn foo() {
3056     let c = Counter(0);
3057     $0let n = c.0;$0
3058     let m = c.0;
3059 }
3060 ",
3061             r#"
3062 struct Counter(i32);
3063 fn foo() {
3064     let c = Counter(0);
3065     fun_name(&c);
3066     let m = c.0;
3067 }
3068
3069 fn $0fun_name(c: &Counter) {
3070     let n = c.0;
3071 }
3072 "#,
3073         );
3074     }
3075
3076     #[test]
3077     fn copy_used_after() {
3078         check_assist(
3079             extract_function,
3080             r#"
3081 //- minicore: copy
3082 fn foo() {
3083     let n = 0;
3084     $0let m = n;$0
3085     let k = n;
3086 }
3087 "#,
3088             r#"
3089 fn foo() {
3090     let n = 0;
3091     fun_name(n);
3092     let k = n;
3093 }
3094
3095 fn $0fun_name(n: i32) {
3096     let m = n;
3097 }
3098 "#,
3099         )
3100     }
3101
3102     #[test]
3103     fn copy_custom_used_after() {
3104         check_assist(
3105             extract_function,
3106             r#"
3107 //- minicore: copy, derive
3108 #[derive(Clone, Copy)]
3109 struct Counter(i32);
3110 fn foo() {
3111     let c = Counter(0);
3112     $0let n = c.0;$0
3113     let m = c.0;
3114 }
3115 "#,
3116             r#"
3117 #[derive(Clone, Copy)]
3118 struct Counter(i32);
3119 fn foo() {
3120     let c = Counter(0);
3121     fun_name(c);
3122     let m = c.0;
3123 }
3124
3125 fn $0fun_name(c: Counter) {
3126     let n = c.0;
3127 }
3128 "#,
3129         );
3130     }
3131
3132     #[test]
3133     fn indented_stmts() {
3134         check_assist(
3135             extract_function,
3136             r#"
3137 fn foo() {
3138     if true {
3139         loop {
3140             $0let n = 1;
3141             let m = 2;$0
3142         }
3143     }
3144 }
3145 "#,
3146             r#"
3147 fn foo() {
3148     if true {
3149         loop {
3150             fun_name();
3151         }
3152     }
3153 }
3154
3155 fn $0fun_name() {
3156     let n = 1;
3157     let m = 2;
3158 }
3159 "#,
3160         );
3161     }
3162
3163     #[test]
3164     fn indented_stmts_inside_mod() {
3165         check_assist(
3166             extract_function,
3167             r#"
3168 mod bar {
3169     fn foo() {
3170         if true {
3171             loop {
3172                 $0let n = 1;
3173                 let m = 2;$0
3174             }
3175         }
3176     }
3177 }
3178 "#,
3179             r#"
3180 mod bar {
3181     fn foo() {
3182         if true {
3183             loop {
3184                 fun_name();
3185             }
3186         }
3187     }
3188
3189     fn $0fun_name() {
3190         let n = 1;
3191         let m = 2;
3192     }
3193 }
3194 "#,
3195         );
3196     }
3197
3198     #[test]
3199     fn break_loop() {
3200         check_assist(
3201             extract_function,
3202             r#"
3203 //- minicore: option
3204 fn foo() {
3205     loop {
3206         let n = 1;
3207         $0let m = n + 1;
3208         break;
3209         let k = 2;$0
3210         let h = 1 + k;
3211     }
3212 }
3213 "#,
3214             r#"
3215 fn foo() {
3216     loop {
3217         let n = 1;
3218         let k = match fun_name(n) {
3219             Some(value) => value,
3220             None => break,
3221         };
3222         let h = 1 + k;
3223     }
3224 }
3225
3226 fn $0fun_name(n: i32) -> Option<i32> {
3227     let m = n + 1;
3228     return None;
3229     let k = 2;
3230     Some(k)
3231 }
3232 "#,
3233         );
3234     }
3235
3236     #[test]
3237     fn return_to_parent() {
3238         check_assist(
3239             extract_function,
3240             r#"
3241 //- minicore: copy, result
3242 fn foo() -> i64 {
3243     let n = 1;
3244     $0let m = n + 1;
3245     return 1;
3246     let k = 2;$0
3247     (n + k) as i64
3248 }
3249 "#,
3250             r#"
3251 fn foo() -> i64 {
3252     let n = 1;
3253     let k = match fun_name(n) {
3254         Ok(value) => value,
3255         Err(value) => return value,
3256     };
3257     (n + k) as i64
3258 }
3259
3260 fn $0fun_name(n: i32) -> Result<i32, i64> {
3261     let m = n + 1;
3262     return Err(1);
3263     let k = 2;
3264     Ok(k)
3265 }
3266 "#,
3267         );
3268     }
3269
3270     #[test]
3271     fn break_and_continue() {
3272         cov_mark::check!(external_control_flow_break_and_continue);
3273         check_assist_not_applicable(
3274             extract_function,
3275             r#"
3276 fn foo() {
3277     loop {
3278         let n = 1;
3279         $0let m = n + 1;
3280         break;
3281         let k = 2;
3282         continue;
3283         let k = k + 1;$0
3284         let r = n + k;
3285     }
3286 }
3287 "#,
3288         );
3289     }
3290
3291     #[test]
3292     fn return_and_break() {
3293         cov_mark::check!(external_control_flow_return_and_bc);
3294         check_assist_not_applicable(
3295             extract_function,
3296             r#"
3297 fn foo() {
3298     loop {
3299         let n = 1;
3300         $0let m = n + 1;
3301         break;
3302         let k = 2;
3303         return;
3304         let k = k + 1;$0
3305         let r = n + k;
3306     }
3307 }
3308 "#,
3309         );
3310     }
3311
3312     #[test]
3313     fn break_loop_with_if() {
3314         check_assist(
3315             extract_function,
3316             r#"
3317 //- minicore: try
3318 fn foo() {
3319     loop {
3320         let mut n = 1;
3321         $0let m = n + 1;
3322         break;
3323         n += m;$0
3324         let h = 1 + n;
3325     }
3326 }
3327 "#,
3328             r#"
3329 use core::ops::ControlFlow;
3330
3331 fn foo() {
3332     loop {
3333         let mut n = 1;
3334         if let ControlFlow::Break(_) = fun_name(&mut n) {
3335             break;
3336         }
3337         let h = 1 + n;
3338     }
3339 }
3340
3341 fn $0fun_name(n: &mut i32) -> ControlFlow<()> {
3342     let m = *n + 1;
3343     return ControlFlow::Break(());
3344     *n += m;
3345     ControlFlow::Continue(())
3346 }
3347 "#,
3348         );
3349     }
3350
3351     #[test]
3352     fn break_loop_nested() {
3353         check_assist(
3354             extract_function,
3355             r#"
3356 //- minicore: try
3357 fn foo() {
3358     loop {
3359         let mut n = 1;
3360         $0let m = n + 1;
3361         if m == 42 {
3362             break;
3363         }$0
3364         let h = 1;
3365     }
3366 }
3367 "#,
3368             r#"
3369 use core::ops::ControlFlow;
3370
3371 fn foo() {
3372     loop {
3373         let mut n = 1;
3374         if let ControlFlow::Break(_) = fun_name(n) {
3375             break;
3376         }
3377         let h = 1;
3378     }
3379 }
3380
3381 fn $0fun_name(n: i32) -> ControlFlow<()> {
3382     let m = n + 1;
3383     if m == 42 {
3384         return ControlFlow::Break(());
3385     }
3386     ControlFlow::Continue(())
3387 }
3388 "#,
3389         );
3390     }
3391
3392     #[test]
3393     fn return_from_nested_loop() {
3394         check_assist(
3395             extract_function,
3396             r#"
3397 fn foo() {
3398     loop {
3399         let n = 1;$0
3400         let k = 1;
3401         loop {
3402             return;
3403         }
3404         let m = k + 1;$0
3405         let h = 1 + m;
3406     }
3407 }
3408 "#,
3409             r#"
3410 fn foo() {
3411     loop {
3412         let n = 1;
3413         let m = match fun_name() {
3414             Some(value) => value,
3415             None => return,
3416         };
3417         let h = 1 + m;
3418     }
3419 }
3420
3421 fn $0fun_name() -> Option<i32> {
3422     let k = 1;
3423     loop {
3424         return None;
3425     }
3426     let m = k + 1;
3427     Some(m)
3428 }
3429 "#,
3430         );
3431     }
3432
3433     #[test]
3434     fn break_from_nested_loop() {
3435         check_assist(
3436             extract_function,
3437             r#"
3438 fn foo() {
3439     loop {
3440         let n = 1;
3441         $0let k = 1;
3442         loop {
3443             break;
3444         }
3445         let m = k + 1;$0
3446         let h = 1 + m;
3447     }
3448 }
3449 "#,
3450             r#"
3451 fn foo() {
3452     loop {
3453         let n = 1;
3454         let m = fun_name();
3455         let h = 1 + m;
3456     }
3457 }
3458
3459 fn $0fun_name() -> i32 {
3460     let k = 1;
3461     loop {
3462         break;
3463     }
3464     let m = k + 1;
3465     m
3466 }
3467 "#,
3468         );
3469     }
3470
3471     #[test]
3472     fn break_from_nested_and_outer_loops() {
3473         check_assist(
3474             extract_function,
3475             r#"
3476 fn foo() {
3477     loop {
3478         let n = 1;
3479         $0let k = 1;
3480         loop {
3481             break;
3482         }
3483         if k == 42 {
3484             break;
3485         }
3486         let m = k + 1;$0
3487         let h = 1 + m;
3488     }
3489 }
3490 "#,
3491             r#"
3492 fn foo() {
3493     loop {
3494         let n = 1;
3495         let m = match fun_name() {
3496             Some(value) => value,
3497             None => break,
3498         };
3499         let h = 1 + m;
3500     }
3501 }
3502
3503 fn $0fun_name() -> Option<i32> {
3504     let k = 1;
3505     loop {
3506         break;
3507     }
3508     if k == 42 {
3509         return None;
3510     }
3511     let m = k + 1;
3512     Some(m)
3513 }
3514 "#,
3515         );
3516     }
3517
3518     #[test]
3519     fn return_from_nested_fn() {
3520         check_assist(
3521             extract_function,
3522             r#"
3523 fn foo() {
3524     loop {
3525         let n = 1;
3526         $0let k = 1;
3527         fn test() {
3528             return;
3529         }
3530         let m = k + 1;$0
3531         let h = 1 + m;
3532     }
3533 }
3534 "#,
3535             r#"
3536 fn foo() {
3537     loop {
3538         let n = 1;
3539         let m = fun_name();
3540         let h = 1 + m;
3541     }
3542 }
3543
3544 fn $0fun_name() -> i32 {
3545     let k = 1;
3546     fn test() {
3547         return;
3548     }
3549     let m = k + 1;
3550     m
3551 }
3552 "#,
3553         );
3554     }
3555
3556     #[test]
3557     fn break_with_value() {
3558         check_assist(
3559             extract_function,
3560             r#"
3561 fn foo() -> i32 {
3562     loop {
3563         let n = 1;
3564         $0let k = 1;
3565         if k == 42 {
3566             break 3;
3567         }
3568         let m = k + 1;$0
3569         let h = 1;
3570     }
3571 }
3572 "#,
3573             r#"
3574 fn foo() -> i32 {
3575     loop {
3576         let n = 1;
3577         if let Some(value) = fun_name() {
3578             break value;
3579         }
3580         let h = 1;
3581     }
3582 }
3583
3584 fn $0fun_name() -> Option<i32> {
3585     let k = 1;
3586     if k == 42 {
3587         return Some(3);
3588     }
3589     let m = k + 1;
3590     None
3591 }
3592 "#,
3593         );
3594     }
3595
3596     #[test]
3597     fn break_with_value_and_return() {
3598         check_assist(
3599             extract_function,
3600             r#"
3601 fn foo() -> i64 {
3602     loop {
3603         let n = 1;$0
3604         let k = 1;
3605         if k == 42 {
3606             break 3;
3607         }
3608         let m = k + 1;$0
3609         let h = 1 + m;
3610     }
3611 }
3612 "#,
3613             r#"
3614 fn foo() -> i64 {
3615     loop {
3616         let n = 1;
3617         let m = match fun_name() {
3618             Ok(value) => value,
3619             Err(value) => break value,
3620         };
3621         let h = 1 + m;
3622     }
3623 }
3624
3625 fn $0fun_name() -> Result<i32, i64> {
3626     let k = 1;
3627     if k == 42 {
3628         return Err(3);
3629     }
3630     let m = k + 1;
3631     Ok(m)
3632 }
3633 "#,
3634         );
3635     }
3636
3637     #[test]
3638     fn try_option() {
3639         check_assist(
3640             extract_function,
3641             r#"
3642 //- minicore: option
3643 fn bar() -> Option<i32> { None }
3644 fn foo() -> Option<()> {
3645     let n = bar()?;
3646     $0let k = foo()?;
3647     let m = k + 1;$0
3648     let h = 1 + m;
3649     Some(())
3650 }
3651 "#,
3652             r#"
3653 fn bar() -> Option<i32> { None }
3654 fn foo() -> Option<()> {
3655     let n = bar()?;
3656     let m = fun_name()?;
3657     let h = 1 + m;
3658     Some(())
3659 }
3660
3661 fn $0fun_name() -> Option<i32> {
3662     let k = foo()?;
3663     let m = k + 1;
3664     Some(m)
3665 }
3666 "#,
3667         );
3668     }
3669
3670     #[test]
3671     fn try_option_unit() {
3672         check_assist(
3673             extract_function,
3674             r#"
3675 //- minicore: option
3676 fn foo() -> Option<()> {
3677     let n = 1;
3678     $0let k = foo()?;
3679     let m = k + 1;$0
3680     let h = 1 + n;
3681     Some(())
3682 }
3683 "#,
3684             r#"
3685 fn foo() -> Option<()> {
3686     let n = 1;
3687     fun_name()?;
3688     let h = 1 + n;
3689     Some(())
3690 }
3691
3692 fn $0fun_name() -> Option<()> {
3693     let k = foo()?;
3694     let m = k + 1;
3695     Some(())
3696 }
3697 "#,
3698         );
3699     }
3700
3701     #[test]
3702     fn try_result() {
3703         check_assist(
3704             extract_function,
3705             r#"
3706 //- minicore: result
3707 fn foo() -> Result<(), i64> {
3708     let n = 1;
3709     $0let k = foo()?;
3710     let m = k + 1;$0
3711     let h = 1 + m;
3712     Ok(())
3713 }
3714 "#,
3715             r#"
3716 fn foo() -> Result<(), i64> {
3717     let n = 1;
3718     let m = fun_name()?;
3719     let h = 1 + m;
3720     Ok(())
3721 }
3722
3723 fn $0fun_name() -> Result<i32, i64> {
3724     let k = foo()?;
3725     let m = k + 1;
3726     Ok(m)
3727 }
3728 "#,
3729         );
3730     }
3731
3732     #[test]
3733     fn try_option_with_return() {
3734         check_assist(
3735             extract_function,
3736             r#"
3737 //- minicore: option
3738 fn foo() -> Option<()> {
3739     let n = 1;
3740     $0let k = foo()?;
3741     if k == 42 {
3742         return None;
3743     }
3744     let m = k + 1;$0
3745     let h = 1 + m;
3746     Some(())
3747 }
3748 "#,
3749             r#"
3750 fn foo() -> Option<()> {
3751     let n = 1;
3752     let m = fun_name()?;
3753     let h = 1 + m;
3754     Some(())
3755 }
3756
3757 fn $0fun_name() -> Option<i32> {
3758     let k = foo()?;
3759     if k == 42 {
3760         return None;
3761     }
3762     let m = k + 1;
3763     Some(m)
3764 }
3765 "#,
3766         );
3767     }
3768
3769     #[test]
3770     fn try_result_with_return() {
3771         check_assist(
3772             extract_function,
3773             r#"
3774 //- minicore: result
3775 fn foo() -> Result<(), i64> {
3776     let n = 1;
3777     $0let k = foo()?;
3778     if k == 42 {
3779         return Err(1);
3780     }
3781     let m = k + 1;$0
3782     let h = 1 + m;
3783     Ok(())
3784 }
3785 "#,
3786             r#"
3787 fn foo() -> Result<(), i64> {
3788     let n = 1;
3789     let m = fun_name()?;
3790     let h = 1 + m;
3791     Ok(())
3792 }
3793
3794 fn $0fun_name() -> Result<i32, i64> {
3795     let k = foo()?;
3796     if k == 42 {
3797         return Err(1);
3798     }
3799     let m = k + 1;
3800     Ok(m)
3801 }
3802 "#,
3803         );
3804     }
3805
3806     #[test]
3807     fn try_and_break() {
3808         cov_mark::check!(external_control_flow_try_and_bc);
3809         check_assist_not_applicable(
3810             extract_function,
3811             r#"
3812 //- minicore: option
3813 fn foo() -> Option<()> {
3814     loop {
3815         let n = Some(1);
3816         $0let m = n? + 1;
3817         break;
3818         let k = 2;
3819         let k = k + 1;$0
3820         let r = n + k;
3821     }
3822     Some(())
3823 }
3824 "#,
3825         );
3826     }
3827
3828     #[test]
3829     fn try_and_return_ok() {
3830         check_assist(
3831             extract_function,
3832             r#"
3833 //- minicore: result
3834 fn foo() -> Result<(), i64> {
3835     let n = 1;
3836     $0let k = foo()?;
3837     if k == 42 {
3838         return Ok(1);
3839     }
3840     let m = k + 1;$0
3841     let h = 1 + m;
3842     Ok(())
3843 }
3844 "#,
3845             r#"
3846 fn foo() -> Result<(), i64> {
3847     let n = 1;
3848     let m = fun_name()?;
3849     let h = 1 + m;
3850     Ok(())
3851 }
3852
3853 fn $0fun_name() -> Result<i32, i64> {
3854     let k = foo()?;
3855     if k == 42 {
3856         return Ok(1);
3857     }
3858     let m = k + 1;
3859     Ok(m)
3860 }
3861 "#,
3862         );
3863     }
3864
3865     #[test]
3866     fn param_usage_in_macro() {
3867         check_assist(
3868             extract_function,
3869             r#"
3870 macro_rules! m {
3871     ($val:expr) => { $val };
3872 }
3873
3874 fn foo() {
3875     let n = 1;
3876     $0let k = n * m!(n);$0
3877     let m = k + 1;
3878 }
3879 "#,
3880             r#"
3881 macro_rules! m {
3882     ($val:expr) => { $val };
3883 }
3884
3885 fn foo() {
3886     let n = 1;
3887     let k = fun_name(n);
3888     let m = k + 1;
3889 }
3890
3891 fn $0fun_name(n: i32) -> i32 {
3892     let k = n * m!(n);
3893     k
3894 }
3895 "#,
3896         );
3897     }
3898
3899     #[test]
3900     fn extract_with_await() {
3901         check_assist(
3902             extract_function,
3903             r#"
3904 fn main() {
3905     $0some_function().await;$0
3906 }
3907
3908 async fn some_function() {
3909
3910 }
3911 "#,
3912             r#"
3913 fn main() {
3914     fun_name().await;
3915 }
3916
3917 async fn $0fun_name() {
3918     some_function().await;
3919 }
3920
3921 async fn some_function() {
3922
3923 }
3924 "#,
3925         );
3926     }
3927
3928     #[test]
3929     fn extract_with_await_and_result_not_producing_match_expr() {
3930         check_assist(
3931             extract_function,
3932             r#"
3933 async fn foo() -> Result<(), ()> {
3934     $0async {}.await;
3935     Err(())?$0
3936 }
3937 "#,
3938             r#"
3939 async fn foo() -> Result<(), ()> {
3940     fun_name().await?
3941 }
3942
3943 async fn $0fun_name() -> _ {
3944     async {}.await;
3945     Err(())?
3946 }
3947 "#,
3948         );
3949     }
3950
3951     #[test]
3952     fn extract_with_await_and_result_producing_match_expr() {
3953         check_assist(
3954             extract_function,
3955             r#"
3956 async fn foo() -> i32 {
3957     loop {
3958         let n = 1;$0
3959         let k = async { 1 }.await;
3960         if k == 42 {
3961             break 3;
3962         }
3963         let m = k + 1;$0
3964         let h = 1 + m;
3965     }
3966 }
3967 "#,
3968             r#"
3969 async fn foo() -> i32 {
3970     loop {
3971         let n = 1;
3972         let m = match fun_name().await {
3973             Ok(value) => value,
3974             Err(value) => break value,
3975         };
3976         let h = 1 + m;
3977     }
3978 }
3979
3980 async fn $0fun_name() -> Result<i32, i32> {
3981     let k = async { 1 }.await;
3982     if k == 42 {
3983         return Err(3);
3984     }
3985     let m = k + 1;
3986     Ok(m)
3987 }
3988 "#,
3989         );
3990     }
3991
3992     #[test]
3993     fn extract_with_await_in_args() {
3994         check_assist(
3995             extract_function,
3996             r#"
3997 fn main() {
3998     $0function_call("a", some_function().await);$0
3999 }
4000
4001 async fn some_function() {
4002
4003 }
4004 "#,
4005             r#"
4006 fn main() {
4007     fun_name().await;
4008 }
4009
4010 async fn $0fun_name() {
4011     function_call("a", some_function().await);
4012 }
4013
4014 async fn some_function() {
4015
4016 }
4017 "#,
4018         );
4019     }
4020
4021     #[test]
4022     fn extract_does_not_extract_standalone_blocks() {
4023         check_assist_not_applicable(
4024             extract_function,
4025             r#"
4026 fn main() $0{}$0
4027 "#,
4028         );
4029     }
4030
4031     #[test]
4032     fn extract_adds_comma_for_match_arm() {
4033         check_assist(
4034             extract_function,
4035             r#"
4036 fn main() {
4037     match 6 {
4038         100 => $0{ 100 }$0
4039         _ => 0,
4040     }
4041 }
4042 "#,
4043             r#"
4044 fn main() {
4045     match 6 {
4046         100 => fun_name(),
4047         _ => 0,
4048     }
4049 }
4050
4051 fn $0fun_name() -> i32 {
4052     100
4053 }
4054 "#,
4055         );
4056         check_assist(
4057             extract_function,
4058             r#"
4059 fn main() {
4060     match 6 {
4061         100 => $0{ 100 }$0,
4062         _ => 0,
4063     }
4064 }
4065 "#,
4066             r#"
4067 fn main() {
4068     match 6 {
4069         100 => fun_name(),
4070         _ => 0,
4071     }
4072 }
4073
4074 fn $0fun_name() -> i32 {
4075     100
4076 }
4077 "#,
4078         );
4079     }
4080
4081     #[test]
4082     fn extract_does_not_tear_comments_apart() {
4083         check_assist(
4084             extract_function,
4085             r#"
4086 fn foo() {
4087     /*$0*/
4088     foo();
4089     foo();
4090     /*$0*/
4091 }
4092 "#,
4093             r#"
4094 fn foo() {
4095     /**/
4096     fun_name();
4097     /**/
4098 }
4099
4100 fn $0fun_name() {
4101     foo();
4102     foo();
4103 }
4104 "#,
4105         );
4106     }
4107
4108     #[test]
4109     fn extract_does_not_wrap_res_in_res() {
4110         check_assist(
4111             extract_function,
4112             r#"
4113 //- minicore: result
4114 fn foo() -> Result<(), i64> {
4115     $0Result::<i32, i64>::Ok(0)?;
4116     Ok(())$0
4117 }
4118 "#,
4119             r#"
4120 fn foo() -> Result<(), i64> {
4121     fun_name()?
4122 }
4123
4124 fn $0fun_name() -> Result<(), i64> {
4125     Result::<i32, i64>::Ok(0)?;
4126     Ok(())
4127 }
4128 "#,
4129         );
4130     }
4131
4132     #[test]
4133     fn extract_knows_const() {
4134         check_assist(
4135             extract_function,
4136             r#"
4137 const fn foo() {
4138     $0()$0
4139 }
4140 "#,
4141             r#"
4142 const fn foo() {
4143     fun_name();
4144 }
4145
4146 const fn $0fun_name() {
4147     ()
4148 }
4149 "#,
4150         );
4151         check_assist(
4152             extract_function,
4153             r#"
4154 const FOO: () = {
4155     $0()$0
4156 };
4157 "#,
4158             r#"
4159 const FOO: () = {
4160     fun_name();
4161 };
4162
4163 const fn $0fun_name() {
4164     ()
4165 }
4166 "#,
4167         );
4168     }
4169
4170     #[test]
4171     fn extract_does_not_move_outer_loop_vars() {
4172         check_assist(
4173             extract_function,
4174             r#"
4175 fn foo() {
4176     let mut x = 5;
4177     for _ in 0..10 {
4178         $0x += 1;$0
4179     }
4180 }
4181 "#,
4182             r#"
4183 fn foo() {
4184     let mut x = 5;
4185     for _ in 0..10 {
4186         fun_name(&mut x);
4187     }
4188 }
4189
4190 fn $0fun_name(x: &mut i32) {
4191     *x += 1;
4192 }
4193 "#,
4194         );
4195         check_assist(
4196             extract_function,
4197             r#"
4198 fn foo() {
4199     for _ in 0..10 {
4200         let mut x = 5;
4201         $0x += 1;$0
4202     }
4203 }
4204 "#,
4205             r#"
4206 fn foo() {
4207     for _ in 0..10 {
4208         let mut x = 5;
4209         fun_name(x);
4210     }
4211 }
4212
4213 fn $0fun_name(mut x: i32) {
4214     x += 1;
4215 }
4216 "#,
4217         );
4218         check_assist(
4219             extract_function,
4220             r#"
4221 fn foo() {
4222     loop {
4223         let mut x = 5;
4224         for _ in 0..10 {
4225             $0x += 1;$0
4226         }
4227     }
4228 }
4229 "#,
4230             r#"
4231 fn foo() {
4232     loop {
4233         let mut x = 5;
4234         for _ in 0..10 {
4235             fun_name(&mut x);
4236         }
4237     }
4238 }
4239
4240 fn $0fun_name(x: &mut i32) {
4241     *x += 1;
4242 }
4243 "#,
4244         );
4245     }
4246
4247     // regression test for #9822
4248     #[test]
4249     fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4250         check_assist(
4251             extract_function,
4252             r#"
4253 struct Foo;
4254 impl Foo {
4255     fn foo(&mut self) {}
4256 }
4257 fn foo() {
4258     let mut x = Foo;
4259     while false {
4260         let y = &mut x;
4261         $0y.foo();$0
4262     }
4263     let z = x;
4264 }
4265 "#,
4266             r#"
4267 struct Foo;
4268 impl Foo {
4269     fn foo(&mut self) {}
4270 }
4271 fn foo() {
4272     let mut x = Foo;
4273     while false {
4274         let y = &mut x;
4275         fun_name(y);
4276     }
4277     let z = x;
4278 }
4279
4280 fn $0fun_name(y: &mut Foo) {
4281     y.foo();
4282 }
4283 "#,
4284         );
4285     }
4286
4287     #[test]
4288     fn extract_with_macro_arg() {
4289         check_assist(
4290             extract_function,
4291             r#"
4292 macro_rules! m {
4293     ($val:expr) => { $val };
4294 }
4295 fn main() {
4296     let bar = "bar";
4297     $0m!(bar);$0
4298 }
4299 "#,
4300             r#"
4301 macro_rules! m {
4302     ($val:expr) => { $val };
4303 }
4304 fn main() {
4305     let bar = "bar";
4306     fun_name(bar);
4307 }
4308
4309 fn $0fun_name(bar: &str) {
4310     m!(bar);
4311 }
4312 "#,
4313         );
4314     }
4315
4316     #[test]
4317     fn unresolveable_types_default_to_placeholder() {
4318         check_assist(
4319             extract_function,
4320             r#"
4321 fn foo() {
4322     let a = __unresolved;
4323     let _ = $0{a}$0;
4324 }
4325 "#,
4326             r#"
4327 fn foo() {
4328     let a = __unresolved;
4329     let _ = fun_name(a);
4330 }
4331
4332 fn $0fun_name(a: _) -> _ {
4333     a
4334 }
4335 "#,
4336         );
4337     }
4338 }