]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
Rollup merge of #103996 - SUPERCILEX:docs, r=RalfJung
[rust.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / destructure_tuple_binding.rs
1 use ide_db::{
2     assists::{AssistId, AssistKind},
3     defs::Definition,
4     search::{FileReference, SearchScope, UsageSearchResult},
5 };
6 use syntax::{
7     ast::{self, AstNode, FieldExpr, HasName, IdentPat, MethodCallExpr},
8     TextRange,
9 };
10
11 use crate::assist_context::{AssistContext, Assists, SourceChangeBuilder};
12
13 // Assist: destructure_tuple_binding
14 //
15 // Destructures a tuple binding in place.
16 //
17 // ```
18 // fn main() {
19 //     let $0t = (1,2);
20 //     let v = t.0;
21 // }
22 // ```
23 // ->
24 // ```
25 // fn main() {
26 //     let ($0_0, _1) = (1,2);
27 //     let v = _0;
28 // }
29 // ```
30 pub(crate) fn destructure_tuple_binding(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
31     destructure_tuple_binding_impl(acc, ctx, false)
32 }
33
34 // And when `with_sub_pattern` enabled (currently disabled):
35 // Assist: destructure_tuple_binding_in_sub_pattern
36 //
37 // Destructures tuple items in sub-pattern (after `@`).
38 //
39 // ```
40 // fn main() {
41 //     let $0t = (1,2);
42 //     let v = t.0;
43 // }
44 // ```
45 // ->
46 // ```
47 // fn main() {
48 //     let t @ ($0_0, _1) = (1,2);
49 //     let v = _0;
50 // }
51 // ```
52 pub(crate) fn destructure_tuple_binding_impl(
53     acc: &mut Assists,
54     ctx: &AssistContext<'_>,
55     with_sub_pattern: bool,
56 ) -> Option<()> {
57     let ident_pat = ctx.find_node_at_offset::<ast::IdentPat>()?;
58     let data = collect_data(ident_pat, ctx)?;
59
60     if with_sub_pattern {
61         acc.add(
62             AssistId("destructure_tuple_binding_in_sub_pattern", AssistKind::RefactorRewrite),
63             "Destructure tuple in sub-pattern",
64             data.range,
65             |builder| {
66                 edit_tuple_assignment(ctx, builder, &data, true);
67                 edit_tuple_usages(&data, builder, ctx, true);
68             },
69         );
70     }
71
72     acc.add(
73         AssistId("destructure_tuple_binding", AssistKind::RefactorRewrite),
74         if with_sub_pattern { "Destructure tuple in place" } else { "Destructure tuple" },
75         data.range,
76         |builder| {
77             edit_tuple_assignment(ctx, builder, &data, false);
78             edit_tuple_usages(&data, builder, ctx, false);
79         },
80     );
81
82     Some(())
83 }
84
85 fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleData> {
86     if ident_pat.at_token().is_some() {
87         // Cannot destructure pattern with sub-pattern:
88         // Only IdentPat can have sub-pattern,
89         // but not TuplePat (`(a,b)`).
90         cov_mark::hit!(destructure_tuple_subpattern);
91         return None;
92     }
93
94     let ty = ctx.sema.type_of_pat(&ident_pat.clone().into())?.adjusted();
95     let ref_type = if ty.is_mutable_reference() {
96         Some(RefType::Mutable)
97     } else if ty.is_reference() {
98         Some(RefType::ReadOnly)
99     } else {
100         None
101     };
102     // might be reference
103     let ty = ty.strip_references();
104     // must be tuple
105     let field_types = ty.tuple_fields(ctx.db());
106     if field_types.is_empty() {
107         cov_mark::hit!(destructure_tuple_no_tuple);
108         return None;
109     }
110
111     let name = ident_pat.name()?.to_string();
112     let range = ident_pat.syntax().text_range();
113
114     let usages = ctx.sema.to_def(&ident_pat).map(|def| {
115         Definition::Local(def)
116             .usages(&ctx.sema)
117             .in_scope(SearchScope::single_file(ctx.file_id()))
118             .all()
119     });
120
121     let field_names = (0..field_types.len())
122         .map(|i| generate_name(ctx, i, &name, &ident_pat, &usages))
123         .collect::<Vec<_>>();
124
125     Some(TupleData { ident_pat, range, ref_type, field_names, usages })
126 }
127
128 fn generate_name(
129     _ctx: &AssistContext<'_>,
130     index: usize,
131     _tuple_name: &str,
132     _ident_pat: &IdentPat,
133     _usages: &Option<UsageSearchResult>,
134 ) -> String {
135     // FIXME: detect if name already used
136     format!("_{index}")
137 }
138
139 enum RefType {
140     ReadOnly,
141     Mutable,
142 }
143 struct TupleData {
144     ident_pat: IdentPat,
145     // name: String,
146     range: TextRange,
147     ref_type: Option<RefType>,
148     field_names: Vec<String>,
149     // field_types: Vec<Type>,
150     usages: Option<UsageSearchResult>,
151 }
152 fn edit_tuple_assignment(
153     ctx: &AssistContext<'_>,
154     builder: &mut SourceChangeBuilder,
155     data: &TupleData,
156     in_sub_pattern: bool,
157 ) {
158     let tuple_pat = {
159         let original = &data.ident_pat;
160         let is_ref = original.ref_token().is_some();
161         let is_mut = original.mut_token().is_some();
162         let fields = data.field_names.iter().map(|name| {
163             ast::Pat::from(ast::make::ident_pat(is_ref, is_mut, ast::make::name(name)))
164         });
165         ast::make::tuple_pat(fields)
166     };
167
168     let add_cursor = |text: &str| {
169         // place cursor on first tuple item
170         let first_tuple = &data.field_names[0];
171         text.replacen(first_tuple, &format!("$0{first_tuple}"), 1)
172     };
173
174     // with sub_pattern: keep original tuple and add subpattern: `tup @ (_0, _1)`
175     if in_sub_pattern {
176         let text = format!(" @ {tuple_pat}");
177         match ctx.config.snippet_cap {
178             Some(cap) => {
179                 let snip = add_cursor(&text);
180                 builder.insert_snippet(cap, data.range.end(), snip);
181             }
182             None => builder.insert(data.range.end(), text),
183         };
184     } else {
185         let text = tuple_pat.to_string();
186         match ctx.config.snippet_cap {
187             Some(cap) => {
188                 let snip = add_cursor(&text);
189                 builder.replace_snippet(cap, data.range, snip);
190             }
191             None => builder.replace(data.range, text),
192         };
193     }
194 }
195
196 fn edit_tuple_usages(
197     data: &TupleData,
198     builder: &mut SourceChangeBuilder,
199     ctx: &AssistContext<'_>,
200     in_sub_pattern: bool,
201 ) {
202     if let Some(usages) = data.usages.as_ref() {
203         for (file_id, refs) in usages.iter() {
204             builder.edit_file(*file_id);
205
206             for r in refs {
207                 edit_tuple_usage(ctx, builder, r, data, in_sub_pattern);
208             }
209         }
210     }
211 }
212 fn edit_tuple_usage(
213     ctx: &AssistContext<'_>,
214     builder: &mut SourceChangeBuilder,
215     usage: &FileReference,
216     data: &TupleData,
217     in_sub_pattern: bool,
218 ) {
219     match detect_tuple_index(usage, data) {
220         Some(index) => edit_tuple_field_usage(ctx, builder, data, index),
221         None => {
222             if in_sub_pattern {
223                 cov_mark::hit!(destructure_tuple_call_with_subpattern);
224                 return;
225             }
226
227             // no index access -> make invalid -> requires handling by user
228             // -> put usage in block comment
229             //
230             // Note: For macro invocations this might result in still valid code:
231             //   When a macro accepts the tuple as argument, as well as no arguments at all,
232             //   uncommenting the tuple still leaves the macro call working (see `tests::in_macro_call::empty_macro`).
233             //   But this is an unlikely case. Usually the resulting macro call will become erroneous.
234             builder.insert(usage.range.start(), "/*");
235             builder.insert(usage.range.end(), "*/");
236         }
237     }
238 }
239
240 fn edit_tuple_field_usage(
241     ctx: &AssistContext<'_>,
242     builder: &mut SourceChangeBuilder,
243     data: &TupleData,
244     index: TupleIndex,
245 ) {
246     let field_name = &data.field_names[index.index];
247
248     if data.ref_type.is_some() {
249         let ref_data = handle_ref_field_usage(ctx, &index.field_expr);
250         builder.replace(ref_data.range, ref_data.format(field_name));
251     } else {
252         builder.replace(index.range, field_name);
253     }
254 }
255 struct TupleIndex {
256     index: usize,
257     range: TextRange,
258     field_expr: FieldExpr,
259 }
260 fn detect_tuple_index(usage: &FileReference, data: &TupleData) -> Option<TupleIndex> {
261     // usage is IDENT
262     // IDENT
263     //  NAME_REF
264     //   PATH_SEGMENT
265     //    PATH
266     //     PATH_EXPR
267     //      PAREN_EXRP*
268     //       FIELD_EXPR
269
270     let node = usage
271         .name
272         .syntax()
273         .ancestors()
274         .skip_while(|s| !ast::PathExpr::can_cast(s.kind()))
275         .skip(1) // PATH_EXPR
276         .find(|s| !ast::ParenExpr::can_cast(s.kind()))?; // skip parentheses
277
278     if let Some(field_expr) = ast::FieldExpr::cast(node) {
279         let idx = field_expr.name_ref()?.as_tuple_field()?;
280         if idx < data.field_names.len() {
281             // special case: in macro call -> range of `field_expr` in applied macro, NOT range in actual file!
282             if field_expr.syntax().ancestors().any(|a| ast::MacroStmts::can_cast(a.kind())) {
283                 cov_mark::hit!(destructure_tuple_macro_call);
284
285                 // issue: cannot differentiate between tuple index passed into macro or tuple index as result of macro:
286                 // ```rust
287                 // macro_rules! m {
288                 //     ($t1:expr, $t2:expr) => { $t1; $t2.0 }
289                 // }
290                 // let t = (1,2);
291                 // m!(t.0, t)
292                 // ```
293                 // -> 2 tuple index usages detected!
294                 //
295                 // -> only handle `t`
296                 return None;
297             }
298
299             Some(TupleIndex { index: idx, range: field_expr.syntax().text_range(), field_expr })
300         } else {
301             // tuple index out of range
302             None
303         }
304     } else {
305         None
306     }
307 }
308
309 struct RefData {
310     range: TextRange,
311     needs_deref: bool,
312     needs_parentheses: bool,
313 }
314 impl RefData {
315     fn format(&self, field_name: &str) -> String {
316         match (self.needs_deref, self.needs_parentheses) {
317             (true, true) => format!("(*{field_name})"),
318             (true, false) => format!("*{field_name}"),
319             (false, true) => format!("({field_name})"),
320             (false, false) => field_name.to_string(),
321         }
322     }
323 }
324 fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> RefData {
325     let s = field_expr.syntax();
326     let mut ref_data =
327         RefData { range: s.text_range(), needs_deref: true, needs_parentheses: true };
328
329     let parent = match s.parent().map(ast::Expr::cast) {
330         Some(Some(parent)) => parent,
331         Some(None) => {
332             ref_data.needs_parentheses = false;
333             return ref_data;
334         }
335         None => return ref_data,
336     };
337
338     match parent {
339         ast::Expr::ParenExpr(it) => {
340             // already parens in place -> don't replace
341             ref_data.needs_parentheses = false;
342             // there might be a ref outside: `&(t.0)` -> can be removed
343             if let Some(it) = it.syntax().parent().and_then(ast::RefExpr::cast) {
344                 ref_data.needs_deref = false;
345                 ref_data.range = it.syntax().text_range();
346             }
347         }
348         ast::Expr::RefExpr(it) => {
349             // `&*` -> cancel each other out
350             ref_data.needs_deref = false;
351             ref_data.needs_parentheses = false;
352             // might be surrounded by parens -> can be removed too
353             match it.syntax().parent().and_then(ast::ParenExpr::cast) {
354                 Some(parent) => ref_data.range = parent.syntax().text_range(),
355                 None => ref_data.range = it.syntax().text_range(),
356             };
357         }
358         // higher precedence than deref `*`
359         // https://doc.rust-lang.org/reference/expressions.html#expression-precedence
360         // -> requires parentheses
361         ast::Expr::PathExpr(_it) => {}
362         ast::Expr::MethodCallExpr(it) => {
363             // `field_expr` is `self_param` (otherwise it would be in `ArgList`)
364
365             // test if there's already auto-ref in place (`value` -> `&value`)
366             // -> no method accepting `self`, but `&self` -> no need for deref
367             //
368             // other combinations (`&value` -> `value`, `&&value` -> `&value`, `&value` -> `&&value`) might or might not be able to auto-ref/deref,
369             // but there might be trait implementations an added `&` might resolve to
370             // -> ONLY handle auto-ref from `value` to `&value`
371             fn is_auto_ref(ctx: &AssistContext<'_>, call_expr: &MethodCallExpr) -> bool {
372                 fn impl_(ctx: &AssistContext<'_>, call_expr: &MethodCallExpr) -> Option<bool> {
373                     let rec = call_expr.receiver()?;
374                     let rec_ty = ctx.sema.type_of_expr(&rec)?.original();
375                     // input must be actual value
376                     if rec_ty.is_reference() {
377                         return Some(false);
378                     }
379
380                     // doesn't resolve trait impl
381                     let f = ctx.sema.resolve_method_call(call_expr)?;
382                     let self_param = f.self_param(ctx.db())?;
383                     // self must be ref
384                     match self_param.access(ctx.db()) {
385                         hir::Access::Shared | hir::Access::Exclusive => Some(true),
386                         hir::Access::Owned => Some(false),
387                     }
388                 }
389                 impl_(ctx, call_expr).unwrap_or(false)
390             }
391
392             if is_auto_ref(ctx, &it) {
393                 ref_data.needs_deref = false;
394                 ref_data.needs_parentheses = false;
395             }
396         }
397         ast::Expr::FieldExpr(_it) => {
398             // `t.0.my_field`
399             ref_data.needs_deref = false;
400             ref_data.needs_parentheses = false;
401         }
402         ast::Expr::IndexExpr(_it) => {
403             // `t.0[1]`
404             ref_data.needs_deref = false;
405             ref_data.needs_parentheses = false;
406         }
407         ast::Expr::TryExpr(_it) => {
408             // `t.0?`
409             // requires deref and parens: `(*_0)`
410         }
411         // lower precedence than deref `*` -> no parens
412         _ => {
413             ref_data.needs_parentheses = false;
414         }
415     };
416
417     ref_data
418 }
419
420 #[cfg(test)]
421 mod tests {
422     use super::*;
423
424     use crate::tests::{check_assist, check_assist_not_applicable};
425
426     // Tests for direct tuple destructure:
427     // `let $0t = (1,2);` -> `let (_0, _1) = (1,2);`
428
429     fn assist(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
430         destructure_tuple_binding_impl(acc, ctx, false)
431     }
432
433     #[test]
434     fn dont_trigger_on_unit() {
435         cov_mark::check!(destructure_tuple_no_tuple);
436         check_assist_not_applicable(
437             assist,
438             r#"
439 fn main() {
440 let $0v = ();
441 }
442             "#,
443         )
444     }
445     #[test]
446     fn dont_trigger_on_number() {
447         cov_mark::check!(destructure_tuple_no_tuple);
448         check_assist_not_applicable(
449             assist,
450             r#"
451 fn main() {
452 let $0v = 32;
453 }
454             "#,
455         )
456     }
457
458     #[test]
459     fn destructure_3_tuple() {
460         check_assist(
461             assist,
462             r#"
463 fn main() {
464     let $0tup = (1,2,3);
465 }
466             "#,
467             r#"
468 fn main() {
469     let ($0_0, _1, _2) = (1,2,3);
470 }
471             "#,
472         )
473     }
474     #[test]
475     fn destructure_2_tuple() {
476         check_assist(
477             assist,
478             r#"
479 fn main() {
480     let $0tup = (1,2);
481 }
482             "#,
483             r#"
484 fn main() {
485     let ($0_0, _1) = (1,2);
486 }
487             "#,
488         )
489     }
490     #[test]
491     fn replace_indices() {
492         check_assist(
493             assist,
494             r#"
495 fn main() {
496     let $0tup = (1,2,3);
497     let v1 = tup.0;
498     let v2 = tup.1;
499     let v3 = tup.2;
500 }
501             "#,
502             r#"
503 fn main() {
504     let ($0_0, _1, _2) = (1,2,3);
505     let v1 = _0;
506     let v2 = _1;
507     let v3 = _2;
508 }
509             "#,
510         )
511     }
512
513     #[test]
514     fn replace_usage_in_parentheses() {
515         check_assist(
516             assist,
517             r#"
518 fn main() {
519     let $0tup = (1,2,3);
520     let a = (tup).1;
521     let b = ((tup)).1;
522 }
523             "#,
524             r#"
525 fn main() {
526     let ($0_0, _1, _2) = (1,2,3);
527     let a = _1;
528     let b = _1;
529 }
530             "#,
531         )
532     }
533
534     #[test]
535     fn handle_function_call() {
536         check_assist(
537             assist,
538             r#"
539 fn main() {
540     let $0tup = (1,2);
541     let v = tup.into();
542 }
543             "#,
544             r#"
545 fn main() {
546     let ($0_0, _1) = (1,2);
547     let v = /*tup*/.into();
548 }
549             "#,
550         )
551     }
552
553     #[test]
554     fn handle_invalid_index() {
555         check_assist(
556             assist,
557             r#"
558 fn main() {
559     let $0tup = (1,2);
560     let v = tup.3;
561 }
562             "#,
563             r#"
564 fn main() {
565     let ($0_0, _1) = (1,2);
566     let v = /*tup*/.3;
567 }
568             "#,
569         )
570     }
571
572     #[test]
573     fn dont_replace_variable_with_same_name_as_tuple() {
574         check_assist(
575             assist,
576             r#"
577 fn main() {
578     let tup = (1,2);
579     let v = tup.1;
580     let $0tup = (1,2,3);
581     let v = tup.1;
582     let tup = (1,2,3);
583     let v = tup.1;
584 }
585             "#,
586             r#"
587 fn main() {
588     let tup = (1,2);
589     let v = tup.1;
590     let ($0_0, _1, _2) = (1,2,3);
591     let v = _1;
592     let tup = (1,2,3);
593     let v = tup.1;
594 }
595             "#,
596         )
597     }
598
599     #[test]
600     fn keep_function_call_in_tuple_item() {
601         check_assist(
602             assist,
603             r#"
604 fn main() {
605     let $0t = ("3.14", 0);
606     let pi: f32 = t.0.parse().unwrap_or(0.0);
607 }
608             "#,
609             r#"
610 fn main() {
611     let ($0_0, _1) = ("3.14", 0);
612     let pi: f32 = _0.parse().unwrap_or(0.0);
613 }
614             "#,
615         )
616     }
617
618     #[test]
619     fn keep_type() {
620         check_assist(
621             assist,
622             r#"
623 fn main() {
624     let $0t: (usize, i32) = (1,2);
625 }
626             "#,
627             r#"
628 fn main() {
629     let ($0_0, _1): (usize, i32) = (1,2);
630 }
631             "#,
632         )
633     }
634
635     #[test]
636     fn destructure_reference() {
637         check_assist(
638             assist,
639             r#"
640 fn main() {
641     let t = (1,2);
642     let $0t = &t;
643     let v = t.0;
644 }
645             "#,
646             r#"
647 fn main() {
648     let t = (1,2);
649     let ($0_0, _1) = &t;
650     let v = *_0;
651 }
652             "#,
653         )
654     }
655
656     #[test]
657     fn destructure_multiple_reference() {
658         check_assist(
659             assist,
660             r#"
661 fn main() {
662     let t = (1,2);
663     let $0t = &&t;
664     let v = t.0;
665 }
666             "#,
667             r#"
668 fn main() {
669     let t = (1,2);
670     let ($0_0, _1) = &&t;
671     let v = *_0;
672 }
673             "#,
674         )
675     }
676
677     #[test]
678     fn keep_reference() {
679         check_assist(
680             assist,
681             r#"
682 fn foo(t: &(usize, usize)) -> usize {
683     match t {
684         &$0t => t.0
685     }
686 }
687             "#,
688             r#"
689 fn foo(t: &(usize, usize)) -> usize {
690     match t {
691         &($0_0, _1) => _0
692     }
693 }
694             "#,
695         )
696     }
697
698     #[test]
699     fn with_ref() {
700         check_assist(
701             assist,
702             r#"
703 fn main() {
704     let ref $0t = (1,2);
705     let v = t.0;
706 }
707             "#,
708             r#"
709 fn main() {
710     let (ref $0_0, ref _1) = (1,2);
711     let v = *_0;
712 }
713             "#,
714         )
715     }
716
717     #[test]
718     fn with_mut() {
719         check_assist(
720             assist,
721             r#"
722 fn main() {
723     let mut $0t = (1,2);
724     t.0 = 42;
725     let v = t.0;
726 }
727             "#,
728             r#"
729 fn main() {
730     let (mut $0_0, mut _1) = (1,2);
731     _0 = 42;
732     let v = _0;
733 }
734             "#,
735         )
736     }
737
738     #[test]
739     fn with_ref_mut() {
740         check_assist(
741             assist,
742             r#"
743 fn main() {
744     let ref mut $0t = (1,2);
745     t.0 = 42;
746     let v = t.0;
747 }
748             "#,
749             r#"
750 fn main() {
751     let (ref mut $0_0, ref mut _1) = (1,2);
752     *_0 = 42;
753     let v = *_0;
754 }
755             "#,
756         )
757     }
758
759     #[test]
760     fn dont_trigger_for_non_tuple_reference() {
761         check_assist_not_applicable(
762             assist,
763             r#"
764 fn main() {
765     let v = 42;
766     let $0v = &42;
767 }
768             "#,
769         )
770     }
771
772     #[test]
773     fn dont_trigger_on_static_tuple() {
774         check_assist_not_applicable(
775             assist,
776             r#"
777 static $0TUP: (usize, usize) = (1,2);
778             "#,
779         )
780     }
781
782     #[test]
783     fn dont_trigger_on_wildcard() {
784         check_assist_not_applicable(
785             assist,
786             r#"
787 fn main() {
788     let $0_ = (1,2);
789 }
790             "#,
791         )
792     }
793
794     #[test]
795     fn dont_trigger_in_struct() {
796         check_assist_not_applicable(
797             assist,
798             r#"
799 struct S {
800     $0tup: (usize, usize),
801 }
802             "#,
803         )
804     }
805
806     #[test]
807     fn dont_trigger_in_struct_creation() {
808         check_assist_not_applicable(
809             assist,
810             r#"
811 struct S {
812     tup: (usize, usize),
813 }
814 fn main() {
815     let s = S {
816         $0tup: (1,2),
817     };
818 }
819             "#,
820         )
821     }
822
823     #[test]
824     fn dont_trigger_on_tuple_struct() {
825         check_assist_not_applicable(
826             assist,
827             r#"
828 struct S(usize, usize);
829 fn main() {
830     let $0s = S(1,2);
831 }
832             "#,
833         )
834     }
835
836     #[test]
837     fn dont_trigger_when_subpattern_exists() {
838         // sub-pattern is only allowed with IdentPat (name), not other patterns (like TuplePat)
839         cov_mark::check!(destructure_tuple_subpattern);
840         check_assist_not_applicable(
841             assist,
842             r#"
843 fn sum(t: (usize, usize)) -> usize {
844     match t {
845         $0t @ (1..=3,1..=3) => t.0 + t.1,
846         _ => 0,
847     }
848 }
849             "#,
850         )
851     }
852
853     #[test]
854     fn in_subpattern() {
855         check_assist(
856             assist,
857             r#"
858 fn main() {
859     let t1 @ (_, $0t2) = (1, (2,3));
860     let v = t1.0 + t2.0 + t2.1;
861 }
862             "#,
863             r#"
864 fn main() {
865     let t1 @ (_, ($0_0, _1)) = (1, (2,3));
866     let v = t1.0 + _0 + _1;
867 }
868             "#,
869         )
870     }
871
872     #[test]
873     fn in_nested_tuple() {
874         check_assist(
875             assist,
876             r#"
877 fn main() {
878     let ($0tup, v) = ((1,2),3);
879 }
880             "#,
881             r#"
882 fn main() {
883     let (($0_0, _1), v) = ((1,2),3);
884 }
885             "#,
886         )
887     }
888
889     #[test]
890     fn in_closure() {
891         check_assist(
892             assist,
893             r#"
894 fn main() {
895     let $0tup = (1,2,3);
896     let f = |v| v + tup.1;
897 }
898             "#,
899             r#"
900 fn main() {
901     let ($0_0, _1, _2) = (1,2,3);
902     let f = |v| v + _1;
903 }
904             "#,
905         )
906     }
907
908     #[test]
909     fn in_closure_args() {
910         check_assist(
911             assist,
912             r#"
913 fn main() {
914     let f = |$0t| t.0 + t.1;
915     let v = f((1,2));
916 }
917             "#,
918             r#"
919 fn main() {
920     let f = |($0_0, _1)| _0 + _1;
921     let v = f((1,2));
922 }
923             "#,
924         )
925     }
926
927     #[test]
928     fn in_function_args() {
929         check_assist(
930             assist,
931             r#"
932 fn f($0t: (usize, usize)) {
933     let v = t.0;
934 }
935             "#,
936             r#"
937 fn f(($0_0, _1): (usize, usize)) {
938     let v = _0;
939 }
940             "#,
941         )
942     }
943
944     #[test]
945     fn in_if_let() {
946         check_assist(
947             assist,
948             r#"
949 fn f(t: (usize, usize)) {
950     if let $0t = t {
951         let v = t.0;
952     }
953 }
954             "#,
955             r#"
956 fn f(t: (usize, usize)) {
957     if let ($0_0, _1) = t {
958         let v = _0;
959     }
960 }
961             "#,
962         )
963     }
964     #[test]
965     fn in_if_let_option() {
966         check_assist(
967             assist,
968             r#"
969 //- minicore: option
970 fn f(o: Option<(usize, usize)>) {
971     if let Some($0t) = o {
972         let v = t.0;
973     }
974 }
975             "#,
976             r#"
977 fn f(o: Option<(usize, usize)>) {
978     if let Some(($0_0, _1)) = o {
979         let v = _0;
980     }
981 }
982             "#,
983         )
984     }
985
986     #[test]
987     fn in_match() {
988         check_assist(
989             assist,
990             r#"
991 fn main() {
992     match (1,2) {
993         $0t => t.1,
994     };
995 }
996             "#,
997             r#"
998 fn main() {
999     match (1,2) {
1000         ($0_0, _1) => _1,
1001     };
1002 }
1003             "#,
1004         )
1005     }
1006     #[test]
1007     fn in_match_option() {
1008         check_assist(
1009             assist,
1010             r#"
1011 //- minicore: option
1012 fn main() {
1013     match Some((1,2)) {
1014         Some($0t) => t.1,
1015         _ => 0,
1016     };
1017 }
1018             "#,
1019             r#"
1020 fn main() {
1021     match Some((1,2)) {
1022         Some(($0_0, _1)) => _1,
1023         _ => 0,
1024     };
1025 }
1026             "#,
1027         )
1028     }
1029     #[test]
1030     fn in_match_reference_option() {
1031         check_assist(
1032             assist,
1033             r#"
1034 //- minicore: option
1035 fn main() {
1036     let t = (1,2);
1037     match Some(&t) {
1038         Some($0t) => t.1,
1039         _ => 0,
1040     };
1041 }
1042             "#,
1043             r#"
1044 fn main() {
1045     let t = (1,2);
1046     match Some(&t) {
1047         Some(($0_0, _1)) => *_1,
1048         _ => 0,
1049     };
1050 }
1051             "#,
1052         )
1053     }
1054
1055     #[test]
1056     fn in_for() {
1057         check_assist(
1058             assist,
1059             r#"
1060 //- minicore: iterators
1061 fn main() {
1062     for $0t in core::iter::repeat((1,2))  {
1063         let v = t.1;
1064     }
1065 }
1066             "#,
1067             r#"
1068 fn main() {
1069     for ($0_0, _1) in core::iter::repeat((1,2))  {
1070         let v = _1;
1071     }
1072 }
1073             "#,
1074         )
1075     }
1076     #[test]
1077     fn in_for_nested() {
1078         check_assist(
1079             assist,
1080             r#"
1081 //- minicore: iterators
1082 fn main() {
1083     for (a, $0b) in core::iter::repeat((1,(2,3)))  {
1084         let v = b.1;
1085     }
1086 }
1087             "#,
1088             r#"
1089 fn main() {
1090     for (a, ($0_0, _1)) in core::iter::repeat((1,(2,3)))  {
1091         let v = _1;
1092     }
1093 }
1094             "#,
1095         )
1096     }
1097
1098     #[test]
1099     fn not_applicable_on_tuple_usage() {
1100         //Improvement: might be reasonable to allow & implement
1101         check_assist_not_applicable(
1102             assist,
1103             r#"
1104 fn main() {
1105     let t = (1,2);
1106     let v = $0t.0;
1107 }
1108             "#,
1109         )
1110     }
1111
1112     #[test]
1113     fn replace_all() {
1114         check_assist(
1115             assist,
1116             r#"
1117 fn main() {
1118     let $0t = (1,2);
1119     let v = t.1;
1120     let s = (t.0 + t.1) / 2;
1121     let f = |v| v + t.0;
1122     let r = f(t.1);
1123     let e = t == (9,0);
1124     let m =
1125       match t {
1126         (_,2) if t.0 > 2 => 1,
1127         _ => 0,
1128       };
1129 }
1130             "#,
1131             r#"
1132 fn main() {
1133     let ($0_0, _1) = (1,2);
1134     let v = _1;
1135     let s = (_0 + _1) / 2;
1136     let f = |v| v + _0;
1137     let r = f(_1);
1138     let e = /*t*/ == (9,0);
1139     let m =
1140       match /*t*/ {
1141         (_,2) if _0 > 2 => 1,
1142         _ => 0,
1143       };
1144 }
1145             "#,
1146         )
1147     }
1148
1149     #[test]
1150     fn non_trivial_tuple_assignment() {
1151         check_assist(
1152             assist,
1153             r#"
1154 fn main {
1155     let $0t =
1156         if 1 > 2 {
1157             (1,2)
1158         } else {
1159             (5,6)
1160         };
1161     let v1 = t.0;
1162     let v2 =
1163         if t.0 > t.1 {
1164             t.0 - t.1
1165         } else {
1166             t.1 - t.0
1167         };
1168 }
1169             "#,
1170             r#"
1171 fn main {
1172     let ($0_0, _1) =
1173         if 1 > 2 {
1174             (1,2)
1175         } else {
1176             (5,6)
1177         };
1178     let v1 = _0;
1179     let v2 =
1180         if _0 > _1 {
1181             _0 - _1
1182         } else {
1183             _1 - _0
1184         };
1185 }
1186             "#,
1187         )
1188     }
1189
1190     mod assist {
1191         use super::*;
1192         use crate::tests::check_assist_by_label;
1193
1194         fn assist(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
1195             destructure_tuple_binding_impl(acc, ctx, true)
1196         }
1197         fn in_place_assist(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
1198             destructure_tuple_binding_impl(acc, ctx, false)
1199         }
1200
1201         pub(crate) fn check_in_place_assist(ra_fixture_before: &str, ra_fixture_after: &str) {
1202             check_assist_by_label(
1203                 in_place_assist,
1204                 ra_fixture_before,
1205                 ra_fixture_after,
1206                 // "Destructure tuple in place",
1207                 "Destructure tuple",
1208             );
1209         }
1210
1211         pub(crate) fn check_sub_pattern_assist(ra_fixture_before: &str, ra_fixture_after: &str) {
1212             check_assist_by_label(
1213                 assist,
1214                 ra_fixture_before,
1215                 ra_fixture_after,
1216                 "Destructure tuple in sub-pattern",
1217             );
1218         }
1219
1220         pub(crate) fn check_both_assists(
1221             ra_fixture_before: &str,
1222             ra_fixture_after_in_place: &str,
1223             ra_fixture_after_in_sub_pattern: &str,
1224         ) {
1225             check_in_place_assist(ra_fixture_before, ra_fixture_after_in_place);
1226             check_sub_pattern_assist(ra_fixture_before, ra_fixture_after_in_sub_pattern);
1227         }
1228     }
1229
1230     /// Tests for destructure of tuple in sub-pattern:
1231     /// `let $0t = (1,2);` -> `let t @ (_0, _1) = (1,2);`
1232     mod sub_pattern {
1233         use super::assist::*;
1234         use super::*;
1235         use crate::tests::check_assist_by_label;
1236
1237         #[test]
1238         fn destructure_in_sub_pattern() {
1239             check_sub_pattern_assist(
1240                 r#"
1241 #![feature(bindings_after_at)]
1242
1243 fn main() {
1244     let $0t = (1,2);
1245 }
1246                 "#,
1247                 r#"
1248 #![feature(bindings_after_at)]
1249
1250 fn main() {
1251     let t @ ($0_0, _1) = (1,2);
1252 }
1253                 "#,
1254             )
1255         }
1256
1257         #[test]
1258         fn trigger_both_destructure_tuple_assists() {
1259             fn assist(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
1260                 destructure_tuple_binding_impl(acc, ctx, true)
1261             }
1262             let text = r#"
1263 fn main() {
1264     let $0t = (1,2);
1265 }
1266             "#;
1267             check_assist_by_label(
1268                 assist,
1269                 text,
1270                 r#"
1271 fn main() {
1272     let ($0_0, _1) = (1,2);
1273 }
1274             "#,
1275                 "Destructure tuple in place",
1276             );
1277             check_assist_by_label(
1278                 assist,
1279                 text,
1280                 r#"
1281 fn main() {
1282     let t @ ($0_0, _1) = (1,2);
1283 }
1284             "#,
1285                 "Destructure tuple in sub-pattern",
1286             );
1287         }
1288
1289         #[test]
1290         fn replace_indices() {
1291             check_sub_pattern_assist(
1292                 r#"
1293 fn main() {
1294     let $0t = (1,2);
1295     let v1 = t.0;
1296     let v2 = t.1;
1297 }
1298                 "#,
1299                 r#"
1300 fn main() {
1301     let t @ ($0_0, _1) = (1,2);
1302     let v1 = _0;
1303     let v2 = _1;
1304 }
1305                 "#,
1306             )
1307         }
1308
1309         #[test]
1310         fn keep_function_call() {
1311             cov_mark::check!(destructure_tuple_call_with_subpattern);
1312             check_sub_pattern_assist(
1313                 r#"
1314 fn main() {
1315     let $0t = (1,2);
1316     let v = t.into();
1317 }
1318                 "#,
1319                 r#"
1320 fn main() {
1321     let t @ ($0_0, _1) = (1,2);
1322     let v = t.into();
1323 }
1324                 "#,
1325             )
1326         }
1327
1328         #[test]
1329         fn keep_type() {
1330             check_sub_pattern_assist(
1331                 r#"
1332 fn main() {
1333     let $0t: (usize, i32) = (1,2);
1334     let v = t.1;
1335     let f = t.into();
1336 }
1337                 "#,
1338                 r#"
1339 fn main() {
1340     let t @ ($0_0, _1): (usize, i32) = (1,2);
1341     let v = _1;
1342     let f = t.into();
1343 }
1344                 "#,
1345             )
1346         }
1347
1348         #[test]
1349         fn in_function_args() {
1350             check_sub_pattern_assist(
1351                 r#"
1352 fn f($0t: (usize, usize)) {
1353     let v = t.0;
1354     let f = t.into();
1355 }
1356                 "#,
1357                 r#"
1358 fn f(t @ ($0_0, _1): (usize, usize)) {
1359     let v = _0;
1360     let f = t.into();
1361 }
1362                 "#,
1363             )
1364         }
1365
1366         #[test]
1367         fn with_ref() {
1368             check_sub_pattern_assist(
1369                 r#"
1370 fn main() {
1371     let ref $0t = (1,2);
1372     let v = t.1;
1373     let f = t.into();
1374 }
1375                 "#,
1376                 r#"
1377 fn main() {
1378     let ref t @ (ref $0_0, ref _1) = (1,2);
1379     let v = *_1;
1380     let f = t.into();
1381 }
1382                 "#,
1383             )
1384         }
1385         #[test]
1386         fn with_mut() {
1387             check_sub_pattern_assist(
1388                 r#"
1389 fn main() {
1390     let mut $0t = (1,2);
1391     let v = t.1;
1392     let f = t.into();
1393 }
1394                 "#,
1395                 r#"
1396 fn main() {
1397     let mut t @ (mut $0_0, mut _1) = (1,2);
1398     let v = _1;
1399     let f = t.into();
1400 }
1401                 "#,
1402             )
1403         }
1404         #[test]
1405         fn with_ref_mut() {
1406             check_sub_pattern_assist(
1407                 r#"
1408 fn main() {
1409     let ref mut $0t = (1,2);
1410     let v = t.1;
1411     let f = t.into();
1412 }
1413                 "#,
1414                 r#"
1415 fn main() {
1416     let ref mut t @ (ref mut $0_0, ref mut _1) = (1,2);
1417     let v = *_1;
1418     let f = t.into();
1419 }
1420                 "#,
1421             )
1422         }
1423     }
1424
1425     /// Tests for tuple usage in macro call:
1426     /// `println!("{}", t.0)`
1427     mod in_macro_call {
1428         use super::assist::*;
1429
1430         #[test]
1431         fn detect_macro_call() {
1432             cov_mark::check!(destructure_tuple_macro_call);
1433             check_in_place_assist(
1434                 r#"
1435 macro_rules! m {
1436     ($e:expr) => { "foo"; $e };
1437 }
1438
1439 fn main() {
1440     let $0t = (1,2);
1441     m!(t.0);
1442 }
1443                 "#,
1444                 r#"
1445 macro_rules! m {
1446     ($e:expr) => { "foo"; $e };
1447 }
1448
1449 fn main() {
1450     let ($0_0, _1) = (1,2);
1451     m!(/*t*/.0);
1452 }
1453                 "#,
1454             )
1455         }
1456
1457         #[test]
1458         fn tuple_usage() {
1459             check_both_assists(
1460                 // leading `"foo"` to ensure `$e` doesn't start at position `0`
1461                 r#"
1462 macro_rules! m {
1463     ($e:expr) => { "foo"; $e };
1464 }
1465
1466 fn main() {
1467     let $0t = (1,2);
1468     m!(t);
1469 }
1470                 "#,
1471                 r#"
1472 macro_rules! m {
1473     ($e:expr) => { "foo"; $e };
1474 }
1475
1476 fn main() {
1477     let ($0_0, _1) = (1,2);
1478     m!(/*t*/);
1479 }
1480                 "#,
1481                 r#"
1482 macro_rules! m {
1483     ($e:expr) => { "foo"; $e };
1484 }
1485
1486 fn main() {
1487     let t @ ($0_0, _1) = (1,2);
1488     m!(t);
1489 }
1490                 "#,
1491             )
1492         }
1493
1494         #[test]
1495         fn tuple_function_usage() {
1496             check_both_assists(
1497                 r#"
1498 macro_rules! m {
1499     ($e:expr) => { "foo"; $e };
1500 }
1501
1502 fn main() {
1503     let $0t = (1,2);
1504     m!(t.into());
1505 }
1506                 "#,
1507                 r#"
1508 macro_rules! m {
1509     ($e:expr) => { "foo"; $e };
1510 }
1511
1512 fn main() {
1513     let ($0_0, _1) = (1,2);
1514     m!(/*t*/.into());
1515 }
1516                 "#,
1517                 r#"
1518 macro_rules! m {
1519     ($e:expr) => { "foo"; $e };
1520 }
1521
1522 fn main() {
1523     let t @ ($0_0, _1) = (1,2);
1524     m!(t.into());
1525 }
1526                 "#,
1527             )
1528         }
1529
1530         #[test]
1531         fn tuple_index_usage() {
1532             check_both_assists(
1533                 r#"
1534 macro_rules! m {
1535     ($e:expr) => { "foo"; $e };
1536 }
1537
1538 fn main() {
1539     let $0t = (1,2);
1540     m!(t.0);
1541 }
1542                 "#,
1543                 // FIXME: replace `t.0` with `_0` (cannot detect range of tuple index in macro call)
1544                 r#"
1545 macro_rules! m {
1546     ($e:expr) => { "foo"; $e };
1547 }
1548
1549 fn main() {
1550     let ($0_0, _1) = (1,2);
1551     m!(/*t*/.0);
1552 }
1553                 "#,
1554                 // FIXME: replace `t.0` with `_0`
1555                 r#"
1556 macro_rules! m {
1557     ($e:expr) => { "foo"; $e };
1558 }
1559
1560 fn main() {
1561     let t @ ($0_0, _1) = (1,2);
1562     m!(t.0);
1563 }
1564                 "#,
1565             )
1566         }
1567
1568         #[test]
1569         fn tuple_in_parentheses_index_usage() {
1570             check_both_assists(
1571                 r#"
1572 macro_rules! m {
1573     ($e:expr) => { "foo"; $e };
1574 }
1575
1576 fn main() {
1577     let $0t = (1,2);
1578     m!((t).0);
1579 }
1580                 "#,
1581                 // FIXME: replace `(t).0` with `_0`
1582                 r#"
1583 macro_rules! m {
1584     ($e:expr) => { "foo"; $e };
1585 }
1586
1587 fn main() {
1588     let ($0_0, _1) = (1,2);
1589     m!((/*t*/).0);
1590 }
1591                 "#,
1592                 // FIXME: replace `(t).0` with `_0`
1593                 r#"
1594 macro_rules! m {
1595     ($e:expr) => { "foo"; $e };
1596 }
1597
1598 fn main() {
1599     let t @ ($0_0, _1) = (1,2);
1600     m!((t).0);
1601 }
1602                 "#,
1603             )
1604         }
1605
1606         #[test]
1607         fn empty_macro() {
1608             check_in_place_assist(
1609                 r#"
1610 macro_rules! m {
1611     () => { "foo" };
1612     ($e:expr) => { $e; "foo" };
1613 }
1614
1615 fn main() {
1616     let $0t = (1,2);
1617     m!(t);
1618 }
1619                 "#,
1620                 // FIXME: macro allows no arg -> is valid. But assist should result in invalid code
1621                 r#"
1622 macro_rules! m {
1623     () => { "foo" };
1624     ($e:expr) => { $e; "foo" };
1625 }
1626
1627 fn main() {
1628     let ($0_0, _1) = (1,2);
1629     m!(/*t*/);
1630 }
1631                 "#,
1632             )
1633         }
1634
1635         #[test]
1636         fn tuple_index_in_macro() {
1637             check_both_assists(
1638                 r#"
1639 macro_rules! m {
1640     ($t:expr, $i:expr) => { $t.0 + $i };
1641 }
1642
1643 fn main() {
1644     let $0t = (1,2);
1645     m!(t, t.0);
1646 }
1647                 "#,
1648                 // FIXME: replace `t.0` in macro call (not IN macro) with `_0`
1649                 r#"
1650 macro_rules! m {
1651     ($t:expr, $i:expr) => { $t.0 + $i };
1652 }
1653
1654 fn main() {
1655     let ($0_0, _1) = (1,2);
1656     m!(/*t*/, /*t*/.0);
1657 }
1658                 "#,
1659                 // FIXME: replace `t.0` in macro call with `_0`
1660                 r#"
1661 macro_rules! m {
1662     ($t:expr, $i:expr) => { $t.0 + $i };
1663 }
1664
1665 fn main() {
1666     let t @ ($0_0, _1) = (1,2);
1667     m!(t, t.0);
1668 }
1669                 "#,
1670             )
1671         }
1672     }
1673
1674     mod refs {
1675         use super::assist::*;
1676
1677         #[test]
1678         fn no_ref() {
1679             check_in_place_assist(
1680                 r#"
1681 fn main() {
1682     let $0t = &(1,2);
1683     let v: i32 = t.0;
1684 }
1685                 "#,
1686                 r#"
1687 fn main() {
1688     let ($0_0, _1) = &(1,2);
1689     let v: i32 = *_0;
1690 }
1691                 "#,
1692             )
1693         }
1694         #[test]
1695         fn no_ref_with_parens() {
1696             check_in_place_assist(
1697                 r#"
1698 fn main() {
1699     let $0t = &(1,2);
1700     let v: i32 = (t.0);
1701 }
1702                 "#,
1703                 r#"
1704 fn main() {
1705     let ($0_0, _1) = &(1,2);
1706     let v: i32 = (*_0);
1707 }
1708                 "#,
1709             )
1710         }
1711         #[test]
1712         fn with_ref() {
1713             check_in_place_assist(
1714                 r#"
1715 fn main() {
1716     let $0t = &(1,2);
1717     let v: &i32 = &t.0;
1718 }
1719                 "#,
1720                 r#"
1721 fn main() {
1722     let ($0_0, _1) = &(1,2);
1723     let v: &i32 = _0;
1724 }
1725                 "#,
1726             )
1727         }
1728         #[test]
1729         fn with_ref_in_parens_ref() {
1730             check_in_place_assist(
1731                 r#"
1732 fn main() {
1733     let $0t = &(1,2);
1734     let v: &i32 = &(t.0);
1735 }
1736                 "#,
1737                 r#"
1738 fn main() {
1739     let ($0_0, _1) = &(1,2);
1740     let v: &i32 = _0;
1741 }
1742                 "#,
1743             )
1744         }
1745         #[test]
1746         fn with_ref_in_ref_parens() {
1747             check_in_place_assist(
1748                 r#"
1749 fn main() {
1750     let $0t = &(1,2);
1751     let v: &i32 = (&t.0);
1752 }
1753                 "#,
1754                 r#"
1755 fn main() {
1756     let ($0_0, _1) = &(1,2);
1757     let v: &i32 = _0;
1758 }
1759                 "#,
1760             )
1761         }
1762
1763         #[test]
1764         fn deref_and_parentheses() {
1765             // Operator/Expressions with higher precedence than deref (`*`):
1766             // https://doc.rust-lang.org/reference/expressions.html#expression-precedence
1767             // * Path
1768             // * Method call
1769             // * Field expression
1770             // * Function calls, array indexing
1771             // * `?`
1772             check_in_place_assist(
1773                 r#"
1774 //- minicore: option
1775 fn f1(v: i32) {}
1776 fn f2(v: &i32) {}
1777 trait T {
1778     fn do_stuff(self) {}
1779 }
1780 impl T for i32 {
1781     fn do_stuff(self) {}
1782 }
1783 impl T for &i32 {
1784     fn do_stuff(self) {}
1785 }
1786 struct S4 {
1787     value: i32,
1788 }
1789
1790 fn foo() -> Option<()> {
1791     let $0t = &(0, (1,"1"), Some(2), [3;3], S4 { value: 4 }, &5);
1792     let v: i32 = t.0;           // deref, no parens
1793     let v: &i32 = &t.0;         // no deref, no parens, remove `&`
1794     f1(t.0);                    // deref, no parens
1795     f2(&t.0);                   // `&*` -> cancel out -> no deref, no parens
1796     // https://github.com/rust-lang/rust-analyzer/issues/1109#issuecomment-658868639
1797     // let v: i32 = t.1.0;      // no deref, no parens
1798     let v: i32 = t.4.value;     // no deref, no parens
1799     t.0.do_stuff();             // deref, parens
1800     let v: i32 = t.2?;          // deref, parens
1801     let v: i32 = t.3[0];        // no deref, no parens
1802     (t.0).do_stuff();           // deref, no additional parens
1803     let v: i32 = *t.5;          // deref (-> 2), no parens
1804
1805     None
1806 }
1807                 "#,
1808                 r#"
1809 fn f1(v: i32) {}
1810 fn f2(v: &i32) {}
1811 trait T {
1812     fn do_stuff(self) {}
1813 }
1814 impl T for i32 {
1815     fn do_stuff(self) {}
1816 }
1817 impl T for &i32 {
1818     fn do_stuff(self) {}
1819 }
1820 struct S4 {
1821     value: i32,
1822 }
1823
1824 fn foo() -> Option<()> {
1825     let ($0_0, _1, _2, _3, _4, _5) = &(0, (1,"1"), Some(2), [3;3], S4 { value: 4 }, &5);
1826     let v: i32 = *_0;           // deref, no parens
1827     let v: &i32 = _0;         // no deref, no parens, remove `&`
1828     f1(*_0);                    // deref, no parens
1829     f2(_0);                   // `&*` -> cancel out -> no deref, no parens
1830     // https://github.com/rust-lang/rust-analyzer/issues/1109#issuecomment-658868639
1831     // let v: i32 = t.1.0;      // no deref, no parens
1832     let v: i32 = _4.value;     // no deref, no parens
1833     (*_0).do_stuff();             // deref, parens
1834     let v: i32 = (*_2)?;          // deref, parens
1835     let v: i32 = _3[0];        // no deref, no parens
1836     (*_0).do_stuff();           // deref, no additional parens
1837     let v: i32 = **_5;          // deref (-> 2), no parens
1838
1839     None
1840 }
1841                 "#,
1842             )
1843         }
1844
1845         // ---------
1846         // auto-ref/deref
1847
1848         #[test]
1849         fn self_auto_ref_doesnt_need_deref() {
1850             check_in_place_assist(
1851                 r#"
1852 #[derive(Clone, Copy)]
1853 struct S;
1854 impl S {
1855   fn f(&self) {}
1856 }
1857
1858 fn main() {
1859     let $0t = &(S,2);
1860     let s = t.0.f();
1861 }
1862                 "#,
1863                 r#"
1864 #[derive(Clone, Copy)]
1865 struct S;
1866 impl S {
1867   fn f(&self) {}
1868 }
1869
1870 fn main() {
1871     let ($0_0, _1) = &(S,2);
1872     let s = _0.f();
1873 }
1874                 "#,
1875             )
1876         }
1877
1878         #[test]
1879         fn self_owned_requires_deref() {
1880             check_in_place_assist(
1881                 r#"
1882 #[derive(Clone, Copy)]
1883 struct S;
1884 impl S {
1885   fn f(self) {}
1886 }
1887
1888 fn main() {
1889     let $0t = &(S,2);
1890     let s = t.0.f();
1891 }
1892                 "#,
1893                 r#"
1894 #[derive(Clone, Copy)]
1895 struct S;
1896 impl S {
1897   fn f(self) {}
1898 }
1899
1900 fn main() {
1901     let ($0_0, _1) = &(S,2);
1902     let s = (*_0).f();
1903 }
1904                 "#,
1905             )
1906         }
1907
1908         #[test]
1909         fn self_auto_ref_in_trait_call_doesnt_require_deref() {
1910             check_in_place_assist(
1911                 r#"
1912 trait T {
1913     fn f(self);
1914 }
1915 #[derive(Clone, Copy)]
1916 struct S;
1917 impl T for &S {
1918     fn f(self) {}
1919 }
1920
1921 fn main() {
1922     let $0t = &(S,2);
1923     let s = t.0.f();
1924 }
1925                 "#,
1926                 // FIXME: doesn't need deref * parens. But `ctx.sema.resolve_method_call` doesn't resolve trait implementations
1927                 r#"
1928 trait T {
1929     fn f(self);
1930 }
1931 #[derive(Clone, Copy)]
1932 struct S;
1933 impl T for &S {
1934     fn f(self) {}
1935 }
1936
1937 fn main() {
1938     let ($0_0, _1) = &(S,2);
1939     let s = (*_0).f();
1940 }
1941                 "#,
1942             )
1943         }
1944         #[test]
1945         fn no_auto_deref_because_of_owned_and_ref_trait_impl() {
1946             check_in_place_assist(
1947                 r#"
1948 trait T {
1949     fn f(self);
1950 }
1951 #[derive(Clone, Copy)]
1952 struct S;
1953 impl T for S {
1954     fn f(self) {}
1955 }
1956 impl T for &S {
1957     fn f(self) {}
1958 }
1959
1960 fn main() {
1961     let $0t = &(S,2);
1962     let s = t.0.f();
1963 }
1964                 "#,
1965                 r#"
1966 trait T {
1967     fn f(self);
1968 }
1969 #[derive(Clone, Copy)]
1970 struct S;
1971 impl T for S {
1972     fn f(self) {}
1973 }
1974 impl T for &S {
1975     fn f(self) {}
1976 }
1977
1978 fn main() {
1979     let ($0_0, _1) = &(S,2);
1980     let s = (*_0).f();
1981 }
1982                 "#,
1983             )
1984         }
1985
1986         #[test]
1987         fn no_outer_parens_when_ref_deref() {
1988             check_in_place_assist(
1989                 r#"
1990 #[derive(Clone, Copy)]
1991 struct S;
1992 impl S {
1993     fn do_stuff(&self) -> i32 { 42 }
1994 }
1995 fn main() {
1996     let $0t = &(S,&S);
1997     let v = (&t.0).do_stuff();
1998 }
1999                 "#,
2000                 r#"
2001 #[derive(Clone, Copy)]
2002 struct S;
2003 impl S {
2004     fn do_stuff(&self) -> i32 { 42 }
2005 }
2006 fn main() {
2007     let ($0_0, _1) = &(S,&S);
2008     let v = _0.do_stuff();
2009 }
2010                 "#,
2011             )
2012         }
2013
2014         #[test]
2015         fn auto_ref_deref() {
2016             check_in_place_assist(
2017                 r#"
2018 #[derive(Clone, Copy)]
2019 struct S;
2020 impl S {
2021     fn do_stuff(&self) -> i32 { 42 }
2022 }
2023 fn main() {
2024     let $0t = &(S,&S);
2025     let v = (&t.0).do_stuff();      // no deref, remove parens
2026     // `t.0` gets auto-refed -> no deref needed -> no parens
2027     let v = t.0.do_stuff();         // no deref, no parens
2028     let v = &t.0.do_stuff();        // `&` is for result -> no deref, no parens
2029     // deref: `_1` is `&&S`, but method called is on `&S` -> there might be a method accepting `&&S`
2030     let v = t.1.do_stuff();         // deref, parens
2031 }
2032                 "#,
2033                 r#"
2034 #[derive(Clone, Copy)]
2035 struct S;
2036 impl S {
2037     fn do_stuff(&self) -> i32 { 42 }
2038 }
2039 fn main() {
2040     let ($0_0, _1) = &(S,&S);
2041     let v = _0.do_stuff();      // no deref, remove parens
2042     // `t.0` gets auto-refed -> no deref needed -> no parens
2043     let v = _0.do_stuff();         // no deref, no parens
2044     let v = &_0.do_stuff();        // `&` is for result -> no deref, no parens
2045     // deref: `_1` is `&&S`, but method called is on `&S` -> there might be a method accepting `&&S`
2046     let v = (*_1).do_stuff();         // deref, parens
2047 }
2048                 "#,
2049             )
2050         }
2051
2052         #[test]
2053         fn mutable() {
2054             check_in_place_assist(
2055                 r#"
2056 fn f_owned(v: i32) {}
2057 fn f(v: &i32) {}
2058 fn f_mut(v: &mut i32) { *v = 42; }
2059
2060 fn main() {
2061     let $0t = &mut (1,2);
2062     let v = t.0;
2063     t.0 = 42;
2064     f_owned(t.0);
2065     f(&t.0);
2066     f_mut(&mut t.0);
2067 }
2068                 "#,
2069                 r#"
2070 fn f_owned(v: i32) {}
2071 fn f(v: &i32) {}
2072 fn f_mut(v: &mut i32) { *v = 42; }
2073
2074 fn main() {
2075     let ($0_0, _1) = &mut (1,2);
2076     let v = *_0;
2077     *_0 = 42;
2078     f_owned(*_0);
2079     f(_0);
2080     f_mut(_0);
2081 }
2082                 "#,
2083             )
2084         }
2085
2086         #[test]
2087         fn with_ref_keyword() {
2088             check_in_place_assist(
2089                 r#"
2090 fn f_owned(v: i32) {}
2091 fn f(v: &i32) {}
2092
2093 fn main() {
2094     let ref $0t = (1,2);
2095     let v = t.0;
2096     f_owned(t.0);
2097     f(&t.0);
2098 }
2099                 "#,
2100                 r#"
2101 fn f_owned(v: i32) {}
2102 fn f(v: &i32) {}
2103
2104 fn main() {
2105     let (ref $0_0, ref _1) = (1,2);
2106     let v = *_0;
2107     f_owned(*_0);
2108     f(_0);
2109 }
2110                 "#,
2111             )
2112         }
2113         #[test]
2114         fn with_ref_mut_keywords() {
2115             check_in_place_assist(
2116                 r#"
2117 fn f_owned(v: i32) {}
2118 fn f(v: &i32) {}
2119 fn f_mut(v: &mut i32) { *v = 42; }
2120
2121 fn main() {
2122     let ref mut $0t = (1,2);
2123     let v = t.0;
2124     t.0 = 42;
2125     f_owned(t.0);
2126     f(&t.0);
2127     f_mut(&mut t.0);
2128 }
2129                 "#,
2130                 r#"
2131 fn f_owned(v: i32) {}
2132 fn f(v: &i32) {}
2133 fn f_mut(v: &mut i32) { *v = 42; }
2134
2135 fn main() {
2136     let (ref mut $0_0, ref mut _1) = (1,2);
2137     let v = *_0;
2138     *_0 = 42;
2139     f_owned(*_0);
2140     f(_0);
2141     f_mut(_0);
2142 }
2143                 "#,
2144             )
2145         }
2146     }
2147 }