diff options
Diffstat (limited to 'crates/ide/src')
-rw-r--r-- | crates/ide/src/inlay_hints.rs | 1015 |
1 files changed, 493 insertions, 522 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index d6dfa0183..9f2f6c80a 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -299,9 +299,8 @@ fn should_not_display_type_hint( | |||
299 | // Type of expr should be iterable. | 299 | // Type of expr should be iterable. |
300 | return it.in_token().is_none() || | 300 | return it.in_token().is_none() || |
301 | it.iterable() | 301 | it.iterable() |
302 | .and_then(|iterable_expr|sema.type_of_expr(&iterable_expr)) | 302 | .and_then(|iterable_expr| sema.type_of_expr(&iterable_expr)) |
303 | .map(|iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit()) | 303 | .map_or(true, |iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit()) |
304 | .unwrap_or(true) | ||
305 | }, | 304 | }, |
306 | _ => (), | 305 | _ => (), |
307 | } | 306 | } |
@@ -319,8 +318,8 @@ fn should_hide_param_name_hint( | |||
319 | // hide when: | 318 | // hide when: |
320 | // - the parameter name is a suffix of the function's name | 319 | // - the parameter name is a suffix of the function's name |
321 | // - the argument is an enum whose name is equal to the parameter | 320 | // - the argument is an enum whose name is equal to the parameter |
322 | // - exact argument<->parameter match(ignoring leading underscore) or argument is a prefix/suffix | 321 | // - exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix |
323 | // of parameter with _ splitting it off | 322 | // of argument with _ splitting it off |
324 | // - param starts with `ra_fixture` | 323 | // - param starts with `ra_fixture` |
325 | // - param is a well known name in an unary function | 324 | // - param is a well known name in an unary function |
326 | 325 | ||
@@ -342,23 +341,22 @@ fn should_hide_param_name_hint( | |||
342 | } | 341 | } |
343 | 342 | ||
344 | fn is_argument_similar_to_param_name(argument: &ast::Expr, param_name: &str) -> bool { | 343 | fn is_argument_similar_to_param_name(argument: &ast::Expr, param_name: &str) -> bool { |
345 | match get_string_representation(argument) { | 344 | // check whether param_name and argument are the same or |
346 | None => false, | 345 | // whether param_name is a prefix/suffix of argument(split at `_`) |
347 | Some(argument) => { | 346 | let argument = match get_string_representation(argument) { |
348 | let mut res = false; | 347 | Some(argument) => argument, |
349 | if let Some(first) = argument.bytes().skip_while(|&c| c == b'_').position(|c| c == b'_') | 348 | None => return false, |
350 | { | 349 | }; |
351 | res |= param_name == argument[..first].trim_start_matches('_'); | 350 | |
352 | } | 351 | let param_name = param_name.trim_start_matches('_'); |
353 | if let Some(last) = | 352 | let argument = argument.trim_start_matches('_'); |
354 | argument.bytes().rev().skip_while(|&c| c == b'_').position(|c| c == b'_') | 353 | if argument.strip_prefix(param_name).map_or(false, |s| s.starts_with('_')) { |
355 | { | 354 | return true; |
356 | res |= param_name == argument[last..].trim_end_matches('_'); | ||
357 | } | ||
358 | res |= argument == param_name; | ||
359 | res | ||
360 | } | ||
361 | } | 355 | } |
356 | if argument.strip_suffix(param_name).map_or(false, |s| s.ends_with('_')) { | ||
357 | return true; | ||
358 | } | ||
359 | argument == param_name | ||
362 | } | 360 | } |
363 | 361 | ||
364 | /// Hide the parameter name of an unary function if it is a `_` - prefixed suffix of the function's name, or equal. | 362 | /// Hide the parameter name of an unary function if it is a `_` - prefixed suffix of the function's name, or equal. |
@@ -451,6 +449,42 @@ mod tests { | |||
451 | check_with_config(TEST_CONFIG, ra_fixture); | 449 | check_with_config(TEST_CONFIG, ra_fixture); |
452 | } | 450 | } |
453 | 451 | ||
452 | fn check_params(ra_fixture: &str) { | ||
453 | check_with_config( | ||
454 | InlayHintsConfig { | ||
455 | parameter_hints: true, | ||
456 | type_hints: false, | ||
457 | chaining_hints: false, | ||
458 | max_length: None, | ||
459 | }, | ||
460 | ra_fixture, | ||
461 | ); | ||
462 | } | ||
463 | |||
464 | fn check_types(ra_fixture: &str) { | ||
465 | check_with_config( | ||
466 | InlayHintsConfig { | ||
467 | parameter_hints: false, | ||
468 | type_hints: true, | ||
469 | chaining_hints: false, | ||
470 | max_length: None, | ||
471 | }, | ||
472 | ra_fixture, | ||
473 | ); | ||
474 | } | ||
475 | |||
476 | fn check_chains(ra_fixture: &str) { | ||
477 | check_with_config( | ||
478 | InlayHintsConfig { | ||
479 | parameter_hints: false, | ||
480 | type_hints: false, | ||
481 | chaining_hints: true, | ||
482 | max_length: None, | ||
483 | }, | ||
484 | ra_fixture, | ||
485 | ); | ||
486 | } | ||
487 | |||
454 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { | 488 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { |
455 | let ra_fixture = | 489 | let ra_fixture = |
456 | format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); | 490 | format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); |
@@ -471,17 +505,28 @@ mod tests { | |||
471 | } | 505 | } |
472 | 506 | ||
473 | #[test] | 507 | #[test] |
474 | fn param_hints_only() { | 508 | fn hints_disabled() { |
475 | check_with_config( | 509 | check_with_config( |
476 | InlayHintsConfig { | 510 | InlayHintsConfig { |
477 | parameter_hints: true, | ||
478 | type_hints: false, | 511 | type_hints: false, |
512 | parameter_hints: false, | ||
479 | chaining_hints: false, | 513 | chaining_hints: false, |
480 | max_length: None, | 514 | max_length: None, |
481 | }, | 515 | }, |
482 | r#" | 516 | r#" |
483 | fn foo(a: i32, b: i32) -> i32 { a + b } | 517 | fn foo(a: i32, b: i32) -> i32 { a + b } |
484 | fn main() { | 518 | fn main() { |
519 | let _x = foo(4, 4); | ||
520 | }"#, | ||
521 | ); | ||
522 | } | ||
523 | |||
524 | #[test] | ||
525 | fn param_hints_only() { | ||
526 | check_params( | ||
527 | r#" | ||
528 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
529 | fn main() { | ||
485 | let _x = foo( | 530 | let _x = foo( |
486 | 4, | 531 | 4, |
487 | //^ a | 532 | //^ a |
@@ -494,13 +539,7 @@ fn main() { | |||
494 | 539 | ||
495 | #[test] | 540 | #[test] |
496 | fn param_name_similar_to_fn_name_still_hints() { | 541 | fn param_name_similar_to_fn_name_still_hints() { |
497 | check_with_config( | 542 | check_params( |
498 | InlayHintsConfig { | ||
499 | parameter_hints: true, | ||
500 | type_hints: false, | ||
501 | chaining_hints: false, | ||
502 | max_length: None, | ||
503 | }, | ||
504 | r#" | 543 | r#" |
505 | fn max(x: i32, y: i32) -> i32 { x + y } | 544 | fn max(x: i32, y: i32) -> i32 { x + y } |
506 | fn main() { | 545 | fn main() { |
@@ -516,13 +555,7 @@ fn main() { | |||
516 | 555 | ||
517 | #[test] | 556 | #[test] |
518 | fn param_name_similar_to_fn_name() { | 557 | fn param_name_similar_to_fn_name() { |
519 | check_with_config( | 558 | check_params( |
520 | InlayHintsConfig { | ||
521 | parameter_hints: true, | ||
522 | type_hints: false, | ||
523 | chaining_hints: false, | ||
524 | max_length: None, | ||
525 | }, | ||
526 | r#" | 559 | r#" |
527 | fn param_with_underscore(with_underscore: i32) -> i32 { with_underscore } | 560 | fn param_with_underscore(with_underscore: i32) -> i32 { with_underscore } |
528 | fn main() { | 561 | fn main() { |
@@ -535,13 +568,7 @@ fn main() { | |||
535 | 568 | ||
536 | #[test] | 569 | #[test] |
537 | fn param_name_same_as_fn_name() { | 570 | fn param_name_same_as_fn_name() { |
538 | check_with_config( | 571 | check_params( |
539 | InlayHintsConfig { | ||
540 | parameter_hints: true, | ||
541 | type_hints: false, | ||
542 | chaining_hints: false, | ||
543 | max_length: None, | ||
544 | }, | ||
545 | r#" | 572 | r#" |
546 | fn foo(foo: i32) -> i32 { foo } | 573 | fn foo(foo: i32) -> i32 { foo } |
547 | fn main() { | 574 | fn main() { |
@@ -554,13 +581,7 @@ fn main() { | |||
554 | 581 | ||
555 | #[test] | 582 | #[test] |
556 | fn never_hide_param_when_multiple_params() { | 583 | fn never_hide_param_when_multiple_params() { |
557 | check_with_config( | 584 | check_params( |
558 | InlayHintsConfig { | ||
559 | parameter_hints: true, | ||
560 | type_hints: false, | ||
561 | chaining_hints: false, | ||
562 | max_length: None, | ||
563 | }, | ||
564 | r#" | 585 | r#" |
565 | fn foo(bar: i32, baz: i32) -> i32 { bar + baz } | 586 | fn foo(bar: i32, baz: i32) -> i32 { bar + baz } |
566 | fn main() { | 587 | fn main() { |
@@ -575,209 +596,56 @@ fn main() { | |||
575 | } | 596 | } |
576 | 597 | ||
577 | #[test] | 598 | #[test] |
578 | fn hints_disabled() { | 599 | fn hide_param_hints_for_clones() { |
579 | check_with_config( | 600 | check_params( |
580 | InlayHintsConfig { | ||
581 | type_hints: false, | ||
582 | parameter_hints: false, | ||
583 | chaining_hints: false, | ||
584 | max_length: None, | ||
585 | }, | ||
586 | r#" | ||
587 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
588 | fn main() { | ||
589 | let _x = foo(4, 4); | ||
590 | }"#, | ||
591 | ); | ||
592 | } | ||
593 | |||
594 | #[test] | ||
595 | fn type_hints_only() { | ||
596 | check_with_config( | ||
597 | InlayHintsConfig { | ||
598 | type_hints: true, | ||
599 | parameter_hints: false, | ||
600 | chaining_hints: false, | ||
601 | max_length: None, | ||
602 | }, | ||
603 | r#" | ||
604 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
605 | fn main() { | ||
606 | let _x = foo(4, 4); | ||
607 | //^^ i32 | ||
608 | }"#, | ||
609 | ); | ||
610 | } | ||
611 | |||
612 | #[test] | ||
613 | fn default_generic_types_should_not_be_displayed() { | ||
614 | check( | ||
615 | r#" | ||
616 | struct Test<K, T = u8> { k: K, t: T } | ||
617 | |||
618 | fn main() { | ||
619 | let zz = Test { t: 23u8, k: 33 }; | ||
620 | //^^ Test<i32> | ||
621 | let zz_ref = &zz; | ||
622 | //^^^^^^ &Test<i32> | ||
623 | let test = || zz; | ||
624 | //^^^^ || -> Test<i32> | ||
625 | }"#, | ||
626 | ); | ||
627 | } | ||
628 | |||
629 | #[test] | ||
630 | fn let_statement() { | ||
631 | check( | ||
632 | r#" | ||
633 | #[derive(PartialEq)] | ||
634 | enum Option<T> { None, Some(T) } | ||
635 | |||
636 | #[derive(PartialEq)] | ||
637 | struct Test { a: Option<u32>, b: u8 } | ||
638 | |||
639 | fn main() { | ||
640 | struct InnerStruct {} | ||
641 | |||
642 | let test = 54; | ||
643 | //^^^^ i32 | ||
644 | let test: i32 = 33; | ||
645 | let mut test = 33; | ||
646 | //^^^^^^^^ i32 | ||
647 | let _ = 22; | ||
648 | let test = "test"; | ||
649 | //^^^^ &str | ||
650 | let test = InnerStruct {}; | ||
651 | //^^^^ InnerStruct | ||
652 | |||
653 | let test = unresolved(); | ||
654 | |||
655 | let test = (42, 'a'); | ||
656 | //^^^^ (i32, char) | ||
657 | let (a, (b, (c,)) = (2, (3, (9.2,)); | ||
658 | //^ i32 ^ i32 ^ f64 | ||
659 | let &x = &92; | ||
660 | //^ i32 | ||
661 | }"#, | ||
662 | ); | ||
663 | } | ||
664 | |||
665 | #[test] | ||
666 | fn closure_parameters() { | ||
667 | check( | ||
668 | r#" | ||
669 | fn main() { | ||
670 | let mut start = 0; | ||
671 | //^^^^^^^^^ i32 | ||
672 | (0..2).for_each(|increment| { start += increment; }); | ||
673 | //^^^^^^^^^ i32 | ||
674 | |||
675 | let multiply = | ||
676 | //^^^^^^^^ |…| -> i32 | ||
677 | | a, b| a * b | ||
678 | //^ i32 ^ i32 | ||
679 | ; | ||
680 | |||
681 | let _: i32 = multiply(1, 2); | ||
682 | let multiply_ref = &multiply; | ||
683 | //^^^^^^^^^^^^ &|…| -> i32 | ||
684 | |||
685 | let return_42 = || 42; | ||
686 | //^^^^^^^^^ || -> i32 | ||
687 | }"#, | ||
688 | ); | ||
689 | } | ||
690 | |||
691 | #[test] | ||
692 | fn if_expr() { | ||
693 | check( | ||
694 | r#" | ||
695 | enum Option<T> { None, Some(T) } | ||
696 | use Option::*; | ||
697 | |||
698 | struct Test { a: Option<u32>, b: u8 } | ||
699 | |||
700 | fn main() { | ||
701 | let test = Some(Test { a: Some(3), b: 1 }); | ||
702 | //^^^^ Option<Test> | ||
703 | if let None = &test {}; | ||
704 | if let test = &test {}; | ||
705 | //^^^^ &Option<Test> | ||
706 | if let Some(test) = &test {}; | ||
707 | //^^^^ &Test | ||
708 | if let Some(Test { a, b }) = &test {}; | ||
709 | //^ &Option<u32> ^ &u8 | ||
710 | if let Some(Test { a: x, b: y }) = &test {}; | ||
711 | //^ &Option<u32> ^ &u8 | ||
712 | if let Some(Test { a: Some(x), b: y }) = &test {}; | ||
713 | //^ &u32 ^ &u8 | ||
714 | if let Some(Test { a: None, b: y }) = &test {}; | ||
715 | //^ &u8 | ||
716 | if let Some(Test { b: y, .. }) = &test {}; | ||
717 | //^ &u8 | ||
718 | if test == None {} | ||
719 | }"#, | ||
720 | ); | ||
721 | } | ||
722 | |||
723 | #[test] | ||
724 | fn while_expr() { | ||
725 | check( | ||
726 | r#" | 601 | r#" |
727 | enum Option<T> { None, Some(T) } | 602 | fn foo(bar: i32, baz: String, qux: f32) {} |
728 | use Option::*; | ||
729 | |||
730 | struct Test { a: Option<u32>, b: u8 } | ||
731 | 603 | ||
732 | fn main() { | 604 | fn main() { |
733 | let test = Some(Test { a: Some(3), b: 1 }); | 605 | let bar = 3; |
734 | //^^^^ Option<Test> | 606 | let baz = &"baz"; |
735 | while let Some(Test { a: Some(x), b: y }) = &test {}; | 607 | let fez = 1.0; |
736 | //^ &u32 ^ &u8 | 608 | foo(bar.clone(), baz.clone(), fez.clone()); |
737 | }"#, | 609 | //^^^^^^^^^^^ qux |
610 | } | ||
611 | "#, | ||
738 | ); | 612 | ); |
739 | } | 613 | } |
740 | 614 | ||
741 | #[test] | 615 | #[test] |
742 | fn match_arm_list() { | 616 | fn self_param_hints() { |
743 | check( | 617 | check_params( |
744 | r#" | 618 | r#" |
745 | enum Option<T> { None, Some(T) } | 619 | struct Foo; |
746 | use Option::*; | ||
747 | 620 | ||
748 | struct Test { a: Option<u32>, b: u8 } | 621 | impl Foo { |
622 | fn foo(self: Self) {} | ||
623 | fn bar(self: &Self) {} | ||
624 | } | ||
749 | 625 | ||
750 | fn main() { | 626 | fn main() { |
751 | match Some(Test { a: Some(3), b: 1 }) { | 627 | Foo::foo(Foo); |
752 | None => (), | 628 | //^^^ self |
753 | test => (), | 629 | Foo::bar(&Foo); |
754 | //^^^^ Option<Test> | 630 | //^^^^ self |
755 | Some(Test { a: Some(x), b: y }) => (), | 631 | } |
756 | //^ u32 ^ u8 | 632 | "#, |
757 | _ => {} | 633 | ) |
758 | } | ||
759 | }"#, | ||
760 | ); | ||
761 | } | 634 | } |
762 | 635 | ||
763 | #[test] | 636 | #[test] |
764 | fn hint_truncation() { | 637 | fn param_name_hints_show_for_literals() { |
765 | check_with_config( | 638 | check_params( |
766 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, | 639 | r#"pub fn test(a: i32, b: i32) -> [i32; 2] { [a, b] } |
767 | r#" | ||
768 | struct Smol<T>(T); | ||
769 | |||
770 | struct VeryLongOuterName<T>(T); | ||
771 | |||
772 | fn main() { | 640 | fn main() { |
773 | let a = Smol(0u32); | 641 | test( |
774 | //^ Smol<u32> | 642 | 0x0fab272b, |
775 | let b = VeryLongOuterName(0usize); | 643 | //^^^^^^^^^^ a |
776 | //^ VeryLongOuterName<…> | 644 | 0x0fab272b |
777 | let c = Smol(Smol(0u32)) | 645 | //^^^^^^^^^^ b |
778 | //^ Smol<Smol<…>> | 646 | ); |
779 | }"#, | 647 | }"#, |
780 | ); | 648 | ) |
781 | } | 649 | } |
782 | 650 | ||
783 | #[test] | 651 | #[test] |
@@ -939,10 +807,129 @@ fn main() { | |||
939 | ); | 807 | ); |
940 | } | 808 | } |
941 | 809 | ||
810 | // Type-Hint tests | ||
811 | |||
812 | #[test] | ||
813 | fn type_hints_only() { | ||
814 | check_types( | ||
815 | r#" | ||
816 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
817 | fn main() { | ||
818 | let _x = foo(4, 4); | ||
819 | //^^ i32 | ||
820 | }"#, | ||
821 | ); | ||
822 | } | ||
823 | |||
824 | #[test] | ||
825 | fn default_generic_types_should_not_be_displayed() { | ||
826 | check( | ||
827 | r#" | ||
828 | struct Test<K, T = u8> { k: K, t: T } | ||
829 | |||
830 | fn main() { | ||
831 | let zz = Test { t: 23u8, k: 33 }; | ||
832 | //^^ Test<i32> | ||
833 | let zz_ref = &zz; | ||
834 | //^^^^^^ &Test<i32> | ||
835 | let test = || zz; | ||
836 | //^^^^ || -> Test<i32> | ||
837 | }"#, | ||
838 | ); | ||
839 | } | ||
840 | |||
841 | #[test] | ||
842 | fn shorten_iterators_in_associated_params() { | ||
843 | check_types( | ||
844 | r#" | ||
845 | use core::iter; | ||
846 | |||
847 | pub struct SomeIter<T> {} | ||
848 | |||
849 | impl<T> SomeIter<T> { | ||
850 | pub fn new() -> Self { SomeIter {} } | ||
851 | pub fn push(&mut self, t: T) {} | ||
852 | } | ||
853 | |||
854 | impl<T> Iterator for SomeIter<T> { | ||
855 | type Item = T; | ||
856 | fn next(&mut self) -> Option<Self::Item> { | ||
857 | None | ||
858 | } | ||
859 | } | ||
860 | |||
861 | fn main() { | ||
862 | let mut some_iter = SomeIter::new(); | ||
863 | //^^^^^^^^^^^^^ SomeIter<Take<Repeat<i32>>> | ||
864 | some_iter.push(iter::repeat(2).take(2)); | ||
865 | let iter_of_iters = some_iter.take(2); | ||
866 | //^^^^^^^^^^^^^ impl Iterator<Item = impl Iterator<Item = i32>> | ||
867 | } | ||
868 | "#, | ||
869 | ); | ||
870 | } | ||
871 | |||
872 | #[test] | ||
873 | fn infer_call_method_return_associated_types_with_generic() { | ||
874 | check_types( | ||
875 | r#" | ||
876 | pub trait Default { | ||
877 | fn default() -> Self; | ||
878 | } | ||
879 | pub trait Foo { | ||
880 | type Bar: Default; | ||
881 | } | ||
882 | |||
883 | pub fn quux<T: Foo>() -> T::Bar { | ||
884 | let y = Default::default(); | ||
885 | //^ <T as Foo>::Bar | ||
886 | |||
887 | y | ||
888 | } | ||
889 | "#, | ||
890 | ); | ||
891 | } | ||
892 | |||
893 | #[test] | ||
894 | fn fn_hints() { | ||
895 | check_types( | ||
896 | r#" | ||
897 | trait Sized {} | ||
898 | |||
899 | fn foo() -> impl Fn() { loop {} } | ||
900 | fn foo1() -> impl Fn(f64) { loop {} } | ||
901 | fn foo2() -> impl Fn(f64, f64) { loop {} } | ||
902 | fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} } | ||
903 | fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} } | ||
904 | fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} } | ||
905 | fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} } | ||
906 | fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} } | ||
907 | |||
908 | fn main() { | ||
909 | let foo = foo(); | ||
910 | // ^^^ impl Fn() | ||
911 | let foo = foo1(); | ||
912 | // ^^^ impl Fn(f64) | ||
913 | let foo = foo2(); | ||
914 | // ^^^ impl Fn(f64, f64) | ||
915 | let foo = foo3(); | ||
916 | // ^^^ impl Fn(f64, f64) -> u32 | ||
917 | let foo = foo4(); | ||
918 | // ^^^ &dyn Fn(f64, f64) -> u32 | ||
919 | let foo = foo5(); | ||
920 | // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32 | ||
921 | let foo = foo6(); | ||
922 | // ^^^ impl Fn(f64, f64) -> u32 + Sized | ||
923 | let foo = foo7(); | ||
924 | // ^^^ *const (impl Fn(f64, f64) -> u32 + Sized) | ||
925 | } | ||
926 | "#, | ||
927 | ) | ||
928 | } | ||
929 | |||
942 | #[test] | 930 | #[test] |
943 | fn unit_structs_have_no_type_hints() { | 931 | fn unit_structs_have_no_type_hints() { |
944 | check_with_config( | 932 | check_types( |
945 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, | ||
946 | r#" | 933 | r#" |
947 | enum Result<T, E> { Ok(T), Err(E) } | 934 | enum Result<T, E> { Ok(T), Err(E) } |
948 | use Result::*; | 935 | use Result::*; |
@@ -959,159 +946,116 @@ fn main() { | |||
959 | } | 946 | } |
960 | 947 | ||
961 | #[test] | 948 | #[test] |
962 | fn chaining_hints_ignore_comments() { | 949 | fn let_statement() { |
963 | check_expect( | 950 | check_types( |
964 | InlayHintsConfig { | ||
965 | parameter_hints: false, | ||
966 | type_hints: false, | ||
967 | chaining_hints: true, | ||
968 | max_length: None, | ||
969 | }, | ||
970 | r#" | 951 | r#" |
971 | struct A(B); | 952 | #[derive(PartialEq)] |
972 | impl A { fn into_b(self) -> B { self.0 } } | 953 | enum Option<T> { None, Some(T) } |
973 | struct B(C); | 954 | |
974 | impl B { fn into_c(self) -> C { self.0 } } | 955 | #[derive(PartialEq)] |
975 | struct C; | 956 | struct Test { a: Option<u32>, b: u8 } |
976 | 957 | ||
977 | fn main() { | 958 | fn main() { |
978 | let c = A(B(C)) | 959 | struct InnerStruct {} |
979 | .into_b() // This is a comment | 960 | |
980 | // This is another comment | 961 | let test = 54; |
981 | .into_c(); | 962 | //^^^^ i32 |
982 | } | 963 | let test: i32 = 33; |
983 | "#, | 964 | let mut test = 33; |
984 | expect![[r#" | 965 | //^^^^^^^^ i32 |
985 | [ | 966 | let _ = 22; |
986 | InlayHint { | 967 | let test = "test"; |
987 | range: 148..173, | 968 | //^^^^ &str |
988 | kind: ChainingHint, | 969 | let test = InnerStruct {}; |
989 | label: "B", | 970 | //^^^^ InnerStruct |
990 | }, | 971 | |
991 | InlayHint { | 972 | let test = unresolved(); |
992 | range: 148..155, | 973 | |
993 | kind: ChainingHint, | 974 | let test = (42, 'a'); |
994 | label: "A", | 975 | //^^^^ (i32, char) |
995 | }, | 976 | let (a, (b, (c,)) = (2, (3, (9.2,)); |
996 | ] | 977 | //^ i32 ^ i32 ^ f64 |
997 | "#]], | 978 | let &x = &92; |
979 | //^ i32 | ||
980 | }"#, | ||
998 | ); | 981 | ); |
999 | } | 982 | } |
1000 | 983 | ||
1001 | #[test] | 984 | #[test] |
1002 | fn chaining_hints_without_newlines() { | 985 | fn if_expr() { |
1003 | check_with_config( | 986 | check_types( |
1004 | InlayHintsConfig { | ||
1005 | parameter_hints: false, | ||
1006 | type_hints: false, | ||
1007 | chaining_hints: true, | ||
1008 | max_length: None, | ||
1009 | }, | ||
1010 | r#" | 987 | r#" |
1011 | struct A(B); | 988 | enum Option<T> { None, Some(T) } |
1012 | impl A { fn into_b(self) -> B { self.0 } } | 989 | use Option::*; |
1013 | struct B(C); | 990 | |
1014 | impl B { fn into_c(self) -> C { self.0 } } | 991 | struct Test { a: Option<u32>, b: u8 } |
1015 | struct C; | ||
1016 | 992 | ||
1017 | fn main() { | 993 | fn main() { |
1018 | let c = A(B(C)).into_b().into_c(); | 994 | let test = Some(Test { a: Some(3), b: 1 }); |
995 | //^^^^ Option<Test> | ||
996 | if let None = &test {}; | ||
997 | if let test = &test {}; | ||
998 | //^^^^ &Option<Test> | ||
999 | if let Some(test) = &test {}; | ||
1000 | //^^^^ &Test | ||
1001 | if let Some(Test { a, b }) = &test {}; | ||
1002 | //^ &Option<u32> ^ &u8 | ||
1003 | if let Some(Test { a: x, b: y }) = &test {}; | ||
1004 | //^ &Option<u32> ^ &u8 | ||
1005 | if let Some(Test { a: Some(x), b: y }) = &test {}; | ||
1006 | //^ &u32 ^ &u8 | ||
1007 | if let Some(Test { a: None, b: y }) = &test {}; | ||
1008 | //^ &u8 | ||
1009 | if let Some(Test { b: y, .. }) = &test {}; | ||
1010 | //^ &u8 | ||
1011 | if test == None {} | ||
1019 | }"#, | 1012 | }"#, |
1020 | ); | 1013 | ); |
1021 | } | 1014 | } |
1022 | 1015 | ||
1023 | #[test] | 1016 | #[test] |
1024 | fn struct_access_chaining_hints() { | 1017 | fn while_expr() { |
1025 | check_expect( | 1018 | check_types( |
1026 | InlayHintsConfig { | ||
1027 | parameter_hints: false, | ||
1028 | type_hints: false, | ||
1029 | chaining_hints: true, | ||
1030 | max_length: None, | ||
1031 | }, | ||
1032 | r#" | 1019 | r#" |
1033 | struct A { pub b: B } | 1020 | enum Option<T> { None, Some(T) } |
1034 | struct B { pub c: C } | 1021 | use Option::*; |
1035 | struct C(pub bool); | ||
1036 | struct D; | ||
1037 | 1022 | ||
1038 | impl D { | 1023 | struct Test { a: Option<u32>, b: u8 } |
1039 | fn foo(&self) -> i32 { 42 } | ||
1040 | } | ||
1041 | 1024 | ||
1042 | fn main() { | 1025 | fn main() { |
1043 | let x = A { b: B { c: C(true) } } | 1026 | let test = Some(Test { a: Some(3), b: 1 }); |
1044 | .b | 1027 | //^^^^ Option<Test> |
1045 | .c | 1028 | while let Some(Test { a: Some(x), b: y }) = &test {}; |
1046 | .0; | 1029 | //^ &u32 ^ &u8 |
1047 | let x = D | ||
1048 | .foo(); | ||
1049 | }"#, | 1030 | }"#, |
1050 | expect![[r#" | ||
1051 | [ | ||
1052 | InlayHint { | ||
1053 | range: 144..191, | ||
1054 | kind: ChainingHint, | ||
1055 | label: "C", | ||
1056 | }, | ||
1057 | InlayHint { | ||
1058 | range: 144..180, | ||
1059 | kind: ChainingHint, | ||
1060 | label: "B", | ||
1061 | }, | ||
1062 | ] | ||
1063 | "#]], | ||
1064 | ); | 1031 | ); |
1065 | } | 1032 | } |
1066 | 1033 | ||
1067 | #[test] | 1034 | #[test] |
1068 | fn generic_chaining_hints() { | 1035 | fn match_arm_list() { |
1069 | check_expect( | 1036 | check_types( |
1070 | InlayHintsConfig { | ||
1071 | parameter_hints: false, | ||
1072 | type_hints: false, | ||
1073 | chaining_hints: true, | ||
1074 | max_length: None, | ||
1075 | }, | ||
1076 | r#" | 1037 | r#" |
1077 | struct A<T>(T); | 1038 | enum Option<T> { None, Some(T) } |
1078 | struct B<T>(T); | 1039 | use Option::*; |
1079 | struct C<T>(T); | 1040 | |
1080 | struct X<T,R>(T, R); | 1041 | struct Test { a: Option<u32>, b: u8 } |
1081 | 1042 | ||
1082 | impl<T> A<T> { | ||
1083 | fn new(t: T) -> Self { A(t) } | ||
1084 | fn into_b(self) -> B<T> { B(self.0) } | ||
1085 | } | ||
1086 | impl<T> B<T> { | ||
1087 | fn into_c(self) -> C<T> { C(self.0) } | ||
1088 | } | ||
1089 | fn main() { | 1043 | fn main() { |
1090 | let c = A::new(X(42, true)) | 1044 | match Some(Test { a: Some(3), b: 1 }) { |
1091 | .into_b() | 1045 | None => (), |
1092 | .into_c(); | 1046 | test => (), |
1093 | } | 1047 | //^^^^ Option<Test> |
1094 | "#, | 1048 | Some(Test { a: Some(x), b: y }) => (), |
1095 | expect![[r#" | 1049 | //^ u32 ^ u8 |
1096 | [ | 1050 | _ => {} |
1097 | InlayHint { | 1051 | } |
1098 | range: 247..284, | 1052 | }"#, |
1099 | kind: ChainingHint, | ||
1100 | label: "B<X<i32, bool>>", | ||
1101 | }, | ||
1102 | InlayHint { | ||
1103 | range: 247..266, | ||
1104 | kind: ChainingHint, | ||
1105 | label: "A<X<i32, bool>>", | ||
1106 | }, | ||
1107 | ] | ||
1108 | "#]], | ||
1109 | ); | 1053 | ); |
1110 | } | 1054 | } |
1111 | 1055 | ||
1112 | #[test] | 1056 | #[test] |
1113 | fn incomplete_for_no_hint() { | 1057 | fn incomplete_for_no_hint() { |
1114 | check( | 1058 | check_types( |
1115 | r#" | 1059 | r#" |
1116 | fn main() { | 1060 | fn main() { |
1117 | let data = &[1i32, 2, 3]; | 1061 | let data = &[1i32, 2, 3]; |
@@ -1146,7 +1090,7 @@ fn main() { | |||
1146 | 1090 | ||
1147 | #[test] | 1091 | #[test] |
1148 | fn complete_for_hint() { | 1092 | fn complete_for_hint() { |
1149 | check( | 1093 | check_types( |
1150 | r#" | 1094 | r#" |
1151 | pub struct Vec<T> {} | 1095 | pub struct Vec<T> {} |
1152 | 1096 | ||
@@ -1175,13 +1119,7 @@ fn main() { | |||
1175 | 1119 | ||
1176 | #[test] | 1120 | #[test] |
1177 | fn multi_dyn_trait_bounds() { | 1121 | fn multi_dyn_trait_bounds() { |
1178 | check_with_config( | 1122 | check_types( |
1179 | InlayHintsConfig { | ||
1180 | type_hints: true, | ||
1181 | parameter_hints: false, | ||
1182 | chaining_hints: false, | ||
1183 | max_length: None, | ||
1184 | }, | ||
1185 | r#" | 1123 | r#" |
1186 | pub struct Vec<T> {} | 1124 | pub struct Vec<T> {} |
1187 | 1125 | ||
@@ -1208,13 +1146,7 @@ fn main() { | |||
1208 | 1146 | ||
1209 | #[test] | 1147 | #[test] |
1210 | fn shorten_iterator_hints() { | 1148 | fn shorten_iterator_hints() { |
1211 | check_with_config( | 1149 | check_types( |
1212 | InlayHintsConfig { | ||
1213 | parameter_hints: false, | ||
1214 | type_hints: true, | ||
1215 | chaining_hints: false, | ||
1216 | max_length: None, | ||
1217 | }, | ||
1218 | r#" | 1150 | r#" |
1219 | use core::iter; | 1151 | use core::iter; |
1220 | 1152 | ||
@@ -1244,7 +1176,55 @@ fn main() { | |||
1244 | } | 1176 | } |
1245 | 1177 | ||
1246 | #[test] | 1178 | #[test] |
1247 | fn shorten_iterator_chaining_hints() { | 1179 | fn closures() { |
1180 | check( | ||
1181 | r#" | ||
1182 | fn main() { | ||
1183 | let mut start = 0; | ||
1184 | //^^^^^^^^^ i32 | ||
1185 | (0..2).for_each(|increment| { start += increment; }); | ||
1186 | //^^^^^^^^^ i32 | ||
1187 | |||
1188 | let multiply = | ||
1189 | //^^^^^^^^ |…| -> i32 | ||
1190 | | a, b| a * b | ||
1191 | //^ i32 ^ i32 | ||
1192 | ; | ||
1193 | |||
1194 | let _: i32 = multiply(1, 2); | ||
1195 | let multiply_ref = &multiply; | ||
1196 | //^^^^^^^^^^^^ &|…| -> i32 | ||
1197 | |||
1198 | let return_42 = || 42; | ||
1199 | //^^^^^^^^^ || -> i32 | ||
1200 | }"#, | ||
1201 | ); | ||
1202 | } | ||
1203 | |||
1204 | #[test] | ||
1205 | fn hint_truncation() { | ||
1206 | check_with_config( | ||
1207 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, | ||
1208 | r#" | ||
1209 | struct Smol<T>(T); | ||
1210 | |||
1211 | struct VeryLongOuterName<T>(T); | ||
1212 | |||
1213 | fn main() { | ||
1214 | let a = Smol(0u32); | ||
1215 | //^ Smol<u32> | ||
1216 | let b = VeryLongOuterName(0usize); | ||
1217 | //^ VeryLongOuterName<…> | ||
1218 | let c = Smol(Smol(0u32)) | ||
1219 | //^ Smol<Smol<…>> | ||
1220 | }"#, | ||
1221 | ); | ||
1222 | } | ||
1223 | |||
1224 | // Chaining hint tests | ||
1225 | |||
1226 | #[test] | ||
1227 | fn chaining_hints_ignore_comments() { | ||
1248 | check_expect( | 1228 | check_expect( |
1249 | InlayHintsConfig { | 1229 | InlayHintsConfig { |
1250 | parameter_hints: false, | 1230 | parameter_hints: false, |
@@ -1253,46 +1233,30 @@ fn main() { | |||
1253 | max_length: None, | 1233 | max_length: None, |
1254 | }, | 1234 | }, |
1255 | r#" | 1235 | r#" |
1256 | use core::iter; | 1236 | struct A(B); |
1257 | 1237 | impl A { fn into_b(self) -> B { self.0 } } | |
1258 | struct MyIter; | 1238 | struct B(C); |
1259 | 1239 | impl B { fn into_c(self) -> C { self.0 } } | |
1260 | impl Iterator for MyIter { | 1240 | struct C; |
1261 | type Item = (); | ||
1262 | fn next(&mut self) -> Option<Self::Item> { | ||
1263 | None | ||
1264 | } | ||
1265 | } | ||
1266 | 1241 | ||
1267 | fn main() { | 1242 | fn main() { |
1268 | let _x = MyIter.by_ref() | 1243 | let c = A(B(C)) |
1269 | .take(5) | 1244 | .into_b() // This is a comment |
1270 | .by_ref() | 1245 | // This is another comment |
1271 | .take(5) | 1246 | .into_c(); |
1272 | .by_ref(); | ||
1273 | } | 1247 | } |
1274 | "#, | 1248 | "#, |
1275 | expect![[r#" | 1249 | expect![[r#" |
1276 | [ | 1250 | [ |
1277 | InlayHint { | 1251 | InlayHint { |
1278 | range: 175..242, | 1252 | range: 148..173, |
1279 | kind: ChainingHint, | ||
1280 | label: "impl Iterator<Item = ()>", | ||
1281 | }, | ||
1282 | InlayHint { | ||
1283 | range: 175..225, | ||
1284 | kind: ChainingHint, | ||
1285 | label: "impl Iterator<Item = ()>", | ||
1286 | }, | ||
1287 | InlayHint { | ||
1288 | range: 175..207, | ||
1289 | kind: ChainingHint, | 1253 | kind: ChainingHint, |
1290 | label: "impl Iterator<Item = ()>", | 1254 | label: "B", |
1291 | }, | 1255 | }, |
1292 | InlayHint { | 1256 | InlayHint { |
1293 | range: 175..190, | 1257 | range: 148..155, |
1294 | kind: ChainingHint, | 1258 | kind: ChainingHint, |
1295 | label: "&mut MyIter", | 1259 | label: "A", |
1296 | }, | 1260 | }, |
1297 | ] | 1261 | ] |
1298 | "#]], | 1262 | "#]], |
@@ -1300,156 +1264,163 @@ fn main() { | |||
1300 | } | 1264 | } |
1301 | 1265 | ||
1302 | #[test] | 1266 | #[test] |
1303 | fn shorten_iterators_in_associated_params() { | 1267 | fn chaining_hints_without_newlines() { |
1304 | check_with_config( | 1268 | check_chains( |
1269 | r#" | ||
1270 | struct A(B); | ||
1271 | impl A { fn into_b(self) -> B { self.0 } } | ||
1272 | struct B(C); | ||
1273 | impl B { fn into_c(self) -> C { self.0 } } | ||
1274 | struct C; | ||
1275 | |||
1276 | fn main() { | ||
1277 | let c = A(B(C)).into_b().into_c(); | ||
1278 | }"#, | ||
1279 | ); | ||
1280 | } | ||
1281 | |||
1282 | #[test] | ||
1283 | fn struct_access_chaining_hints() { | ||
1284 | check_expect( | ||
1305 | InlayHintsConfig { | 1285 | InlayHintsConfig { |
1306 | parameter_hints: false, | 1286 | parameter_hints: false, |
1307 | type_hints: true, | 1287 | type_hints: false, |
1308 | chaining_hints: false, | 1288 | chaining_hints: true, |
1309 | max_length: None, | 1289 | max_length: None, |
1310 | }, | 1290 | }, |
1311 | r#" | 1291 | r#" |
1312 | use core::iter; | 1292 | struct A { pub b: B } |
1313 | 1293 | struct B { pub c: C } | |
1314 | pub struct SomeIter<T> {} | 1294 | struct C(pub bool); |
1315 | 1295 | struct D; | |
1316 | impl<T> SomeIter<T> { | ||
1317 | pub fn new() -> Self { SomeIter {} } | ||
1318 | pub fn push(&mut self, t: T) {} | ||
1319 | } | ||
1320 | 1296 | ||
1321 | impl<T> Iterator for SomeIter<T> { | 1297 | impl D { |
1322 | type Item = T; | 1298 | fn foo(&self) -> i32 { 42 } |
1323 | fn next(&mut self) -> Option<Self::Item> { | ||
1324 | None | ||
1325 | } | ||
1326 | } | 1299 | } |
1327 | 1300 | ||
1328 | fn main() { | 1301 | fn main() { |
1329 | let mut some_iter = SomeIter::new(); | 1302 | let x = A { b: B { c: C(true) } } |
1330 | //^^^^^^^^^^^^^ SomeIter<Take<Repeat<i32>>> | 1303 | .b |
1331 | some_iter.push(iter::repeat(2).take(2)); | 1304 | .c |
1332 | let iter_of_iters = some_iter.take(2); | 1305 | .0; |
1333 | //^^^^^^^^^^^^^ impl Iterator<Item = impl Iterator<Item = i32>> | 1306 | let x = D |
1334 | } | 1307 | .foo(); |
1335 | "#, | 1308 | }"#, |
1309 | expect![[r#" | ||
1310 | [ | ||
1311 | InlayHint { | ||
1312 | range: 144..191, | ||
1313 | kind: ChainingHint, | ||
1314 | label: "C", | ||
1315 | }, | ||
1316 | InlayHint { | ||
1317 | range: 144..180, | ||
1318 | kind: ChainingHint, | ||
1319 | label: "B", | ||
1320 | }, | ||
1321 | ] | ||
1322 | "#]], | ||
1336 | ); | 1323 | ); |
1337 | } | 1324 | } |
1338 | 1325 | ||
1339 | #[test] | 1326 | #[test] |
1340 | fn hide_param_hints_for_clones() { | 1327 | fn generic_chaining_hints() { |
1341 | check_with_config( | 1328 | check_expect( |
1342 | InlayHintsConfig { | 1329 | InlayHintsConfig { |
1343 | parameter_hints: true, | 1330 | parameter_hints: false, |
1344 | type_hints: false, | 1331 | type_hints: false, |
1345 | chaining_hints: false, | 1332 | chaining_hints: true, |
1346 | max_length: None, | 1333 | max_length: None, |
1347 | }, | 1334 | }, |
1348 | r#" | 1335 | r#" |
1349 | fn foo(bar: i32, baz: String, qux: f32) {} | 1336 | struct A<T>(T); |
1337 | struct B<T>(T); | ||
1338 | struct C<T>(T); | ||
1339 | struct X<T,R>(T, R); | ||
1350 | 1340 | ||
1341 | impl<T> A<T> { | ||
1342 | fn new(t: T) -> Self { A(t) } | ||
1343 | fn into_b(self) -> B<T> { B(self.0) } | ||
1344 | } | ||
1345 | impl<T> B<T> { | ||
1346 | fn into_c(self) -> C<T> { C(self.0) } | ||
1347 | } | ||
1351 | fn main() { | 1348 | fn main() { |
1352 | let bar = 3; | 1349 | let c = A::new(X(42, true)) |
1353 | let baz = &"baz"; | 1350 | .into_b() |
1354 | let fez = 1.0; | 1351 | .into_c(); |
1355 | foo(bar.clone(), baz.clone(), fez.clone()); | ||
1356 | //^^^^^^^^^^^ qux | ||
1357 | } | 1352 | } |
1358 | "#, | 1353 | "#, |
1354 | expect![[r#" | ||
1355 | [ | ||
1356 | InlayHint { | ||
1357 | range: 247..284, | ||
1358 | kind: ChainingHint, | ||
1359 | label: "B<X<i32, bool>>", | ||
1360 | }, | ||
1361 | InlayHint { | ||
1362 | range: 247..266, | ||
1363 | kind: ChainingHint, | ||
1364 | label: "A<X<i32, bool>>", | ||
1365 | }, | ||
1366 | ] | ||
1367 | "#]], | ||
1359 | ); | 1368 | ); |
1360 | } | 1369 | } |
1361 | 1370 | ||
1362 | #[test] | 1371 | #[test] |
1363 | fn infer_call_method_return_associated_types_with_generic() { | 1372 | fn shorten_iterator_chaining_hints() { |
1364 | check( | 1373 | check_expect( |
1374 | InlayHintsConfig { | ||
1375 | parameter_hints: false, | ||
1376 | type_hints: false, | ||
1377 | chaining_hints: true, | ||
1378 | max_length: None, | ||
1379 | }, | ||
1365 | r#" | 1380 | r#" |
1366 | pub trait Default { | 1381 | use core::iter; |
1367 | fn default() -> Self; | ||
1368 | } | ||
1369 | pub trait Foo { | ||
1370 | type Bar: Default; | ||
1371 | } | ||
1372 | 1382 | ||
1373 | pub fn quux<T: Foo>() -> T::Bar { | 1383 | struct MyIter; |
1374 | let y = Default::default(); | ||
1375 | //^ <T as Foo>::Bar | ||
1376 | 1384 | ||
1377 | y | 1385 | impl Iterator for MyIter { |
1378 | } | 1386 | type Item = (); |
1379 | "#, | 1387 | fn next(&mut self) -> Option<Self::Item> { |
1380 | ); | 1388 | None |
1381 | } | 1389 | } |
1382 | |||
1383 | #[test] | ||
1384 | fn self_param_hints() { | ||
1385 | check( | ||
1386 | r#" | ||
1387 | struct Foo; | ||
1388 | |||
1389 | impl Foo { | ||
1390 | fn foo(self: Self) {} | ||
1391 | fn bar(self: &Self) {} | ||
1392 | } | 1390 | } |
1393 | 1391 | ||
1394 | fn main() { | 1392 | fn main() { |
1395 | Foo::foo(Foo); | 1393 | let _x = MyIter.by_ref() |
1396 | //^^^ self | 1394 | .take(5) |
1397 | Foo::bar(&Foo); | 1395 | .by_ref() |
1398 | //^^^^ self | 1396 | .take(5) |
1399 | } | 1397 | .by_ref(); |
1400 | "#, | ||
1401 | ) | ||
1402 | } | ||
1403 | |||
1404 | #[test] | ||
1405 | fn fn_hints() { | ||
1406 | check( | ||
1407 | r#" | ||
1408 | trait Sized {} | ||
1409 | |||
1410 | fn foo() -> impl Fn() { loop {} } | ||
1411 | fn foo1() -> impl Fn(f64) { loop {} } | ||
1412 | fn foo2() -> impl Fn(f64, f64) { loop {} } | ||
1413 | fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} } | ||
1414 | fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} } | ||
1415 | fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} } | ||
1416 | fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} } | ||
1417 | fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} } | ||
1418 | |||
1419 | fn main() { | ||
1420 | let foo = foo(); | ||
1421 | // ^^^ impl Fn() | ||
1422 | let foo = foo1(); | ||
1423 | // ^^^ impl Fn(f64) | ||
1424 | let foo = foo2(); | ||
1425 | // ^^^ impl Fn(f64, f64) | ||
1426 | let foo = foo3(); | ||
1427 | // ^^^ impl Fn(f64, f64) -> u32 | ||
1428 | let foo = foo4(); | ||
1429 | // ^^^ &dyn Fn(f64, f64) -> u32 | ||
1430 | let foo = foo5(); | ||
1431 | // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32 | ||
1432 | let foo = foo6(); | ||
1433 | // ^^^ impl Fn(f64, f64) -> u32 + Sized | ||
1434 | let foo = foo7(); | ||
1435 | // ^^^ *const (impl Fn(f64, f64) -> u32 + Sized) | ||
1436 | } | 1398 | } |
1437 | "#, | 1399 | "#, |
1438 | ) | 1400 | expect![[r#" |
1439 | } | 1401 | [ |
1440 | 1402 | InlayHint { | |
1441 | #[test] | 1403 | range: 175..242, |
1442 | fn param_name_hints_show_for_literals() { | 1404 | kind: ChainingHint, |
1443 | check( | 1405 | label: "impl Iterator<Item = ()>", |
1444 | r#"pub fn test(a: i32, b: i32) -> [i32; 2] { [a, b] } | 1406 | }, |
1445 | fn main() { | 1407 | InlayHint { |
1446 | test( | 1408 | range: 175..225, |
1447 | 0x0fab272b, | 1409 | kind: ChainingHint, |
1448 | //^^^^^^^^^^ a | 1410 | label: "impl Iterator<Item = ()>", |
1449 | 0x0fab272b | 1411 | }, |
1450 | //^^^^^^^^^^ b | 1412 | InlayHint { |
1451 | ); | 1413 | range: 175..207, |
1452 | }"#, | 1414 | kind: ChainingHint, |
1453 | ) | 1415 | label: "impl Iterator<Item = ()>", |
1416 | }, | ||
1417 | InlayHint { | ||
1418 | range: 175..190, | ||
1419 | kind: ChainingHint, | ||
1420 | label: "&mut MyIter", | ||
1421 | }, | ||
1422 | ] | ||
1423 | "#]], | ||
1424 | ); | ||
1454 | } | 1425 | } |
1455 | } | 1426 | } |