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