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