diff options
Diffstat (limited to 'crates/hir_ty/src/tests/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 1053 |
1 files changed, 1053 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs new file mode 100644 index 000000000..fa68355aa --- /dev/null +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -0,0 +1,1053 @@ | |||
1 | use expect::expect; | ||
2 | |||
3 | use super::{check_infer, check_types}; | ||
4 | |||
5 | #[test] | ||
6 | fn infer_slice_method() { | ||
7 | check_infer( | ||
8 | r#" | ||
9 | #[lang = "slice"] | ||
10 | impl<T> [T] { | ||
11 | fn foo(&self) -> T { | ||
12 | loop {} | ||
13 | } | ||
14 | } | ||
15 | |||
16 | #[lang = "slice_alloc"] | ||
17 | impl<T> [T] {} | ||
18 | |||
19 | fn test(x: &[u8]) { | ||
20 | <[_]>::foo(x); | ||
21 | } | ||
22 | "#, | ||
23 | expect![[r#" | ||
24 | 44..48 'self': &[T] | ||
25 | 55..78 '{ ... }': T | ||
26 | 65..72 'loop {}': ! | ||
27 | 70..72 '{}': () | ||
28 | 130..131 'x': &[u8] | ||
29 | 140..162 '{ ...(x); }': () | ||
30 | 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 | ||
31 | 146..159 '<[_]>::foo(x)': u8 | ||
32 | 157..158 'x': &[u8] | ||
33 | "#]], | ||
34 | ); | ||
35 | } | ||
36 | |||
37 | #[test] | ||
38 | fn infer_associated_method_struct() { | ||
39 | check_infer( | ||
40 | r#" | ||
41 | struct A { x: u32 } | ||
42 | |||
43 | impl A { | ||
44 | fn new() -> A { | ||
45 | A { x: 0 } | ||
46 | } | ||
47 | } | ||
48 | fn test() { | ||
49 | let a = A::new(); | ||
50 | a.x; | ||
51 | } | ||
52 | "#, | ||
53 | expect![[r#" | ||
54 | 48..74 '{ ... }': A | ||
55 | 58..68 'A { x: 0 }': A | ||
56 | 65..66 '0': u32 | ||
57 | 87..121 '{ ...a.x; }': () | ||
58 | 97..98 'a': A | ||
59 | 101..107 'A::new': fn new() -> A | ||
60 | 101..109 'A::new()': A | ||
61 | 115..116 'a': A | ||
62 | 115..118 'a.x': u32 | ||
63 | "#]], | ||
64 | ); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn infer_associated_method_enum() { | ||
69 | check_infer( | ||
70 | r#" | ||
71 | enum A { B, C } | ||
72 | |||
73 | impl A { | ||
74 | pub fn b() -> A { | ||
75 | A::B | ||
76 | } | ||
77 | pub fn c() -> A { | ||
78 | A::C | ||
79 | } | ||
80 | } | ||
81 | fn test() { | ||
82 | let a = A::b(); | ||
83 | a; | ||
84 | let c = A::c(); | ||
85 | c; | ||
86 | } | ||
87 | "#, | ||
88 | expect![[r#" | ||
89 | 46..66 '{ ... }': A | ||
90 | 56..60 'A::B': A | ||
91 | 87..107 '{ ... }': A | ||
92 | 97..101 'A::C': A | ||
93 | 120..177 '{ ... c; }': () | ||
94 | 130..131 'a': A | ||
95 | 134..138 'A::b': fn b() -> A | ||
96 | 134..140 'A::b()': A | ||
97 | 146..147 'a': A | ||
98 | 157..158 'c': A | ||
99 | 161..165 'A::c': fn c() -> A | ||
100 | 161..167 'A::c()': A | ||
101 | 173..174 'c': A | ||
102 | "#]], | ||
103 | ); | ||
104 | } | ||
105 | |||
106 | #[test] | ||
107 | fn infer_associated_method_with_modules() { | ||
108 | check_infer( | ||
109 | r#" | ||
110 | mod a { | ||
111 | struct A; | ||
112 | impl A { pub fn thing() -> A { A {} }} | ||
113 | } | ||
114 | |||
115 | mod b { | ||
116 | struct B; | ||
117 | impl B { pub fn thing() -> u32 { 99 }} | ||
118 | |||
119 | mod c { | ||
120 | struct C; | ||
121 | impl C { pub fn thing() -> C { C {} }} | ||
122 | } | ||
123 | } | ||
124 | use b::c; | ||
125 | |||
126 | fn test() { | ||
127 | let x = a::A::thing(); | ||
128 | let y = b::B::thing(); | ||
129 | let z = c::C::thing(); | ||
130 | } | ||
131 | "#, | ||
132 | expect![[r#" | ||
133 | 55..63 '{ A {} }': A | ||
134 | 57..61 'A {}': A | ||
135 | 125..131 '{ 99 }': u32 | ||
136 | 127..129 '99': u32 | ||
137 | 201..209 '{ C {} }': C | ||
138 | 203..207 'C {}': C | ||
139 | 240..324 '{ ...g(); }': () | ||
140 | 250..251 'x': A | ||
141 | 254..265 'a::A::thing': fn thing() -> A | ||
142 | 254..267 'a::A::thing()': A | ||
143 | 277..278 'y': u32 | ||
144 | 281..292 'b::B::thing': fn thing() -> u32 | ||
145 | 281..294 'b::B::thing()': u32 | ||
146 | 304..305 'z': C | ||
147 | 308..319 'c::C::thing': fn thing() -> C | ||
148 | 308..321 'c::C::thing()': C | ||
149 | "#]], | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn infer_associated_method_generics() { | ||
155 | check_infer( | ||
156 | r#" | ||
157 | struct Gen<T> { | ||
158 | val: T | ||
159 | } | ||
160 | |||
161 | impl<T> Gen<T> { | ||
162 | pub fn make(val: T) -> Gen<T> { | ||
163 | Gen { val } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | fn test() { | ||
168 | let a = Gen::make(0u32); | ||
169 | } | ||
170 | "#, | ||
171 | expect![[r#" | ||
172 | 63..66 'val': T | ||
173 | 81..108 '{ ... }': Gen<T> | ||
174 | 91..102 'Gen { val }': Gen<T> | ||
175 | 97..100 'val': T | ||
176 | 122..154 '{ ...32); }': () | ||
177 | 132..133 'a': Gen<u32> | ||
178 | 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32> | ||
179 | 136..151 'Gen::make(0u32)': Gen<u32> | ||
180 | 146..150 '0u32': u32 | ||
181 | "#]], | ||
182 | ); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn infer_associated_method_generics_without_args() { | ||
187 | check_infer( | ||
188 | r#" | ||
189 | struct Gen<T> { | ||
190 | val: T | ||
191 | } | ||
192 | |||
193 | impl<T> Gen<T> { | ||
194 | pub fn make() -> Gen<T> { | ||
195 | loop { } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | fn test() { | ||
200 | let a = Gen::<u32>::make(); | ||
201 | } | ||
202 | "#, | ||
203 | expect![[r#" | ||
204 | 75..99 '{ ... }': Gen<T> | ||
205 | 85..93 'loop { }': ! | ||
206 | 90..93 '{ }': () | ||
207 | 113..148 '{ ...e(); }': () | ||
208 | 123..124 'a': Gen<u32> | ||
209 | 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32> | ||
210 | 127..145 'Gen::<...make()': Gen<u32> | ||
211 | "#]], | ||
212 | ); | ||
213 | } | ||
214 | |||
215 | #[test] | ||
216 | fn infer_associated_method_generics_2_type_params_without_args() { | ||
217 | check_infer( | ||
218 | r#" | ||
219 | struct Gen<T, U> { | ||
220 | val: T, | ||
221 | val2: U, | ||
222 | } | ||
223 | |||
224 | impl<T> Gen<u32, T> { | ||
225 | pub fn make() -> Gen<u32,T> { | ||
226 | loop { } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | fn test() { | ||
231 | let a = Gen::<u32, u64>::make(); | ||
232 | } | ||
233 | "#, | ||
234 | expect![[r#" | ||
235 | 101..125 '{ ... }': Gen<u32, T> | ||
236 | 111..119 'loop { }': ! | ||
237 | 116..119 '{ }': () | ||
238 | 139..179 '{ ...e(); }': () | ||
239 | 149..150 'a': Gen<u32, u64> | ||
240 | 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> | ||
241 | 153..176 'Gen::<...make()': Gen<u32, u64> | ||
242 | "#]], | ||
243 | ); | ||
244 | } | ||
245 | |||
246 | #[test] | ||
247 | fn cross_crate_associated_method_call() { | ||
248 | check_types( | ||
249 | r#" | ||
250 | //- /main.rs crate:main deps:other_crate | ||
251 | fn test() { | ||
252 | let x = other_crate::foo::S::thing(); | ||
253 | x; | ||
254 | } //^ i128 | ||
255 | |||
256 | //- /lib.rs crate:other_crate | ||
257 | mod foo { | ||
258 | struct S; | ||
259 | impl S { | ||
260 | fn thing() -> i128 {} | ||
261 | } | ||
262 | } | ||
263 | "#, | ||
264 | ); | ||
265 | } | ||
266 | |||
267 | #[test] | ||
268 | fn infer_trait_method_simple() { | ||
269 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
270 | check_infer( | ||
271 | r#" | ||
272 | trait Trait1 { | ||
273 | fn method(&self) -> u32; | ||
274 | } | ||
275 | struct S1; | ||
276 | impl Trait1 for S1 {} | ||
277 | trait Trait2 { | ||
278 | fn method(&self) -> i128; | ||
279 | } | ||
280 | struct S2; | ||
281 | impl Trait2 for S2 {} | ||
282 | fn test() { | ||
283 | S1.method(); // -> u32 | ||
284 | S2.method(); // -> i128 | ||
285 | } | ||
286 | "#, | ||
287 | expect![[r#" | ||
288 | 30..34 'self': &Self | ||
289 | 109..113 'self': &Self | ||
290 | 169..227 '{ ...i128 }': () | ||
291 | 175..177 'S1': S1 | ||
292 | 175..186 'S1.method()': u32 | ||
293 | 202..204 'S2': S2 | ||
294 | 202..213 'S2.method()': i128 | ||
295 | "#]], | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn infer_trait_method_scoped() { | ||
301 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
302 | check_infer( | ||
303 | r#" | ||
304 | struct S; | ||
305 | mod foo { | ||
306 | pub trait Trait1 { | ||
307 | fn method(&self) -> u32; | ||
308 | } | ||
309 | impl Trait1 for super::S {} | ||
310 | } | ||
311 | mod bar { | ||
312 | pub trait Trait2 { | ||
313 | fn method(&self) -> i128; | ||
314 | } | ||
315 | impl Trait2 for super::S {} | ||
316 | } | ||
317 | |||
318 | mod foo_test { | ||
319 | use super::S; | ||
320 | use super::foo::Trait1; | ||
321 | fn test() { | ||
322 | S.method(); // -> u32 | ||
323 | } | ||
324 | } | ||
325 | |||
326 | mod bar_test { | ||
327 | use super::S; | ||
328 | use super::bar::Trait2; | ||
329 | fn test() { | ||
330 | S.method(); // -> i128 | ||
331 | } | ||
332 | } | ||
333 | "#, | ||
334 | expect![[r#" | ||
335 | 62..66 'self': &Self | ||
336 | 168..172 'self': &Self | ||
337 | 299..336 '{ ... }': () | ||
338 | 309..310 'S': S | ||
339 | 309..319 'S.method()': u32 | ||
340 | 415..453 '{ ... }': () | ||
341 | 425..426 'S': S | ||
342 | 425..435 'S.method()': i128 | ||
343 | "#]], | ||
344 | ); | ||
345 | } | ||
346 | |||
347 | #[test] | ||
348 | fn infer_trait_method_generic_1() { | ||
349 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
350 | check_infer( | ||
351 | r#" | ||
352 | trait Trait<T> { | ||
353 | fn method(&self) -> T; | ||
354 | } | ||
355 | struct S; | ||
356 | impl Trait<u32> for S {} | ||
357 | fn test() { | ||
358 | S.method(); | ||
359 | } | ||
360 | "#, | ||
361 | expect![[r#" | ||
362 | 32..36 'self': &Self | ||
363 | 91..110 '{ ...d(); }': () | ||
364 | 97..98 'S': S | ||
365 | 97..107 'S.method()': u32 | ||
366 | "#]], | ||
367 | ); | ||
368 | } | ||
369 | |||
370 | #[test] | ||
371 | fn infer_trait_method_generic_more_params() { | ||
372 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
373 | check_infer( | ||
374 | r#" | ||
375 | trait Trait<T1, T2, T3> { | ||
376 | fn method1(&self) -> (T1, T2, T3); | ||
377 | fn method2(&self) -> (T3, T2, T1); | ||
378 | } | ||
379 | struct S1; | ||
380 | impl Trait<u8, u16, u32> for S1 {} | ||
381 | struct S2; | ||
382 | impl<T> Trait<i8, i16, T> for S2 {} | ||
383 | fn test() { | ||
384 | S1.method1(); // u8, u16, u32 | ||
385 | S1.method2(); // u32, u16, u8 | ||
386 | S2.method1(); // i8, i16, {unknown} | ||
387 | S2.method2(); // {unknown}, i16, i8 | ||
388 | } | ||
389 | "#, | ||
390 | expect![[r#" | ||
391 | 42..46 'self': &Self | ||
392 | 81..85 'self': &Self | ||
393 | 209..360 '{ ..., i8 }': () | ||
394 | 215..217 'S1': S1 | ||
395 | 215..227 'S1.method1()': (u8, u16, u32) | ||
396 | 249..251 'S1': S1 | ||
397 | 249..261 'S1.method2()': (u32, u16, u8) | ||
398 | 283..285 'S2': S2 | ||
399 | 283..295 'S2.method1()': (i8, i16, {unknown}) | ||
400 | 323..325 'S2': S2 | ||
401 | 323..335 'S2.method2()': ({unknown}, i16, i8) | ||
402 | "#]], | ||
403 | ); | ||
404 | } | ||
405 | |||
406 | #[test] | ||
407 | fn infer_trait_method_generic_2() { | ||
408 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
409 | check_infer( | ||
410 | r#" | ||
411 | trait Trait<T> { | ||
412 | fn method(&self) -> T; | ||
413 | } | ||
414 | struct S<T>(T); | ||
415 | impl<U> Trait<U> for S<U> {} | ||
416 | fn test() { | ||
417 | S(1u32).method(); | ||
418 | } | ||
419 | "#, | ||
420 | expect![[r#" | ||
421 | 32..36 'self': &Self | ||
422 | 101..126 '{ ...d(); }': () | ||
423 | 107..108 'S': S<u32>(u32) -> S<u32> | ||
424 | 107..114 'S(1u32)': S<u32> | ||
425 | 107..123 'S(1u32...thod()': u32 | ||
426 | 109..113 '1u32': u32 | ||
427 | "#]], | ||
428 | ); | ||
429 | } | ||
430 | |||
431 | #[test] | ||
432 | fn infer_trait_assoc_method() { | ||
433 | check_infer( | ||
434 | r#" | ||
435 | trait Default { | ||
436 | fn default() -> Self; | ||
437 | } | ||
438 | struct S; | ||
439 | impl Default for S {} | ||
440 | fn test() { | ||
441 | let s1: S = Default::default(); | ||
442 | let s2 = S::default(); | ||
443 | let s3 = <S as Default>::default(); | ||
444 | } | ||
445 | "#, | ||
446 | expect![[r#" | ||
447 | 86..192 '{ ...t(); }': () | ||
448 | 96..98 's1': S | ||
449 | 104..120 'Defaul...efault': fn default<S>() -> S | ||
450 | 104..122 'Defaul...ault()': S | ||
451 | 132..134 's2': S | ||
452 | 137..147 'S::default': fn default<S>() -> S | ||
453 | 137..149 'S::default()': S | ||
454 | 159..161 's3': S | ||
455 | 164..187 '<S as ...efault': fn default<S>() -> S | ||
456 | 164..189 '<S as ...ault()': S | ||
457 | "#]], | ||
458 | ); | ||
459 | } | ||
460 | |||
461 | #[test] | ||
462 | fn infer_trait_assoc_method_generics_1() { | ||
463 | check_infer( | ||
464 | r#" | ||
465 | trait Trait<T> { | ||
466 | fn make() -> T; | ||
467 | } | ||
468 | struct S; | ||
469 | impl Trait<u32> for S {} | ||
470 | struct G<T>; | ||
471 | impl<T> Trait<T> for G<T> {} | ||
472 | fn test() { | ||
473 | let a = S::make(); | ||
474 | let b = G::<u64>::make(); | ||
475 | let c: f64 = G::make(); | ||
476 | } | ||
477 | "#, | ||
478 | expect![[r#" | ||
479 | 126..210 '{ ...e(); }': () | ||
480 | 136..137 'a': u32 | ||
481 | 140..147 'S::make': fn make<S, u32>() -> u32 | ||
482 | 140..149 'S::make()': u32 | ||
483 | 159..160 'b': u64 | ||
484 | 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 | ||
485 | 163..179 'G::<u6...make()': u64 | ||
486 | 189..190 'c': f64 | ||
487 | 198..205 'G::make': fn make<G<f64>, f64>() -> f64 | ||
488 | 198..207 'G::make()': f64 | ||
489 | "#]], | ||
490 | ); | ||
491 | } | ||
492 | |||
493 | #[test] | ||
494 | fn infer_trait_assoc_method_generics_2() { | ||
495 | check_infer( | ||
496 | r#" | ||
497 | trait Trait<T> { | ||
498 | fn make<U>() -> (T, U); | ||
499 | } | ||
500 | struct S; | ||
501 | impl Trait<u32> for S {} | ||
502 | struct G<T>; | ||
503 | impl<T> Trait<T> for G<T> {} | ||
504 | fn test() { | ||
505 | let a = S::make::<i64>(); | ||
506 | let b: (_, i64) = S::make(); | ||
507 | let c = G::<u32>::make::<i64>(); | ||
508 | let d: (u32, _) = G::make::<i64>(); | ||
509 | let e: (u32, i64) = G::make(); | ||
510 | } | ||
511 | "#, | ||
512 | expect![[r#" | ||
513 | 134..312 '{ ...e(); }': () | ||
514 | 144..145 'a': (u32, i64) | ||
515 | 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) | ||
516 | 148..164 'S::mak...i64>()': (u32, i64) | ||
517 | 174..175 'b': (u32, i64) | ||
518 | 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64) | ||
519 | 188..197 'S::make()': (u32, i64) | ||
520 | 207..208 'c': (u32, i64) | ||
521 | 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
522 | 211..234 'G::<u3...i64>()': (u32, i64) | ||
523 | 244..245 'd': (u32, i64) | ||
524 | 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
525 | 258..274 'G::mak...i64>()': (u32, i64) | ||
526 | 284..285 'e': (u32, i64) | ||
527 | 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
528 | 300..309 'G::make()': (u32, i64) | ||
529 | "#]], | ||
530 | ); | ||
531 | } | ||
532 | |||
533 | #[test] | ||
534 | fn infer_trait_assoc_method_generics_3() { | ||
535 | check_infer( | ||
536 | r#" | ||
537 | trait Trait<T> { | ||
538 | fn make() -> (Self, T); | ||
539 | } | ||
540 | struct S<T>; | ||
541 | impl Trait<i64> for S<i32> {} | ||
542 | fn test() { | ||
543 | let a = S::make(); | ||
544 | } | ||
545 | "#, | ||
546 | expect![[r#" | ||
547 | 100..126 '{ ...e(); }': () | ||
548 | 110..111 'a': (S<i32>, i64) | ||
549 | 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) | ||
550 | 114..123 'S::make()': (S<i32>, i64) | ||
551 | "#]], | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn infer_trait_assoc_method_generics_4() { | ||
557 | check_infer( | ||
558 | r#" | ||
559 | trait Trait<T> { | ||
560 | fn make() -> (Self, T); | ||
561 | } | ||
562 | struct S<T>; | ||
563 | impl Trait<i64> for S<u64> {} | ||
564 | impl Trait<i32> for S<u32> {} | ||
565 | fn test() { | ||
566 | let a: (S<u64>, _) = S::make(); | ||
567 | let b: (_, i32) = S::make(); | ||
568 | } | ||
569 | "#, | ||
570 | expect![[r#" | ||
571 | 130..202 '{ ...e(); }': () | ||
572 | 140..141 'a': (S<u64>, i64) | ||
573 | 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) | ||
574 | 157..166 'S::make()': (S<u64>, i64) | ||
575 | 176..177 'b': (S<u32>, i32) | ||
576 | 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) | ||
577 | 190..199 'S::make()': (S<u32>, i32) | ||
578 | "#]], | ||
579 | ); | ||
580 | } | ||
581 | |||
582 | #[test] | ||
583 | fn infer_trait_assoc_method_generics_5() { | ||
584 | check_infer( | ||
585 | r#" | ||
586 | trait Trait<T> { | ||
587 | fn make<U>() -> (Self, T, U); | ||
588 | } | ||
589 | struct S<T>; | ||
590 | impl Trait<i64> for S<u64> {} | ||
591 | fn test() { | ||
592 | let a = <S as Trait<i64>>::make::<u8>(); | ||
593 | let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>(); | ||
594 | } | ||
595 | "#, | ||
596 | expect![[r#" | ||
597 | 106..210 '{ ...>(); }': () | ||
598 | 116..117 'a': (S<u64>, i64, u8) | ||
599 | 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | ||
600 | 120..151 '<S as ...<u8>()': (S<u64>, i64, u8) | ||
601 | 161..162 'b': (S<u64>, i64, u8) | ||
602 | 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | ||
603 | 181..207 'Trait:...<u8>()': (S<u64>, i64, u8) | ||
604 | "#]], | ||
605 | ); | ||
606 | } | ||
607 | |||
608 | #[test] | ||
609 | fn infer_call_trait_method_on_generic_param_1() { | ||
610 | check_infer( | ||
611 | r#" | ||
612 | trait Trait { | ||
613 | fn method(&self) -> u32; | ||
614 | } | ||
615 | fn test<T: Trait>(t: T) { | ||
616 | t.method(); | ||
617 | } | ||
618 | "#, | ||
619 | expect![[r#" | ||
620 | 29..33 'self': &Self | ||
621 | 63..64 't': T | ||
622 | 69..88 '{ ...d(); }': () | ||
623 | 75..76 't': T | ||
624 | 75..85 't.method()': u32 | ||
625 | "#]], | ||
626 | ); | ||
627 | } | ||
628 | |||
629 | #[test] | ||
630 | fn infer_call_trait_method_on_generic_param_2() { | ||
631 | check_infer( | ||
632 | r#" | ||
633 | trait Trait<T> { | ||
634 | fn method(&self) -> T; | ||
635 | } | ||
636 | fn test<U, T: Trait<U>>(t: T) { | ||
637 | t.method(); | ||
638 | } | ||
639 | "#, | ||
640 | expect![[r#" | ||
641 | 32..36 'self': &Self | ||
642 | 70..71 't': T | ||
643 | 76..95 '{ ...d(); }': () | ||
644 | 82..83 't': T | ||
645 | 82..92 't.method()': U | ||
646 | "#]], | ||
647 | ); | ||
648 | } | ||
649 | |||
650 | #[test] | ||
651 | fn infer_with_multiple_trait_impls() { | ||
652 | check_infer( | ||
653 | r#" | ||
654 | trait Into<T> { | ||
655 | fn into(self) -> T; | ||
656 | } | ||
657 | struct S; | ||
658 | impl Into<u32> for S {} | ||
659 | impl Into<u64> for S {} | ||
660 | fn test() { | ||
661 | let x: u32 = S.into(); | ||
662 | let y: u64 = S.into(); | ||
663 | let z = Into::<u64>::into(S); | ||
664 | } | ||
665 | "#, | ||
666 | expect![[r#" | ||
667 | 28..32 'self': Self | ||
668 | 110..201 '{ ...(S); }': () | ||
669 | 120..121 'x': u32 | ||
670 | 129..130 'S': S | ||
671 | 129..137 'S.into()': u32 | ||
672 | 147..148 'y': u64 | ||
673 | 156..157 'S': S | ||
674 | 156..164 'S.into()': u64 | ||
675 | 174..175 'z': u64 | ||
676 | 178..195 'Into::...::into': fn into<S, u64>(S) -> u64 | ||
677 | 178..198 'Into::...nto(S)': u64 | ||
678 | 196..197 'S': S | ||
679 | "#]], | ||
680 | ); | ||
681 | } | ||
682 | |||
683 | #[test] | ||
684 | fn method_resolution_unify_impl_self_type() { | ||
685 | check_types( | ||
686 | r#" | ||
687 | struct S<T>; | ||
688 | impl S<u32> { fn foo(&self) -> u8 {} } | ||
689 | impl S<i32> { fn foo(&self) -> i8 {} } | ||
690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } | ||
691 | //^ (u8, i8) | ||
692 | "#, | ||
693 | ); | ||
694 | } | ||
695 | |||
696 | #[test] | ||
697 | fn method_resolution_trait_before_autoref() { | ||
698 | check_types( | ||
699 | r#" | ||
700 | trait Trait { fn foo(self) -> u128; } | ||
701 | struct S; | ||
702 | impl S { fn foo(&self) -> i8 { 0 } } | ||
703 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
704 | fn test() { S.foo(); } | ||
705 | //^ u128 | ||
706 | "#, | ||
707 | ); | ||
708 | } | ||
709 | |||
710 | #[test] | ||
711 | fn method_resolution_by_value_before_autoref() { | ||
712 | check_types( | ||
713 | r#" | ||
714 | trait Clone { fn clone(&self) -> Self; } | ||
715 | struct S; | ||
716 | impl Clone for S {} | ||
717 | impl Clone for &S {} | ||
718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } | ||
719 | //^ (S, S, &S) | ||
720 | "#, | ||
721 | ); | ||
722 | } | ||
723 | |||
724 | #[test] | ||
725 | fn method_resolution_trait_before_autoderef() { | ||
726 | check_types( | ||
727 | r#" | ||
728 | trait Trait { fn foo(self) -> u128; } | ||
729 | struct S; | ||
730 | impl S { fn foo(self) -> i8 { 0 } } | ||
731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | ||
732 | fn test() { (&S).foo(); } | ||
733 | //^ u128 | ||
734 | "#, | ||
735 | ); | ||
736 | } | ||
737 | |||
738 | #[test] | ||
739 | fn method_resolution_impl_before_trait() { | ||
740 | check_types( | ||
741 | r#" | ||
742 | trait Trait { fn foo(self) -> u128; } | ||
743 | struct S; | ||
744 | impl S { fn foo(self) -> i8 { 0 } } | ||
745 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
746 | fn test() { S.foo(); } | ||
747 | //^ i8 | ||
748 | "#, | ||
749 | ); | ||
750 | } | ||
751 | |||
752 | #[test] | ||
753 | fn method_resolution_impl_ref_before_trait() { | ||
754 | check_types( | ||
755 | r#" | ||
756 | trait Trait { fn foo(self) -> u128; } | ||
757 | struct S; | ||
758 | impl S { fn foo(&self) -> i8 { 0 } } | ||
759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | ||
760 | fn test() { S.foo(); } | ||
761 | //^ i8 | ||
762 | "#, | ||
763 | ); | ||
764 | } | ||
765 | |||
766 | #[test] | ||
767 | fn method_resolution_trait_autoderef() { | ||
768 | check_types( | ||
769 | r#" | ||
770 | trait Trait { fn foo(self) -> u128; } | ||
771 | struct S; | ||
772 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
773 | fn test() { (&S).foo(); } | ||
774 | //^ u128 | ||
775 | "#, | ||
776 | ); | ||
777 | } | ||
778 | |||
779 | #[test] | ||
780 | fn method_resolution_unsize_array() { | ||
781 | check_types( | ||
782 | r#" | ||
783 | #[lang = "slice"] | ||
784 | impl<T> [T] { | ||
785 | fn len(&self) -> usize { loop {} } | ||
786 | } | ||
787 | fn test() { | ||
788 | let a = [1, 2, 3]; | ||
789 | a.len(); | ||
790 | } //^ usize | ||
791 | "#, | ||
792 | ); | ||
793 | } | ||
794 | |||
795 | #[test] | ||
796 | fn method_resolution_trait_from_prelude() { | ||
797 | check_types( | ||
798 | r#" | ||
799 | //- /main.rs crate:main deps:other_crate | ||
800 | struct S; | ||
801 | impl Clone for S {} | ||
802 | |||
803 | fn test() { | ||
804 | S.clone(); | ||
805 | //^ S | ||
806 | } | ||
807 | |||
808 | //- /lib.rs crate:other_crate | ||
809 | #[prelude_import] use foo::*; | ||
810 | |||
811 | mod foo { | ||
812 | trait Clone { | ||
813 | fn clone(&self) -> Self; | ||
814 | } | ||
815 | } | ||
816 | "#, | ||
817 | ); | ||
818 | } | ||
819 | |||
820 | #[test] | ||
821 | fn method_resolution_where_clause_for_unknown_trait() { | ||
822 | // The blanket impl currently applies because we ignore the unresolved where clause | ||
823 | check_types( | ||
824 | r#" | ||
825 | trait Trait { fn foo(self) -> u128; } | ||
826 | struct S; | ||
827 | impl<T> Trait for T where T: UnknownTrait {} | ||
828 | fn test() { (&S).foo(); } | ||
829 | //^ u128 | ||
830 | "#, | ||
831 | ); | ||
832 | } | ||
833 | |||
834 | #[test] | ||
835 | fn method_resolution_where_clause_not_met() { | ||
836 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
837 | // This is also to make sure that we don't resolve to the foo method just | ||
838 | // because that's the only method named foo we can find, which would make | ||
839 | // the below tests not work | ||
840 | check_types( | ||
841 | r#" | ||
842 | trait Clone {} | ||
843 | trait Trait { fn foo(self) -> u128; } | ||
844 | struct S; | ||
845 | impl<T> Trait for T where T: Clone {} | ||
846 | fn test() { (&S).foo(); } | ||
847 | //^ {unknown} | ||
848 | "#, | ||
849 | ); | ||
850 | } | ||
851 | |||
852 | #[test] | ||
853 | fn method_resolution_where_clause_inline_not_met() { | ||
854 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
855 | check_types( | ||
856 | r#" | ||
857 | trait Clone {} | ||
858 | trait Trait { fn foo(self) -> u128; } | ||
859 | struct S; | ||
860 | impl<T: Clone> Trait for T {} | ||
861 | fn test() { (&S).foo(); } | ||
862 | //^ {unknown} | ||
863 | "#, | ||
864 | ); | ||
865 | } | ||
866 | |||
867 | #[test] | ||
868 | fn method_resolution_where_clause_1() { | ||
869 | check_types( | ||
870 | r#" | ||
871 | trait Clone {} | ||
872 | trait Trait { fn foo(self) -> u128; } | ||
873 | struct S; | ||
874 | impl Clone for S {} | ||
875 | impl<T> Trait for T where T: Clone {} | ||
876 | fn test() { S.foo(); } | ||
877 | //^ u128 | ||
878 | "#, | ||
879 | ); | ||
880 | } | ||
881 | |||
882 | #[test] | ||
883 | fn method_resolution_where_clause_2() { | ||
884 | check_types( | ||
885 | r#" | ||
886 | trait Into<T> { fn into(self) -> T; } | ||
887 | trait From<T> { fn from(other: T) -> Self; } | ||
888 | struct S1; | ||
889 | struct S2; | ||
890 | impl From<S2> for S1 {} | ||
891 | impl<T, U> Into<U> for T where U: From<T> {} | ||
892 | fn test() { S2.into(); } | ||
893 | //^ {unknown} | ||
894 | "#, | ||
895 | ); | ||
896 | } | ||
897 | |||
898 | #[test] | ||
899 | fn method_resolution_where_clause_inline() { | ||
900 | check_types( | ||
901 | r#" | ||
902 | trait Into<T> { fn into(self) -> T; } | ||
903 | trait From<T> { fn from(other: T) -> Self; } | ||
904 | struct S1; | ||
905 | struct S2; | ||
906 | impl From<S2> for S1 {} | ||
907 | impl<T, U: From<T>> Into<U> for T {} | ||
908 | fn test() { S2.into(); } | ||
909 | //^ {unknown} | ||
910 | "#, | ||
911 | ); | ||
912 | } | ||
913 | |||
914 | #[test] | ||
915 | fn method_resolution_overloaded_method() { | ||
916 | test_utils::mark::check!(impl_self_type_match_without_receiver); | ||
917 | check_types( | ||
918 | r#" | ||
919 | struct Wrapper<T>(T); | ||
920 | struct Foo<T>(T); | ||
921 | struct Bar<T>(T); | ||
922 | |||
923 | impl<T> Wrapper<Foo<T>> { | ||
924 | pub fn new(foo_: T) -> Self { | ||
925 | Wrapper(Foo(foo_)) | ||
926 | } | ||
927 | } | ||
928 | |||
929 | impl<T> Wrapper<Bar<T>> { | ||
930 | pub fn new(bar_: T) -> Self { | ||
931 | Wrapper(Bar(bar_)) | ||
932 | } | ||
933 | } | ||
934 | |||
935 | fn main() { | ||
936 | let a = Wrapper::<Foo<f32>>::new(1.0); | ||
937 | let b = Wrapper::<Bar<f32>>::new(1.0); | ||
938 | (a, b); | ||
939 | //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) | ||
940 | } | ||
941 | "#, | ||
942 | ); | ||
943 | } | ||
944 | |||
945 | #[test] | ||
946 | fn method_resolution_encountering_fn_type() { | ||
947 | check_types( | ||
948 | r#" | ||
949 | //- /main.rs | ||
950 | fn foo() {} | ||
951 | trait FnOnce { fn call(self); } | ||
952 | fn test() { foo.call(); } | ||
953 | //^ {unknown} | ||
954 | "#, | ||
955 | ); | ||
956 | } | ||
957 | |||
958 | #[test] | ||
959 | fn method_resolution_non_parameter_type() { | ||
960 | check_types( | ||
961 | r#" | ||
962 | mod a { | ||
963 | pub trait Foo { | ||
964 | fn foo(&self); | ||
965 | } | ||
966 | } | ||
967 | |||
968 | struct Wrapper<T>(T); | ||
969 | fn foo<T>(t: Wrapper<T>) | ||
970 | where | ||
971 | Wrapper<T>: a::Foo, | ||
972 | { | ||
973 | t.foo(); | ||
974 | } //^ {unknown} | ||
975 | "#, | ||
976 | ); | ||
977 | } | ||
978 | |||
979 | #[test] | ||
980 | fn method_resolution_3373() { | ||
981 | check_types( | ||
982 | r#" | ||
983 | struct A<T>(T); | ||
984 | |||
985 | impl A<i32> { | ||
986 | fn from(v: i32) -> A<i32> { A(v) } | ||
987 | } | ||
988 | |||
989 | fn main() { | ||
990 | A::from(3); | ||
991 | } //^ A<i32> | ||
992 | "#, | ||
993 | ); | ||
994 | } | ||
995 | |||
996 | #[test] | ||
997 | fn method_resolution_slow() { | ||
998 | // this can get quite slow if we set the solver size limit too high | ||
999 | check_types( | ||
1000 | r#" | ||
1001 | trait SendX {} | ||
1002 | |||
1003 | struct S1; impl SendX for S1 {} | ||
1004 | struct S2; impl SendX for S2 {} | ||
1005 | struct U1; | ||
1006 | |||
1007 | trait Trait { fn method(self); } | ||
1008 | |||
1009 | struct X1<A, B> {} | ||
1010 | impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {} | ||
1011 | |||
1012 | struct S<B, C> {} | ||
1013 | |||
1014 | trait FnX {} | ||
1015 | |||
1016 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | ||
1017 | |||
1018 | fn test() { (S {}).method(); } | ||
1019 | //^ () | ||
1020 | "#, | ||
1021 | ); | ||
1022 | } | ||
1023 | |||
1024 | #[test] | ||
1025 | fn dyn_trait_super_trait_not_in_scope() { | ||
1026 | check_infer( | ||
1027 | r#" | ||
1028 | mod m { | ||
1029 | pub trait SuperTrait { | ||
1030 | fn foo(&self) -> u32 { 0 } | ||
1031 | } | ||
1032 | } | ||
1033 | trait Trait: m::SuperTrait {} | ||
1034 | |||
1035 | struct S; | ||
1036 | impl m::SuperTrait for S {} | ||
1037 | impl Trait for S {} | ||
1038 | |||
1039 | fn test(d: &dyn Trait) { | ||
1040 | d.foo(); | ||
1041 | } | ||
1042 | "#, | ||
1043 | expect![[r#" | ||
1044 | 51..55 'self': &Self | ||
1045 | 64..69 '{ 0 }': u32 | ||
1046 | 66..67 '0': u32 | ||
1047 | 176..177 'd': &dyn Trait | ||
1048 | 191..207 '{ ...o(); }': () | ||
1049 | 197..198 'd': &dyn Trait | ||
1050 | 197..204 'd.foo()': u32 | ||
1051 | "#]], | ||
1052 | ); | ||
1053 | } | ||