diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
5 files changed, 141 insertions, 32 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 8d1076774..94b757af2 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -118,11 +118,13 @@ impl Ty { | |||
118 | // TODO: cache this as a query? | 118 | // TODO: cache this as a query? |
119 | // - if so, what signature? (TyFingerprint, Name)? | 119 | // - if so, what signature? (TyFingerprint, Name)? |
120 | // - or maybe cache all names and def_ids of methods per fingerprint? | 120 | // - or maybe cache all names and def_ids of methods per fingerprint? |
121 | pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<Function> { | 121 | /// Look up the method with the given name, returning the actual autoderefed |
122 | self.iterate_methods(db, |f| { | 122 | /// receiver type (but without autoref applied yet). |
123 | pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> { | ||
124 | self.iterate_methods(db, |ty, f| { | ||
123 | let sig = f.signature(db); | 125 | let sig = f.signature(db); |
124 | if sig.name() == name && sig.has_self_param() { | 126 | if sig.name() == name && sig.has_self_param() { |
125 | Some(f) | 127 | Some((ty.clone(), f)) |
126 | } else { | 128 | } else { |
127 | None | 129 | None |
128 | } | 130 | } |
@@ -134,7 +136,7 @@ impl Ty { | |||
134 | pub fn iterate_methods<T>( | 136 | pub fn iterate_methods<T>( |
135 | self, | 137 | self, |
136 | db: &impl HirDatabase, | 138 | db: &impl HirDatabase, |
137 | mut callback: impl FnMut(Function) -> Option<T>, | 139 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
138 | ) -> Option<T> { | 140 | ) -> Option<T> { |
139 | // For method calls, rust first does any number of autoderef, and then one | 141 | // For method calls, rust first does any number of autoderef, and then one |
140 | // autoref (i.e. when the method takes &self or &mut self). We just ignore | 142 | // autoref (i.e. when the method takes &self or &mut self). We just ignore |
@@ -156,7 +158,7 @@ impl Ty { | |||
156 | for item in impl_block.items(db) { | 158 | for item in impl_block.items(db) { |
157 | match item { | 159 | match item { |
158 | ImplItem::Method(f) => { | 160 | ImplItem::Method(f) => { |
159 | if let Some(result) = callback(f) { | 161 | if let Some(result) = callback(&derefed_ty, f) { |
160 | return Some(result); | 162 | return Some(result); |
161 | } | 163 | } |
162 | } | 164 | } |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap index 626f31252..d1ce87b0a 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap | |||
@@ -1,36 +1,36 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-27T14:52:29.938713255+00:00" | 2 | created: "2019-02-16T20:53:59.655361804Z" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | ||
5 | source: crates/ra_hir/src/ty/tests.rs | 4 | source: crates/ra_hir/src/ty/tests.rs |
5 | expression: "&result" | ||
6 | --- | 6 | --- |
7 | [53; 57) 'self': A<[unknown]> | 7 | [53; 57) 'self': A<T2> |
8 | [65; 87) '{ ... }': [unknown] | 8 | [65; 87) '{ ... }': T2 |
9 | [75; 79) 'self': A<[unknown]> | 9 | [75; 79) 'self': A<T2> |
10 | [75; 81) 'self.x': [unknown] | 10 | [75; 81) 'self.x': T2 |
11 | [99; 100) 't': T | 11 | [99; 100) 't': T |
12 | [110; 115) '{ t }': T | 12 | [110; 115) '{ t }': T |
13 | [112; 113) 't': T | 13 | [112; 113) 't': T |
14 | [135; 261) '{ ....x() }': i128 | 14 | [135; 261) '{ ....x() }': i128 |
15 | [146; 147) 'x': i32 | 15 | [146; 147) 'x': i128 |
16 | [150; 151) '1': i32 | 16 | [150; 151) '1': i128 |
17 | [162; 163) 'y': i32 | 17 | [162; 163) 'y': i128 |
18 | [166; 168) 'id': fn id<i32>(T) -> T | 18 | [166; 168) 'id': fn id<i128>(T) -> T |
19 | [166; 171) 'id(x)': i32 | 19 | [166; 171) 'id(x)': i128 |
20 | [169; 170) 'x': i32 | 20 | [169; 170) 'x': i128 |
21 | [182; 183) 'a': A<i32> | 21 | [182; 183) 'a': A<i128> |
22 | [186; 200) 'A { x: id(y) }': A<i32> | 22 | [186; 200) 'A { x: id(y) }': A<i128> |
23 | [193; 195) 'id': fn id<i32>(T) -> T | 23 | [193; 195) 'id': fn id<i128>(T) -> T |
24 | [193; 198) 'id(y)': i32 | 24 | [193; 198) 'id(y)': i128 |
25 | [196; 197) 'y': i32 | 25 | [196; 197) 'y': i128 |
26 | [211; 212) 'z': i32 | 26 | [211; 212) 'z': i128 |
27 | [215; 217) 'id': fn id<i32>(T) -> T | 27 | [215; 217) 'id': fn id<i128>(T) -> T |
28 | [215; 222) 'id(a.x)': i32 | 28 | [215; 222) 'id(a.x)': i128 |
29 | [218; 219) 'a': A<i32> | 29 | [218; 219) 'a': A<i128> |
30 | [218; 221) 'a.x': i32 | 30 | [218; 221) 'a.x': i128 |
31 | [233; 234) 'b': A<i32> | 31 | [233; 234) 'b': A<i128> |
32 | [237; 247) 'A { x: z }': A<i32> | 32 | [237; 247) 'A { x: z }': A<i128> |
33 | [244; 245) 'z': i32 | 33 | [244; 245) 'z': i128 |
34 | [254; 255) 'b': A<i32> | 34 | [254; 255) 'b': A<i128> |
35 | [254; 259) 'b.x()': i128 | 35 | [254; 259) 'b.x()': i128 |
36 | 36 | ||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap new file mode 100644 index 000000000..44f00a52e --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap | |||
@@ -0,0 +1,39 @@ | |||
1 | --- | ||
2 | created: "2019-02-16T21:58:14.029368845Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [74; 78) 'self': A<X, Y> | ||
8 | [85; 107) '{ ... }': X | ||
9 | [95; 99) 'self': A<X, Y> | ||
10 | [95; 101) 'self.x': X | ||
11 | [117; 121) 'self': A<X, Y> | ||
12 | [128; 150) '{ ... }': Y | ||
13 | [138; 142) 'self': A<X, Y> | ||
14 | [138; 144) 'self.y': Y | ||
15 | [163; 167) 'self': A<X, Y> | ||
16 | [169; 170) 't': T | ||
17 | [188; 223) '{ ... }': (X, Y, T) | ||
18 | [198; 217) '(self.....y, t)': (X, Y, T) | ||
19 | [199; 203) 'self': A<X, Y> | ||
20 | [199; 205) 'self.x': X | ||
21 | [207; 211) 'self': A<X, Y> | ||
22 | [207; 213) 'self.y': Y | ||
23 | [215; 216) 't': T | ||
24 | [245; 342) '{ ...(1); }': () | ||
25 | [255; 256) 'a': A<u64, i64> | ||
26 | [259; 281) 'A { x:...1i64 }': A<u64, i64> | ||
27 | [266; 270) '1u64': u64 | ||
28 | [275; 279) '1i64': i64 | ||
29 | [287; 288) 'a': A<u64, i64> | ||
30 | [287; 292) 'a.x()': u64 | ||
31 | [298; 299) 'a': A<u64, i64> | ||
32 | [298; 303) 'a.y()': i64 | ||
33 | [309; 310) 'a': A<u64, i64> | ||
34 | [309; 319) 'a.z(1i128)': (u64, i64, i128) | ||
35 | [313; 318) '1i128': i128 | ||
36 | [325; 326) 'a': A<u64, i64> | ||
37 | [325; 339) 'a.z::<u128>(1)': (u64, i64, u128) | ||
38 | [337; 338) '1': u128 | ||
39 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap new file mode 100644 index 000000000..f609eaf7c --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap | |||
@@ -0,0 +1,16 @@ | |||
1 | --- | ||
2 | created: "2019-02-17T13:35:06.385679926Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [78; 82) 'self': &Option<T> | ||
8 | [98; 100) '{}': () | ||
9 | [111; 112) 'o': Option<u32> | ||
10 | [127; 165) '{ ...f(); }': () | ||
11 | [133; 146) '(&o).as_ref()': Option<&u32> | ||
12 | [134; 136) '&o': &Option<u32> | ||
13 | [135; 136) 'o': Option<u32> | ||
14 | [152; 153) 'o': Option<u32> | ||
15 | [152; 162) 'o.as_ref()': Option<&u32> | ||
16 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 203f1fe4d..5eb9c4f5b 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -507,6 +507,58 @@ fn test() { | |||
507 | } | 507 | } |
508 | 508 | ||
509 | #[test] | 509 | #[test] |
510 | fn infer_impl_generics() { | ||
511 | check_inference( | ||
512 | "infer_impl_generics", | ||
513 | r#" | ||
514 | struct A<T1, T2> { | ||
515 | x: T1, | ||
516 | y: T2, | ||
517 | } | ||
518 | impl<Y, X> A<X, Y> { | ||
519 | fn x(self) -> X { | ||
520 | self.x | ||
521 | } | ||
522 | fn y(self) -> Y { | ||
523 | self.y | ||
524 | } | ||
525 | fn z<T>(self, t: T) -> (X, Y, T) { | ||
526 | (self.x, self.y, t) | ||
527 | } | ||
528 | } | ||
529 | |||
530 | fn test() -> i128 { | ||
531 | let a = A { x: 1u64, y: 1i64 }; | ||
532 | a.x(); | ||
533 | a.y(); | ||
534 | a.z(1i128); | ||
535 | a.z::<u128>(1); | ||
536 | } | ||
537 | "#, | ||
538 | ); | ||
539 | } | ||
540 | |||
541 | #[test] | ||
542 | fn infer_impl_generics_with_autoderef() { | ||
543 | check_inference( | ||
544 | "infer_impl_generics_with_autoderef", | ||
545 | r#" | ||
546 | enum Option<T> { | ||
547 | Some(T), | ||
548 | None, | ||
549 | } | ||
550 | impl<T> Option<T> { | ||
551 | fn as_ref(&self) -> Option<&T> {} | ||
552 | } | ||
553 | fn test(o: Option<u32>) { | ||
554 | (&o).as_ref(); | ||
555 | o.as_ref(); | ||
556 | } | ||
557 | "#, | ||
558 | ); | ||
559 | } | ||
560 | |||
561 | #[test] | ||
510 | fn infer_generic_chain() { | 562 | fn infer_generic_chain() { |
511 | check_inference( | 563 | check_inference( |
512 | "infer_generic_chain", | 564 | "infer_generic_chain", |