diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-22 19:58:22 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-22 19:58:22 +0000 |
commit | 3d8a0982a12f3aa4b8c193a841f864b15c3cb66e (patch) | |
tree | e20ae00628cc28417e22621f583ba6988677ffcd /crates/ra_hir/src/ty | |
parent | bb665a70627cbc2f4fb930fefb04899941b6afa6 (diff) | |
parent | 247d1c17b385ff8a8c1dda2e899495146b643b98 (diff) |
Merge #866
866: Implement basic support for Associated Methods r=flodiebold a=vipentti
This is my attempt at learning to understand how the type inference works by adding basic support for associated methods. Currently it does not resolve associated types or constants.
The basic idea is that `Resolver::resolve_path` returns a new `PathResult` type, which has two variants, `FullyResolved` and `PartiallyResolved`, fully resolved matches the previous behavior, where as `PartiallyResolved` contains the `PerNs<Resolution` in addition to a `segment_index` which contains the index of the segment which we failed to resolve. This index can then be used to continue inference in `infer_path_expr` using the `Type` we managed to resolve.
This changes some of the previous apis, so looking for feedback and suggestions.
This should enable fixing #832
Co-authored-by: Ville Penttinen <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty')
6 files changed, 223 insertions, 0 deletions
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap new file mode 100644 index 000000000..131d1fa16 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap | |||
@@ -0,0 +1,14 @@ | |||
1 | --- | ||
2 | created: "2019-02-21T21:51:46.497925200Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [227; 305) '{ ...:ID; }': () | ||
8 | [237; 238) 'x': [unknown] | ||
9 | [241; 252) 'Struct::FOO': [unknown] | ||
10 | [262; 263) 'y': [unknown] | ||
11 | [266; 275) 'Enum::BAR': [unknown] | ||
12 | [285; 286) 'z': [unknown] | ||
13 | [289; 302) 'TraitTest::ID': [unknown] | ||
14 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_enum.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_enum.snap new file mode 100644 index 000000000..8f27af88c --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_enum.snap | |||
@@ -0,0 +1,20 @@ | |||
1 | --- | ||
2 | created: "2019-02-20T11:04:56.553382800Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [48; 68) '{ ... }': A | ||
8 | [58; 62) 'A::B': A | ||
9 | [89; 109) '{ ... }': A | ||
10 | [99; 103) 'A::C': A | ||
11 | [122; 179) '{ ... c; }': () | ||
12 | [132; 133) 'a': A | ||
13 | [136; 140) 'A::b': fn b() -> A | ||
14 | [136; 142) 'A::b()': A | ||
15 | [148; 149) 'a': A | ||
16 | [159; 160) 'c': A | ||
17 | [163; 167) 'A::c': fn c() -> A | ||
18 | [163; 169) 'A::c()': A | ||
19 | [175; 176) 'c': A | ||
20 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_generics.snap new file mode 100644 index 000000000..fe5d6590e --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_generics.snap | |||
@@ -0,0 +1,16 @@ | |||
1 | --- | ||
2 | created: "2019-02-21T10:25:18.568887300Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [64; 67) 'val': T | ||
8 | [82; 109) '{ ... }': Gen<T> | ||
9 | [92; 103) 'Gen { val }': Gen<T> | ||
10 | [98; 101) 'val': T | ||
11 | [123; 155) '{ ...32); }': () | ||
12 | [133; 134) 'a': Gen<[unknown]> | ||
13 | [137; 146) 'Gen::make': fn make<[unknown]>(T) -> Gen<T> | ||
14 | [137; 152) 'Gen::make(0u32)': Gen<[unknown]> | ||
15 | [147; 151) '0u32': u32 | ||
16 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_struct.snap new file mode 100644 index 000000000..29ca9b0ea --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_struct.snap | |||
@@ -0,0 +1,16 @@ | |||
1 | --- | ||
2 | created: "2019-02-20T11:04:56.553382800Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [50; 76) '{ ... }': A | ||
8 | [60; 70) 'A { x: 0 }': A | ||
9 | [67; 68) '0': u32 | ||
10 | [89; 123) '{ ...a.x; }': () | ||
11 | [99; 100) 'a': A | ||
12 | [103; 109) 'A::new': fn new() -> A | ||
13 | [103; 111) 'A::new()': A | ||
14 | [117; 118) 'a': A | ||
15 | [117; 120) 'a.x': u32 | ||
16 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_with_modules.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_with_modules.snap new file mode 100644 index 000000000..6584bef39 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_method_with_modules.snap | |||
@@ -0,0 +1,23 @@ | |||
1 | --- | ||
2 | created: "2019-02-21T08:55:53.926725400Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [56; 64) '{ A {} }': A | ||
8 | [58; 62) 'A {}': A | ||
9 | [126; 132) '{ 99 }': u32 | ||
10 | [128; 130) '99': u32 | ||
11 | [202; 210) '{ C {} }': C | ||
12 | [204; 208) 'C {}': C | ||
13 | [241; 325) '{ ...g(); }': () | ||
14 | [251; 252) 'x': A | ||
15 | [255; 266) 'a::A::thing': fn thing() -> A | ||
16 | [255; 268) 'a::A::thing()': A | ||
17 | [278; 279) 'y': u32 | ||
18 | [282; 293) 'b::B::thing': fn thing() -> u32 | ||
19 | [282; 295) 'b::B::thing()': u32 | ||
20 | [305; 306) 'z': C | ||
21 | [309; 320) 'c::C::thing': fn thing() -> C | ||
22 | [309; 322) 'c::C::thing()': C | ||
23 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 3affcb4fe..f04e9109c 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -608,6 +608,140 @@ fn test() -> i128 { | |||
608 | } | 608 | } |
609 | 609 | ||
610 | #[test] | 610 | #[test] |
611 | fn infer_associated_const() { | ||
612 | check_inference( | ||
613 | "infer_associated_const", | ||
614 | r#" | ||
615 | struct Struct; | ||
616 | |||
617 | impl Struct { | ||
618 | const FOO: u32 = 1; | ||
619 | } | ||
620 | |||
621 | enum Enum; | ||
622 | |||
623 | impl Enum { | ||
624 | const BAR: u32 = 2; | ||
625 | } | ||
626 | |||
627 | trait Trait { | ||
628 | const ID: u32; | ||
629 | } | ||
630 | |||
631 | struct TraitTest; | ||
632 | |||
633 | impl Trait for TraitTest { | ||
634 | const ID: u32 = 5; | ||
635 | } | ||
636 | |||
637 | fn test() { | ||
638 | let x = Struct::FOO; | ||
639 | let y = Enum::BAR; | ||
640 | let z = TraitTest::ID; | ||
641 | } | ||
642 | "#, | ||
643 | ); | ||
644 | } | ||
645 | |||
646 | #[test] | ||
647 | fn infer_associated_method_struct() { | ||
648 | check_inference( | ||
649 | "infer_associated_method_struct", | ||
650 | r#" | ||
651 | struct A { x: u32 }; | ||
652 | |||
653 | impl A { | ||
654 | fn new() -> A { | ||
655 | A { x: 0 } | ||
656 | } | ||
657 | } | ||
658 | fn test() { | ||
659 | let a = A::new(); | ||
660 | a.x; | ||
661 | } | ||
662 | "#, | ||
663 | ); | ||
664 | } | ||
665 | |||
666 | #[test] | ||
667 | fn infer_associated_method_enum() { | ||
668 | check_inference( | ||
669 | "infer_associated_method_enum", | ||
670 | r#" | ||
671 | enum A { B, C }; | ||
672 | |||
673 | impl A { | ||
674 | pub fn b() -> A { | ||
675 | A::B | ||
676 | } | ||
677 | pub fn c() -> A { | ||
678 | A::C | ||
679 | } | ||
680 | } | ||
681 | fn test() { | ||
682 | let a = A::b(); | ||
683 | a; | ||
684 | let c = A::c(); | ||
685 | c; | ||
686 | } | ||
687 | "#, | ||
688 | ); | ||
689 | } | ||
690 | |||
691 | #[test] | ||
692 | fn infer_associated_method_with_modules() { | ||
693 | check_inference( | ||
694 | "infer_associated_method_with_modules", | ||
695 | r#" | ||
696 | mod a { | ||
697 | struct A; | ||
698 | impl A { pub fn thing() -> A { A {} }} | ||
699 | } | ||
700 | |||
701 | mod b { | ||
702 | struct B; | ||
703 | impl B { pub fn thing() -> u32 { 99 }} | ||
704 | |||
705 | mod c { | ||
706 | struct C; | ||
707 | impl C { pub fn thing() -> C { C {} }} | ||
708 | } | ||
709 | } | ||
710 | use b::c; | ||
711 | |||
712 | fn test() { | ||
713 | let x = a::A::thing(); | ||
714 | let y = b::B::thing(); | ||
715 | let z = c::C::thing(); | ||
716 | } | ||
717 | "#, | ||
718 | ); | ||
719 | } | ||
720 | |||
721 | #[test] | ||
722 | #[ignore] // FIXME: After https://github.com/rust-analyzer/rust-analyzer/pull/866 is merged | ||
723 | fn infer_associated_method_generics() { | ||
724 | check_inference( | ||
725 | "infer_associated_method_generics", | ||
726 | r#" | ||
727 | struct Gen<T> { | ||
728 | val: T | ||
729 | } | ||
730 | |||
731 | impl<T> Gen<T> { | ||
732 | pub fn make(val: T) -> Gen<T> { | ||
733 | Gen { val } | ||
734 | } | ||
735 | } | ||
736 | |||
737 | fn test() { | ||
738 | let a = Gen::make(0u32); | ||
739 | } | ||
740 | "#, | ||
741 | ); | ||
742 | } | ||
743 | |||
744 | #[test] | ||
611 | fn no_panic_on_field_of_enum() { | 745 | fn no_panic_on_field_of_enum() { |
612 | check_inference( | 746 | check_inference( |
613 | "no_panic_on_field_of_enum", | 747 | "no_panic_on_field_of_enum", |