• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Implementation of "type" inlay hints:
2 //! ```no_run
3 //! fn f(a: i32, b: i32) -> i32 { a + b }
4 //! let _x /* i32 */= f(4, 4);
5 //! ```
6 use hir::Semantics;
7 use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
8 
9 use itertools::Itertools;
10 use syntax::{
11     ast::{self, AstNode, HasName},
12     match_ast,
13 };
14 
15 use crate::{
16     inlay_hints::{closure_has_block_body, label_of_ty, ty_to_text_edit},
17     InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind,
18 };
19 
hints( acc: &mut Vec<InlayHint>, famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: FileId, pat: &ast::IdentPat, ) -> Option<()>20 pub(super) fn hints(
21     acc: &mut Vec<InlayHint>,
22     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
23     config: &InlayHintsConfig,
24     _file_id: FileId,
25     pat: &ast::IdentPat,
26 ) -> Option<()> {
27     if !config.type_hints {
28         return None;
29     }
30 
31     let parent = pat.syntax().parent()?;
32     let type_ascriptable = match_ast! {
33         match parent {
34             ast::Param(it) => {
35                 if it.ty().is_some() {
36                     return None;
37                 }
38                 Some(it.colon_token())
39             },
40             ast::LetStmt(it) => {
41                 if config.hide_closure_initialization_hints {
42                     if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
43                         if closure_has_block_body(&closure) {
44                             return None;
45                         }
46                     }
47                 }
48                 if it.ty().is_some() {
49                     return None;
50                 }
51                 Some(it.colon_token())
52             },
53             _ => None
54         }
55     };
56 
57     let descended = sema.descend_node_into_attributes(pat.clone()).pop();
58     let desc_pat = descended.as_ref().unwrap_or(pat);
59     let ty = sema.type_of_binding_in_pat(desc_pat)?;
60 
61     if ty.is_unknown() {
62         return None;
63     }
64 
65     if sema.resolve_bind_pat_to_const(pat).is_some() {
66         return None;
67     }
68 
69     let mut label = label_of_ty(famous_defs, config, &ty)?;
70 
71     if config.hide_named_constructor_hints
72         && is_named_constructor(sema, pat, &label.to_string()).is_some()
73     {
74         return None;
75     }
76 
77     let text_edit = if let Some(colon_token) = &type_ascriptable {
78         ty_to_text_edit(
79             sema,
80             desc_pat.syntax(),
81             &ty,
82             colon_token
83                 .as_ref()
84                 .map_or_else(|| pat.syntax().text_range(), |t| t.text_range())
85                 .end(),
86             if colon_token.is_some() { String::new() } else { String::from(": ") },
87         )
88     } else {
89         None
90     };
91 
92     let render_colons = config.render_colons && !matches!(type_ascriptable, Some(Some(_)));
93     if render_colons {
94         label.prepend_str(": ");
95     }
96 
97     let text_range = match pat.name() {
98         Some(name) => name.syntax().text_range(),
99         None => pat.syntax().text_range(),
100     };
101     acc.push(InlayHint {
102         range: match type_ascriptable {
103             Some(Some(t)) => text_range.cover(t.text_range()),
104             _ => text_range,
105         },
106         kind: InlayKind::Type,
107         label,
108         text_edit,
109         position: InlayHintPosition::After,
110         pad_left: !render_colons,
111         pad_right: false,
112     });
113 
114     Some(())
115 }
116 
is_named_constructor( sema: &Semantics<'_, RootDatabase>, pat: &ast::IdentPat, ty_name: &str, ) -> Option<()>117 fn is_named_constructor(
118     sema: &Semantics<'_, RootDatabase>,
119     pat: &ast::IdentPat,
120     ty_name: &str,
121 ) -> Option<()> {
122     let let_node = pat.syntax().parent()?;
123     let expr = match_ast! {
124         match let_node {
125             ast::LetStmt(it) => it.initializer(),
126             ast::LetExpr(it) => it.expr(),
127             _ => None,
128         }
129     }?;
130 
131     let expr = sema.descend_node_into_attributes(expr.clone()).pop().unwrap_or(expr);
132     // unwrap postfix expressions
133     let expr = match expr {
134         ast::Expr::TryExpr(it) => it.expr(),
135         ast::Expr::AwaitExpr(it) => it.expr(),
136         expr => Some(expr),
137     }?;
138     let expr = match expr {
139         ast::Expr::CallExpr(call) => match call.expr()? {
140             ast::Expr::PathExpr(path) => path,
141             _ => return None,
142         },
143         ast::Expr::PathExpr(path) => path,
144         _ => return None,
145     };
146     let path = expr.path()?;
147 
148     let callable = sema.type_of_expr(&ast::Expr::PathExpr(expr))?.original.as_callable(sema.db);
149     let callable_kind = callable.map(|it| it.kind());
150     let qual_seg = match callable_kind {
151         Some(hir::CallableKind::Function(_) | hir::CallableKind::TupleEnumVariant(_)) => {
152             path.qualifier()?.segment()
153         }
154         _ => path.segment(),
155     }?;
156 
157     let ctor_name = match qual_seg.kind()? {
158         ast::PathSegmentKind::Name(name_ref) => {
159             match qual_seg.generic_arg_list().map(|it| it.generic_args()) {
160                 Some(generics) => format!("{name_ref}<{}>", generics.format(", ")),
161                 None => name_ref.to_string(),
162             }
163         }
164         ast::PathSegmentKind::Type { type_ref: Some(ty), trait_ref: None } => ty.to_string(),
165         _ => return None,
166     };
167     (ctor_name == ty_name).then_some(())
168 }
169 
170 #[cfg(test)]
171 mod tests {
172     // This module also contains tests for super::closure_ret
173 
174     use expect_test::expect;
175     use hir::ClosureStyle;
176     use syntax::{TextRange, TextSize};
177     use test_utils::extract_annotations;
178 
179     use crate::{fixture, inlay_hints::InlayHintsConfig, ClosureReturnTypeHints};
180 
181     use crate::inlay_hints::tests::{
182         check, check_edit, check_no_edit, check_with_config, DISABLED_CONFIG, TEST_CONFIG,
183     };
184 
185     #[track_caller]
check_types(ra_fixture: &str)186     fn check_types(ra_fixture: &str) {
187         check_with_config(InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, ra_fixture);
188     }
189 
190     #[test]
type_hints_only()191     fn type_hints_only() {
192         check_types(
193             r#"
194 fn foo(a: i32, b: i32) -> i32 { a + b }
195 fn main() {
196     let _x = foo(4, 4);
197       //^^ i32
198 }"#,
199         );
200     }
201 
202     #[test]
type_hints_bindings_after_at()203     fn type_hints_bindings_after_at() {
204         check_types(
205             r#"
206 //- minicore: option
207 fn main() {
208     let ref foo @ bar @ ref mut baz = 0;
209           //^^^ &i32
210                 //^^^ i32
211                               //^^^ &mut i32
212     let [x @ ..] = [0];
213        //^ [i32; 1]
214     if let x @ Some(_) = Some(0) {}
215          //^ Option<i32>
216     let foo @ (bar, baz) = (3, 3);
217       //^^^ (i32, i32)
218              //^^^ i32
219                   //^^^ i32
220 }"#,
221         );
222     }
223 
224     #[test]
default_generic_types_should_not_be_displayed()225     fn default_generic_types_should_not_be_displayed() {
226         check(
227             r#"
228 struct Test<K, T = u8> { k: K, t: T }
229 
230 fn main() {
231     let zz = Test { t: 23u8, k: 33 };
232       //^^ Test<i32>
233     let zz_ref = &zz;
234       //^^^^^^ &Test<i32>
235     let test = || zz;
236       //^^^^ impl FnOnce() -> Test<i32>
237 }"#,
238         );
239     }
240 
241     #[test]
shorten_iterators_in_associated_params()242     fn shorten_iterators_in_associated_params() {
243         check_types(
244             r#"
245 //- minicore: iterators
246 use core::iter;
247 
248 pub struct SomeIter<T> {}
249 
250 impl<T> SomeIter<T> {
251     pub fn new() -> Self { SomeIter {} }
252     pub fn push(&mut self, t: T) {}
253 }
254 
255 impl<T> Iterator for SomeIter<T> {
256     type Item = T;
257     fn next(&mut self) -> Option<Self::Item> {
258         None
259     }
260 }
261 
262 fn main() {
263     let mut some_iter = SomeIter::new();
264           //^^^^^^^^^ SomeIter<Take<Repeat<i32>>>
265       some_iter.push(iter::repeat(2).take(2));
266     let iter_of_iters = some_iter.take(2);
267       //^^^^^^^^^^^^^ impl Iterator<Item = impl Iterator<Item = i32>>
268 }
269 "#,
270         );
271     }
272 
273     #[test]
iterator_hint_regression_issue_12674()274     fn iterator_hint_regression_issue_12674() {
275         // Ensure we don't crash while solving the projection type of iterators.
276         let (analysis, file_id) = fixture::file(
277             r#"
278 //- minicore: iterators
279 struct S<T>(T);
280 impl<T> S<T> {
281     fn iter(&self) -> Iter<'_, T> { loop {} }
282 }
283 struct Iter<'a, T: 'a>(&'a T);
284 impl<'a, T> Iterator for Iter<'a, T> {
285     type Item = &'a T;
286     fn next(&mut self) -> Option<Self::Item> { loop {} }
287 }
288 struct Container<'a> {
289     elements: S<&'a str>,
290 }
291 struct SliceIter<'a, T>(&'a T);
292 impl<'a, T> Iterator for SliceIter<'a, T> {
293     type Item = &'a T;
294     fn next(&mut self) -> Option<Self::Item> { loop {} }
295 }
296 
297 fn main(a: SliceIter<'_, Container>) {
298     a
299         .filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
300         .map(|e| e);
301 }
302 "#,
303         );
304         analysis
305             .inlay_hints(
306                 &InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
307                 file_id,
308                 None,
309             )
310             .unwrap();
311     }
312 
313     #[test]
infer_call_method_return_associated_types_with_generic()314     fn infer_call_method_return_associated_types_with_generic() {
315         check_types(
316             r#"
317             pub trait Default {
318                 fn default() -> Self;
319             }
320             pub trait Foo {
321                 type Bar: Default;
322             }
323 
324             pub fn quux<T: Foo>() -> T::Bar {
325                 let y = Default::default();
326                   //^ <T as Foo>::Bar
327 
328                 y
329             }
330             "#,
331         );
332     }
333 
334     #[test]
fn_hints()335     fn fn_hints() {
336         check_types(
337             r#"
338 //- minicore: fn, sized
339 fn foo() -> impl Fn() { loop {} }
340 fn foo1() -> impl Fn(f64) { loop {} }
341 fn foo2() -> impl Fn(f64, f64) { loop {} }
342 fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} }
343 fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} }
344 fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} }
345 fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} }
346 fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} }
347 
348 fn main() {
349     let foo = foo();
350      // ^^^ impl Fn()
351     let foo = foo1();
352      // ^^^ impl Fn(f64)
353     let foo = foo2();
354      // ^^^ impl Fn(f64, f64)
355     let foo = foo3();
356      // ^^^ impl Fn(f64, f64) -> u32
357     let foo = foo4();
358      // ^^^ &dyn Fn(f64, f64) -> u32
359     let foo = foo5();
360      // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32
361     let foo = foo6();
362      // ^^^ impl Fn(f64, f64) -> u32
363     let foo = foo7();
364      // ^^^ *const impl Fn(f64, f64) -> u32
365 }
366 "#,
367         )
368     }
369 
370     #[test]
check_hint_range_limit()371     fn check_hint_range_limit() {
372         let fixture = r#"
373         //- minicore: fn, sized
374         fn foo() -> impl Fn() { loop {} }
375         fn foo1() -> impl Fn(f64) { loop {} }
376         fn foo2() -> impl Fn(f64, f64) { loop {} }
377         fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} }
378         fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} }
379         fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} }
380         fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} }
381         fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} }
382 
383         fn main() {
384             let foo = foo();
385             let foo = foo1();
386             let foo = foo2();
387              // ^^^ impl Fn(f64, f64)
388             let foo = foo3();
389              // ^^^ impl Fn(f64, f64) -> u32
390             let foo = foo4();
391             let foo = foo5();
392             let foo = foo6();
393             let foo = foo7();
394         }
395         "#;
396         let (analysis, file_id) = fixture::file(fixture);
397         let expected = extract_annotations(&analysis.file_text(file_id).unwrap());
398         let inlay_hints = analysis
399             .inlay_hints(
400                 &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
401                 file_id,
402                 Some(TextRange::new(TextSize::from(500), TextSize::from(600))),
403             )
404             .unwrap();
405         let actual =
406             inlay_hints.into_iter().map(|it| (it.range, it.label.to_string())).collect::<Vec<_>>();
407         assert_eq!(expected, actual, "\nExpected:\n{expected:#?}\n\nActual:\n{actual:#?}");
408     }
409 
410     #[test]
fn_hints_ptr_rpit_fn_parentheses()411     fn fn_hints_ptr_rpit_fn_parentheses() {
412         check_types(
413             r#"
414 //- minicore: fn, sized
415 trait Trait {}
416 
417 fn foo1() -> *const impl Fn() { loop {} }
418 fn foo2() -> *const (impl Fn() + Sized) { loop {} }
419 fn foo3() -> *const (impl Fn() + ?Sized) { loop {} }
420 fn foo4() -> *const (impl Sized + Fn()) { loop {} }
421 fn foo5() -> *const (impl ?Sized + Fn()) { loop {} }
422 fn foo6() -> *const (impl Fn() + Trait) { loop {} }
423 fn foo7() -> *const (impl Fn() + Sized + Trait) { loop {} }
424 fn foo8() -> *const (impl Fn() + ?Sized + Trait) { loop {} }
425 fn foo9() -> *const (impl Fn() -> u8 + ?Sized) { loop {} }
426 fn foo10() -> *const (impl Fn() + Sized + ?Sized) { loop {} }
427 
428 fn main() {
429     let foo = foo1();
430     //  ^^^ *const impl Fn()
431     let foo = foo2();
432     //  ^^^ *const impl Fn()
433     let foo = foo3();
434     //  ^^^ *const (impl Fn() + ?Sized)
435     let foo = foo4();
436     //  ^^^ *const impl Fn()
437     let foo = foo5();
438     //  ^^^ *const (impl Fn() + ?Sized)
439     let foo = foo6();
440     //  ^^^ *const (impl Fn() + Trait)
441     let foo = foo7();
442     //  ^^^ *const (impl Fn() + Trait)
443     let foo = foo8();
444     //  ^^^ *const (impl Fn() + Trait + ?Sized)
445     let foo = foo9();
446     //  ^^^ *const (impl Fn() -> u8 + ?Sized)
447     let foo = foo10();
448     //  ^^^ *const impl Fn()
449 }
450 "#,
451         )
452     }
453 
454     #[test]
unit_structs_have_no_type_hints()455     fn unit_structs_have_no_type_hints() {
456         check_types(
457             r#"
458 //- minicore: result
459 struct SyntheticSyntax;
460 
461 fn main() {
462     match Ok(()) {
463         Ok(_) => (),
464         Err(SyntheticSyntax) => (),
465     }
466 }"#,
467         );
468     }
469 
470     #[test]
const_pats_have_no_type_hints()471     fn const_pats_have_no_type_hints() {
472         check_types(
473             r#"
474 const FOO: usize = 0;
475 
476 fn main() {
477     match 0 {
478         FOO => (),
479         _ => ()
480     }
481 }"#,
482         );
483     }
484 
485     #[test]
let_statement()486     fn let_statement() {
487         check_types(
488             r#"
489 #[derive(PartialEq)]
490 enum Option<T> { None, Some(T) }
491 
492 #[derive(PartialEq)]
493 struct Test { a: Option<u32>, b: u8 }
494 
495 fn main() {
496     struct InnerStruct {}
497 
498     let test = 54;
499       //^^^^ i32
500     let test: i32 = 33;
501     let mut test = 33;
502           //^^^^ i32
503     let _ = 22;
504     let test = "test";
505       //^^^^ &str
506     let test = InnerStruct {};
507       //^^^^ InnerStruct
508 
509     let test = unresolved();
510 
511     let test = (42, 'a');
512       //^^^^ (i32, char)
513     let (a,    (b,     (c,)) = (2, (3, (9.2,));
514        //^ i32  ^ i32   ^ f64
515     let &x = &92;
516        //^ i32
517 }"#,
518         );
519     }
520 
521     #[test]
if_expr()522     fn if_expr() {
523         check_types(
524             r#"
525 //- minicore: option
526 struct Test { a: Option<u32>, b: u8 }
527 
528 fn main() {
529 
530 }"#,
531         );
532     }
533 
534     #[test]
while_expr()535     fn while_expr() {
536         check_types(
537             r#"
538 //- minicore: option
539 struct Test { a: Option<u32>, b: u8 }
540 
541 fn main() {
542     let test = Some(Test { a: Some(3), b: 1 });
543       //^^^^ Option<Test>
544     while let Some(Test { a: Some(x),    b: y }) = &test {};
545                                 //^ &u32    ^ &u8
546 }"#,
547         );
548     }
549 
550     #[test]
match_arm_list()551     fn match_arm_list() {
552         check_types(
553             r#"
554 //- minicore: option
555 struct Test { a: Option<u32>, b: u8 }
556 
557 fn main() {
558     match Some(Test { a: Some(3), b: 1 }) {
559         None => (),
560         test => (),
561       //^^^^ Option<Test>
562         Some(Test { a: Some(x), b: y }) => (),
563                           //^ u32  ^ u8
564         _ => {}
565     }
566 }"#,
567         );
568     }
569 
570     #[test]
complete_for_hint()571     fn complete_for_hint() {
572         check_types(
573             r#"
574 //- minicore: iterator
575 pub struct Vec<T> {}
576 
577 impl<T> Vec<T> {
578     pub fn new() -> Self { Vec {} }
579     pub fn push(&mut self, t: T) {}
580 }
581 
582 impl<T> IntoIterator for Vec<T> {
583     type Item = T;
584     type IntoIter = IntoIter<T>;
585 }
586 
587 struct IntoIter<T> {}
588 
589 impl<T> Iterator for IntoIter<T> {
590     type Item = T;
591 }
592 
593 fn main() {
594     let mut data = Vec::new();
595           //^^^^ Vec<&str>
596     data.push("foo");
597     for i in data {
598       //^ &str
599       let z = i;
600         //^ &str
601     }
602 }
603 "#,
604         );
605     }
606 
607     #[test]
multi_dyn_trait_bounds()608     fn multi_dyn_trait_bounds() {
609         check_types(
610             r#"
611 pub struct Vec<T> {}
612 
613 impl<T> Vec<T> {
614     pub fn new() -> Self { Vec {} }
615 }
616 
617 pub struct Box<T> {}
618 
619 trait Display {}
620 auto trait Sync {}
621 
622 fn main() {
623     // The block expression wrapping disables the constructor hint hiding logic
624     let _v = { Vec::<Box<&(dyn Display + Sync)>>::new() };
625       //^^ Vec<Box<&(dyn Display + Sync)>>
626     let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() };
627       //^^ Vec<Box<*const (dyn Display + Sync)>>
628     let _v = { Vec::<Box<dyn Display + Sync>>::new() };
629       //^^ Vec<Box<dyn Display + Sync>>
630 }
631 "#,
632         );
633     }
634 
635     #[test]
shorten_iterator_hints()636     fn shorten_iterator_hints() {
637         check_types(
638             r#"
639 //- minicore: iterators
640 use core::iter;
641 
642 struct MyIter;
643 
644 impl Iterator for MyIter {
645     type Item = ();
646     fn next(&mut self) -> Option<Self::Item> {
647         None
648     }
649 }
650 
651 fn main() {
652     let _x = MyIter;
653       //^^ MyIter
654     let _x = iter::repeat(0);
655       //^^ impl Iterator<Item = i32>
656     fn generic<T: Clone>(t: T) {
657         let _x = iter::repeat(t);
658           //^^ impl Iterator<Item = T>
659         let _chained = iter::repeat(t).take(10);
660           //^^^^^^^^ impl Iterator<Item = T>
661     }
662 }
663 "#,
664         );
665     }
666 
667     #[test]
skip_constructor_and_enum_type_hints()668     fn skip_constructor_and_enum_type_hints() {
669         check_with_config(
670             InlayHintsConfig {
671                 type_hints: true,
672                 hide_named_constructor_hints: true,
673                 ..DISABLED_CONFIG
674             },
675             r#"
676 //- minicore: try, option
677 use core::ops::ControlFlow;
678 
679 mod x {
680     pub mod y { pub struct Foo; }
681     pub struct Foo;
682     pub enum AnotherEnum {
683         Variant()
684     };
685 }
686 struct Struct;
687 struct TupleStruct();
688 
689 impl Struct {
690     fn new() -> Self {
691         Struct
692     }
693     fn try_new() -> ControlFlow<(), Self> {
694         ControlFlow::Continue(Struct)
695     }
696 }
697 
698 struct Generic<T>(T);
699 impl Generic<i32> {
700     fn new() -> Self {
701         Generic(0)
702     }
703 }
704 
705 enum Enum {
706     Variant(u32)
707 }
708 
709 fn times2(value: i32) -> i32 {
710     2 * value
711 }
712 
713 fn main() {
714     let enumb = Enum::Variant(0);
715 
716     let strukt = x::Foo;
717     let strukt = x::y::Foo;
718     let strukt = Struct;
719     let strukt = Struct::new();
720 
721     let tuple_struct = TupleStruct();
722 
723     let generic0 = Generic::new();
724     //  ^^^^^^^^ Generic<i32>
725     let generic1 = Generic(0);
726     //  ^^^^^^^^ Generic<i32>
727     let generic2 = Generic::<i32>::new();
728     let generic3 = <Generic<i32>>::new();
729     let generic4 = Generic::<i32>(0);
730 
731 
732     let option = Some(0);
733     //  ^^^^^^ Option<i32>
734     let func = times2;
735     //  ^^^^ fn times2(i32) -> i32
736     let closure = |x: i32| x * 2;
737     //  ^^^^^^^ impl Fn(i32) -> i32
738 }
739 
740 fn fallible() -> ControlFlow<()> {
741     let strukt = Struct::try_new()?;
742 }
743 "#,
744         );
745     }
746 
747     #[test]
shows_constructor_type_hints_when_enabled()748     fn shows_constructor_type_hints_when_enabled() {
749         check_types(
750             r#"
751 //- minicore: try
752 use core::ops::ControlFlow;
753 
754 struct Struct;
755 struct TupleStruct();
756 
757 impl Struct {
758     fn new() -> Self {
759         Struct
760     }
761     fn try_new() -> ControlFlow<(), Self> {
762         ControlFlow::Continue(Struct)
763     }
764 }
765 
766 struct Generic<T>(T);
767 impl Generic<i32> {
768     fn new() -> Self {
769         Generic(0)
770     }
771 }
772 
773 fn main() {
774     let strukt = Struct::new();
775      // ^^^^^^ Struct
776     let tuple_struct = TupleStruct();
777      // ^^^^^^^^^^^^ TupleStruct
778     let generic0 = Generic::new();
779      // ^^^^^^^^ Generic<i32>
780     let generic1 = Generic::<i32>::new();
781      // ^^^^^^^^ Generic<i32>
782     let generic2 = <Generic<i32>>::new();
783      // ^^^^^^^^ Generic<i32>
784 }
785 
786 fn fallible() -> ControlFlow<()> {
787     let strukt = Struct::try_new()?;
788      // ^^^^^^ Struct
789 }
790 "#,
791         );
792     }
793 
794     #[test]
closure_style()795     fn closure_style() {
796         check_with_config(
797             InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
798             r#"
799 //- minicore: fn
800 fn main() {
801     let x = || 2;
802       //^ impl Fn() -> i32
803     let y = |t: i32| x() + t;
804       //^ impl Fn(i32) -> i32
805     let mut t = 5;
806           //^ i32
807     let z = |k: i32| { t += k; };
808       //^ impl FnMut(i32)
809     let p = (y, z);
810       //^ (impl Fn(i32) -> i32, impl FnMut(i32))
811 }
812             "#,
813         );
814         check_with_config(
815             InlayHintsConfig {
816                 type_hints: true,
817                 closure_style: ClosureStyle::RANotation,
818                 ..DISABLED_CONFIG
819             },
820             r#"
821 //- minicore: fn
822 fn main() {
823     let x = || 2;
824       //^ || -> i32
825     let y = |t: i32| x() + t;
826       //^ |i32| -> i32
827     let mut t = 5;
828           //^ i32
829     let z = |k: i32| { t += k; };
830       //^ |i32| -> ()
831     let p = (y, z);
832       //^ (|i32| -> i32, |i32| -> ())
833 }
834             "#,
835         );
836         check_with_config(
837             InlayHintsConfig {
838                 type_hints: true,
839                 closure_style: ClosureStyle::ClosureWithId,
840                 ..DISABLED_CONFIG
841             },
842             r#"
843 //- minicore: fn
844 fn main() {
845     let x = || 2;
846       //^ {closure#0}
847     let y = |t: i32| x() + t;
848       //^ {closure#1}
849     let mut t = 5;
850           //^ i32
851     let z = |k: i32| { t += k; };
852       //^ {closure#2}
853     let p = (y, z);
854       //^ ({closure#1}, {closure#2})
855 }
856             "#,
857         );
858         check_with_config(
859             InlayHintsConfig {
860                 type_hints: true,
861                 closure_style: ClosureStyle::Hide,
862                 ..DISABLED_CONFIG
863             },
864             r#"
865 //- minicore: fn
866 fn main() {
867     let x = || 2;
868       //^ …
869     let y = |t: i32| x() + t;
870       //^ …
871     let mut t = 5;
872           //^ i32
873     let z = |k: i32| { t += k; };
874       //^ …
875     let p = (y, z);
876       //^ (…, …)
877 }
878             "#,
879         );
880     }
881 
882     #[test]
skip_closure_type_hints()883     fn skip_closure_type_hints() {
884         check_with_config(
885             InlayHintsConfig {
886                 type_hints: true,
887                 hide_closure_initialization_hints: true,
888                 ..DISABLED_CONFIG
889             },
890             r#"
891 //- minicore: fn
892 fn main() {
893     let multiple_2 = |x: i32| { x * 2 };
894 
895     let multiple_2 = |x: i32| x * 2;
896     //  ^^^^^^^^^^ impl Fn(i32) -> i32
897 
898     let (not) = (|x: bool| { !x });
899     //   ^^^ impl Fn(bool) -> bool
900 
901     let (is_zero, _b) = (|x: usize| { x == 0 }, false);
902     //   ^^^^^^^ impl Fn(usize) -> bool
903     //            ^^ bool
904 
905     let plus_one = |x| { x + 1 };
906     //              ^ u8
907     foo(plus_one);
908 
909     let add_mul = bar(|x: u8| { x + 1 });
910     //  ^^^^^^^ impl FnOnce(u8) -> u8 + ?Sized
911 
912     let closure = if let Some(6) = add_mul(2).checked_sub(1) {
913     //  ^^^^^^^ fn(i32) -> i32
914         |x: i32| { x * 2 }
915     } else {
916         |x: i32| { x * 3 }
917     };
918 }
919 
920 fn foo(f: impl FnOnce(u8) -> u8) {}
921 
922 fn bar(f: impl FnOnce(u8) -> u8) -> impl FnOnce(u8) -> u8 {
923     move |x: u8| f(x) * 2
924 }
925 "#,
926         );
927     }
928 
929     #[test]
hint_truncation()930     fn hint_truncation() {
931         check_with_config(
932             InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG },
933             r#"
934 struct Smol<T>(T);
935 
936 struct VeryLongOuterName<T>(T);
937 
938 fn main() {
939     let a = Smol(0u32);
940       //^ Smol<u32>
941     let b = VeryLongOuterName(0usize);
942       //^ VeryLongOuterName<…>
943     let c = Smol(Smol(0u32))
944       //^ Smol<Smol<…>>
945 }"#,
946         );
947     }
948 
949     #[test]
edit_for_let_stmt()950     fn edit_for_let_stmt() {
951         check_edit(
952             TEST_CONFIG,
953             r#"
954 struct S<T>(T);
955 fn test<F>(v: S<(S<i32>, S<()>)>, f: F) {
956     let a = v;
957     let S((b, c)) = v;
958     let a @ S((b, c)) = v;
959     let a = f;
960 }
961 "#,
962             expect![[r#"
963                 struct S<T>(T);
964                 fn test<F>(v: S<(S<i32>, S<()>)>, f: F) {
965                     let a: S<(S<i32>, S<()>)> = v;
966                     let S((b, c)) = v;
967                     let a @ S((b, c)): S<(S<i32>, S<()>)> = v;
968                     let a: F = f;
969                 }
970             "#]],
971         );
972     }
973 
974     #[test]
edit_for_closure_param()975     fn edit_for_closure_param() {
976         check_edit(
977             TEST_CONFIG,
978             r#"
979 fn test<T>(t: T) {
980     let f = |a, b, c| {};
981     let result = f(42, "", t);
982 }
983 "#,
984             expect![[r#"
985                 fn test<T>(t: T) {
986                     let f = |a: i32, b: &str, c: T| {};
987                     let result: () = f(42, "", t);
988                 }
989             "#]],
990         );
991     }
992 
993     #[test]
edit_for_closure_ret()994     fn edit_for_closure_ret() {
995         check_edit(
996             TEST_CONFIG,
997             r#"
998 struct S<T>(T);
999 fn test() {
1000     let f = || { 3 };
1001     let f = |a: S<usize>| { S(a) };
1002 }
1003 "#,
1004             expect![[r#"
1005                 struct S<T>(T);
1006                 fn test() {
1007                     let f = || -> i32 { 3 };
1008                     let f = |a: S<usize>| -> S<S<usize>> { S(a) };
1009                 }
1010             "#]],
1011         );
1012     }
1013 
1014     #[test]
edit_prefixes_paths()1015     fn edit_prefixes_paths() {
1016         check_edit(
1017             TEST_CONFIG,
1018             r#"
1019 pub struct S<T>(T);
1020 mod middle {
1021     pub struct S<T, U>(T, U);
1022     pub fn make() -> S<inner::S<i64>, super::S<usize>> { loop {} }
1023 
1024     mod inner {
1025         pub struct S<T>(T);
1026     }
1027 
1028     fn test() {
1029         let a = make();
1030     }
1031 }
1032 "#,
1033             expect![[r#"
1034                 pub struct S<T>(T);
1035                 mod middle {
1036                     pub struct S<T, U>(T, U);
1037                     pub fn make() -> S<inner::S<i64>, super::S<usize>> { loop {} }
1038 
1039                     mod inner {
1040                         pub struct S<T>(T);
1041                     }
1042 
1043                     fn test() {
1044                         let a: S<inner::S<i64>, crate::S<usize>> = make();
1045                     }
1046                 }
1047             "#]],
1048         );
1049     }
1050 
1051     #[test]
no_edit_for_top_pat_where_type_annotation_is_invalid()1052     fn no_edit_for_top_pat_where_type_annotation_is_invalid() {
1053         check_no_edit(
1054             TEST_CONFIG,
1055             r#"
1056 fn test() {
1057     if let a = 42 {}
1058     while let a = 42 {}
1059     match 42 {
1060         a => (),
1061     }
1062 }
1063 "#,
1064         )
1065     }
1066 
1067     #[test]
no_edit_for_opaque_type()1068     fn no_edit_for_opaque_type() {
1069         check_no_edit(
1070             TEST_CONFIG,
1071             r#"
1072 trait Trait {}
1073 struct S<T>(T);
1074 fn foo() -> impl Trait {}
1075 fn bar() -> S<impl Trait> {}
1076 fn test() {
1077     let a = foo();
1078     let a = bar();
1079     let f = || { foo() };
1080     let f = || { bar() };
1081 }
1082 "#,
1083         );
1084     }
1085 
1086     #[test]
no_edit_for_closure_return_without_body_block()1087     fn no_edit_for_closure_return_without_body_block() {
1088         // We can lift this limitation; see FIXME in closure_ret module.
1089         let config = InlayHintsConfig {
1090             closure_return_type_hints: ClosureReturnTypeHints::Always,
1091             ..TEST_CONFIG
1092         };
1093         check_no_edit(
1094             config,
1095             r#"
1096 struct S<T>(T);
1097 fn test() {
1098     let f = || 3;
1099     let f = |a: S<usize>| S(a);
1100 }
1101 "#,
1102         );
1103     }
1104 }
1105