]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | use expect_test::expect; |
2 | ||
3 | use super::{check_infer, check_no_mismatches, check_types}; | |
4 | ||
5 | #[test] | |
6 | fn bug_484() { | |
7 | check_infer( | |
8 | r#" | |
9 | fn test() { | |
10 | let x = if true {}; | |
11 | } | |
12 | "#, | |
13 | expect![[r#" | |
14 | 10..37 '{ ... {}; }': () | |
15 | 20..21 'x': () | |
16 | 24..34 'if true {}': () | |
17 | 27..31 'true': bool | |
18 | 32..34 '{}': () | |
19 | "#]], | |
20 | ); | |
21 | } | |
22 | ||
23 | #[test] | |
24 | fn no_panic_on_field_of_enum() { | |
25 | check_infer( | |
26 | r#" | |
27 | enum X {} | |
28 | ||
29 | fn test(x: X) { | |
30 | x.some_field; | |
31 | } | |
32 | "#, | |
33 | expect![[r#" | |
34 | 19..20 'x': X | |
35 | 25..46 '{ ...eld; }': () | |
36 | 31..32 'x': X | |
37 | 31..43 'x.some_field': {unknown} | |
38 | "#]], | |
39 | ); | |
40 | } | |
41 | ||
42 | #[test] | |
43 | fn bug_585() { | |
44 | check_infer( | |
45 | r#" | |
46 | fn test() { | |
47 | X {}; | |
48 | match x { | |
49 | A::B {} => (), | |
50 | A::Y() => (), | |
51 | } | |
52 | } | |
53 | "#, | |
54 | expect![[r#" | |
55 | 10..88 '{ ... } }': () | |
56 | 16..20 'X {}': {unknown} | |
57 | 26..86 'match ... }': () | |
58 | 32..33 'x': {unknown} | |
59 | 44..51 'A::B {}': {unknown} | |
60 | 55..57 '()': () | |
61 | 67..73 'A::Y()': {unknown} | |
62 | 77..79 '()': () | |
63 | "#]], | |
64 | ); | |
65 | } | |
66 | ||
67 | #[test] | |
68 | fn bug_651() { | |
69 | check_infer( | |
70 | r#" | |
71 | fn quux() { | |
72 | let y = 92; | |
73 | 1 + y; | |
74 | } | |
75 | "#, | |
76 | expect![[r#" | |
77 | 10..40 '{ ...+ y; }': () | |
78 | 20..21 'y': i32 | |
79 | 24..26 '92': i32 | |
80 | 32..33 '1': i32 | |
81 | 32..37 '1 + y': i32 | |
82 | 36..37 'y': i32 | |
83 | "#]], | |
84 | ); | |
85 | } | |
86 | ||
87 | #[test] | |
88 | fn recursive_vars() { | |
89 | check_infer( | |
90 | r#" | |
91 | fn test() { | |
92 | let y = unknown; | |
93 | [y, &y]; | |
94 | } | |
95 | "#, | |
96 | expect![[r#" | |
97 | 10..47 '{ ...&y]; }': () | |
98 | 20..21 'y': {unknown} | |
99 | 24..31 'unknown': {unknown} | |
100 | 37..44 '[y, &y]': [{unknown}; 2] | |
101 | 38..39 'y': {unknown} | |
102 | 41..43 '&y': &{unknown} | |
103 | 42..43 'y': {unknown} | |
104 | "#]], | |
105 | ); | |
106 | } | |
107 | ||
108 | #[test] | |
109 | fn recursive_vars_2() { | |
110 | check_infer( | |
111 | r#" | |
112 | fn test() { | |
113 | let x = unknown; | |
114 | let y = unknown; | |
115 | [(x, y), (&y, &x)]; | |
116 | } | |
117 | "#, | |
118 | expect![[r#" | |
119 | 10..79 '{ ...x)]; }': () | |
120 | 20..21 'x': &{unknown} | |
121 | 24..31 'unknown': &{unknown} | |
122 | 41..42 'y': {unknown} | |
123 | 45..52 'unknown': {unknown} | |
124 | 58..76 '[(x, y..., &x)]': [(&{unknown}, {unknown}); 2] | |
125 | 59..65 '(x, y)': (&{unknown}, {unknown}) | |
126 | 60..61 'x': &{unknown} | |
127 | 63..64 'y': {unknown} | |
128 | 67..75 '(&y, &x)': (&{unknown}, {unknown}) | |
129 | 68..70 '&y': &{unknown} | |
130 | 69..70 'y': {unknown} | |
131 | 72..74 '&x': &&{unknown} | |
132 | 73..74 'x': &{unknown} | |
133 | "#]], | |
134 | ); | |
135 | } | |
136 | ||
137 | #[test] | |
138 | fn array_elements_expected_type() { | |
139 | check_no_mismatches( | |
140 | r#" | |
141 | fn test() { | |
142 | let x: [[u32; 2]; 2] = [[1, 2], [3, 4]]; | |
143 | } | |
144 | "#, | |
145 | ); | |
146 | } | |
147 | ||
148 | #[test] | |
149 | fn infer_std_crash_1() { | |
150 | // caused stack overflow, taken from std | |
151 | check_infer( | |
152 | r#" | |
153 | enum Maybe<T> { | |
154 | Real(T), | |
155 | Fake, | |
156 | } | |
157 | ||
158 | fn write() { | |
159 | match something_unknown { | |
160 | Maybe::Real(ref mut something) => (), | |
161 | } | |
162 | } | |
163 | "#, | |
164 | expect![[r#" | |
165 | 53..138 '{ ... } }': () | |
166 | 59..136 'match ... }': () | |
167 | 65..82 'someth...nknown': Maybe<{unknown}> | |
168 | 93..123 'Maybe:...thing)': Maybe<{unknown}> | |
169 | 105..122 'ref mu...ething': &mut {unknown} | |
170 | 127..129 '()': () | |
171 | "#]], | |
172 | ); | |
173 | } | |
174 | ||
175 | #[test] | |
176 | fn infer_std_crash_2() { | |
177 | // caused "equating two type variables, ...", taken from std | |
178 | check_infer( | |
179 | r#" | |
180 | fn test_line_buffer() { | |
181 | &[0, b'\n', 1, b'\n']; | |
182 | } | |
183 | "#, | |
184 | expect![[r#" | |
185 | 22..52 '{ ...n']; }': () | |
186 | 28..49 '&[0, b...b'\n']': &[u8; 4] | |
187 | 29..49 '[0, b'...b'\n']': [u8; 4] | |
188 | 30..31 '0': u8 | |
189 | 33..38 'b'\n'': u8 | |
190 | 40..41 '1': u8 | |
191 | 43..48 'b'\n'': u8 | |
192 | "#]], | |
193 | ); | |
194 | } | |
195 | ||
196 | #[test] | |
197 | fn infer_std_crash_3() { | |
198 | // taken from rustc | |
199 | check_infer( | |
200 | r#" | |
201 | pub fn compute() { | |
202 | match nope!() { | |
203 | SizeSkeleton::Pointer { non_zero: true, tail } => {} | |
204 | } | |
205 | } | |
206 | "#, | |
207 | expect![[r#" | |
208 | 17..107 '{ ... } }': () | |
209 | 23..105 'match ... }': () | |
210 | 29..36 'nope!()': {unknown} | |
211 | 47..93 'SizeSk...tail }': {unknown} | |
212 | 81..85 'true': bool | |
213 | 81..85 'true': bool | |
214 | 87..91 'tail': {unknown} | |
215 | 97..99 '{}': () | |
216 | "#]], | |
217 | ); | |
218 | } | |
219 | ||
220 | #[test] | |
221 | fn infer_std_crash_4() { | |
222 | // taken from rustc | |
223 | check_infer( | |
224 | r#" | |
225 | pub fn primitive_type() { | |
226 | match *self { | |
227 | BorrowedRef { type_: Primitive(p), ..} => {}, | |
228 | } | |
229 | } | |
230 | "#, | |
231 | expect![[r#" | |
232 | 24..105 '{ ... } }': () | |
233 | 30..103 'match ... }': () | |
234 | 36..41 '*self': {unknown} | |
235 | 37..41 'self': {unknown} | |
236 | 52..90 'Borrow...), ..}': {unknown} | |
237 | 73..85 'Primitive(p)': {unknown} | |
238 | 83..84 'p': {unknown} | |
239 | 94..96 '{}': () | |
240 | "#]], | |
241 | ); | |
242 | } | |
243 | ||
244 | #[test] | |
245 | fn infer_std_crash_5() { | |
246 | // taken from rustc | |
247 | check_infer( | |
248 | r#" | |
249 | fn extra_compiler_flags() { | |
250 | for content in doesnt_matter { | |
251 | let name = if doesnt_matter { | |
252 | first | |
253 | } else { | |
254 | &content | |
255 | }; | |
256 | ||
257 | let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { | |
258 | name | |
259 | } else { | |
260 | content | |
261 | }; | |
262 | } | |
263 | } | |
264 | "#, | |
265 | expect![[r#" | |
266 | 26..322 '{ ... } }': () | |
267 | 32..320 'for co... }': () | |
268 | 36..43 'content': {unknown} | |
269 | 47..60 'doesnt_matter': {unknown} | |
270 | 61..320 '{ ... }': () | |
271 | 75..79 'name': &{unknown} | |
272 | 82..166 'if doe... }': &{unknown} | |
353b0b11 | 273 | 85..98 'doesnt_matter': {unknown} |
064997fb FG |
274 | 99..128 '{ ... }': &{unknown} |
275 | 113..118 'first': &{unknown} | |
276 | 134..166 '{ ... }': &{unknown} | |
277 | 148..156 '&content': &{unknown} | |
278 | 149..156 'content': {unknown} | |
279 | 181..188 'content': &{unknown} | |
280 | 191..313 'if ICE... }': &{unknown} | |
281 | 194..231 'ICE_RE..._VALUE': {unknown} | |
353b0b11 | 282 | 194..247 'ICE_RE...&name)': {unknown} |
064997fb FG |
283 | 241..246 '&name': &&{unknown} |
284 | 242..246 'name': &{unknown} | |
285 | 248..276 '{ ... }': &{unknown} | |
286 | 262..266 'name': &{unknown} | |
287 | 282..313 '{ ... }': {unknown} | |
288 | 296..303 'content': {unknown} | |
289 | "#]], | |
290 | ); | |
291 | } | |
292 | ||
293 | #[test] | |
294 | fn infer_nested_generics_crash() { | |
295 | // another crash found typechecking rustc | |
296 | check_infer( | |
297 | r#" | |
298 | struct Canonical<V> { | |
299 | value: V, | |
300 | } | |
301 | struct QueryResponse<V> { | |
302 | value: V, | |
303 | } | |
304 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { | |
305 | &query_response.value; | |
306 | } | |
307 | "#, | |
308 | expect![[r#" | |
309 | 91..105 'query_response': Canonical<QueryResponse<R>> | |
310 | 136..166 '{ ...lue; }': () | |
311 | 142..163 '&query....value': &QueryResponse<R> | |
312 | 143..157 'query_response': Canonical<QueryResponse<R>> | |
313 | 143..163 'query_....value': QueryResponse<R> | |
314 | "#]], | |
315 | ); | |
316 | } | |
317 | ||
318 | #[test] | |
319 | fn infer_paren_macro_call() { | |
320 | check_infer( | |
321 | r#" | |
322 | macro_rules! bar { () => {0u32} } | |
323 | fn test() { | |
324 | let a = (bar!()); | |
325 | } | |
326 | "#, | |
327 | expect![[r#" | |
328 | !0..4 '0u32': u32 | |
329 | 44..69 '{ ...()); }': () | |
330 | 54..55 'a': u32 | |
331 | "#]], | |
332 | ); | |
333 | } | |
334 | ||
335 | #[test] | |
336 | fn infer_array_macro_call() { | |
337 | check_infer( | |
338 | r#" | |
339 | macro_rules! bar { () => {0u32} } | |
340 | fn test() { | |
341 | let a = [bar!()]; | |
342 | } | |
343 | "#, | |
344 | expect![[r#" | |
345 | !0..4 '0u32': u32 | |
346 | 44..69 '{ ...()]; }': () | |
347 | 54..55 'a': [u32; 1] | |
348 | 58..66 '[bar!()]': [u32; 1] | |
349 | "#]], | |
350 | ); | |
351 | } | |
352 | ||
353 | #[test] | |
354 | fn bug_1030() { | |
355 | check_infer( | |
356 | r#" | |
357 | struct HashSet<T, H>; | |
358 | struct FxHasher; | |
359 | type FxHashSet<T> = HashSet<T, FxHasher>; | |
360 | ||
361 | impl<T, H> HashSet<T, H> { | |
362 | fn default() -> HashSet<T, H> {} | |
363 | } | |
364 | ||
365 | pub fn main_loop() { | |
366 | FxHashSet::default(); | |
367 | } | |
368 | "#, | |
369 | expect![[r#" | |
370 | 143..145 '{}': HashSet<T, H> | |
371 | 168..197 '{ ...t(); }': () | |
372 | 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> | |
373 | 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> | |
374 | "#]], | |
375 | ); | |
376 | } | |
377 | ||
378 | #[test] | |
379 | fn issue_2669() { | |
380 | check_infer( | |
381 | r#" | |
382 | trait A {} | |
383 | trait Write {} | |
384 | struct Response<T> {} | |
385 | ||
386 | trait D { | |
387 | fn foo(); | |
388 | } | |
389 | ||
390 | impl<T:A> D for Response<T> { | |
391 | fn foo() { | |
392 | end(); | |
393 | fn end<W: Write>() { | |
394 | let _x: T = loop {}; | |
395 | } | |
396 | } | |
397 | } | |
398 | "#, | |
399 | expect![[r#" | |
400 | 119..214 '{ ... }': () | |
401 | 129..132 'end': fn end<{unknown}>() | |
402 | 129..134 'end()': () | |
403 | 163..208 '{ ... }': () | |
404 | 181..183 '_x': ! | |
405 | 190..197 'loop {}': ! | |
406 | 195..197 '{}': () | |
407 | "#]], | |
408 | ) | |
409 | } | |
410 | ||
411 | #[test] | |
412 | fn issue_2705() { | |
413 | check_infer( | |
414 | r#" | |
415 | trait Trait {} | |
416 | fn test() { | |
417 | <Trait<u32>>::foo() | |
418 | } | |
419 | "#, | |
420 | expect![[r#" | |
421 | 25..52 '{ ...oo() }': () | |
422 | 31..48 '<Trait...>::foo': {unknown} | |
423 | 31..50 '<Trait...:foo()': () | |
424 | "#]], | |
425 | ); | |
426 | } | |
427 | ||
428 | #[test] | |
429 | fn issue_2683_chars_impl() { | |
430 | check_types( | |
431 | r#" | |
432 | //- minicore: iterator | |
433 | pub struct Chars<'a> {} | |
434 | impl<'a> Iterator for Chars<'a> { | |
435 | type Item = char; | |
436 | fn next(&mut self) -> Option<char> { loop {} } | |
437 | } | |
438 | ||
439 | fn test() { | |
440 | let chars: Chars<'_>; | |
441 | (chars.next(), chars.nth(1)); | |
442 | } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>) | |
443 | "#, | |
444 | ); | |
445 | } | |
446 | ||
447 | #[test] | |
448 | fn issue_3999_slice() { | |
449 | check_infer( | |
450 | r#" | |
451 | fn foo(params: &[usize]) { | |
452 | match params { | |
453 | [ps @ .., _] => {} | |
454 | } | |
455 | } | |
456 | "#, | |
457 | expect![[r#" | |
458 | 7..13 'params': &[usize] | |
459 | 25..80 '{ ... } }': () | |
460 | 31..78 'match ... }': () | |
461 | 37..43 'params': &[usize] | |
462 | 54..66 '[ps @ .., _]': [usize] | |
463 | 55..62 'ps @ ..': &[usize] | |
464 | 60..62 '..': [usize] | |
465 | 64..65 '_': usize | |
466 | 70..72 '{}': () | |
467 | "#]], | |
468 | ); | |
469 | } | |
470 | ||
471 | #[test] | |
472 | fn issue_3999_struct() { | |
473 | // rust-analyzer should not panic on seeing this malformed | |
474 | // record pattern. | |
475 | check_infer( | |
476 | r#" | |
477 | struct Bar { | |
478 | a: bool, | |
479 | } | |
480 | fn foo(b: Bar) { | |
481 | match b { | |
482 | Bar { a: .. } => {}, | |
483 | } | |
484 | } | |
485 | "#, | |
486 | expect![[r#" | |
487 | 35..36 'b': Bar | |
488 | 43..95 '{ ... } }': () | |
489 | 49..93 'match ... }': () | |
490 | 55..56 'b': Bar | |
491 | 67..80 'Bar { a: .. }': Bar | |
492 | 76..78 '..': bool | |
493 | 84..86 '{}': () | |
494 | "#]], | |
495 | ); | |
496 | } | |
497 | ||
498 | #[test] | |
499 | fn issue_4235_name_conflicts() { | |
500 | check_infer( | |
501 | r#" | |
502 | struct FOO {} | |
503 | static FOO:FOO = FOO {}; | |
504 | ||
505 | impl FOO { | |
506 | fn foo(&self) {} | |
507 | } | |
508 | ||
509 | fn main() { | |
510 | let a = &FOO; | |
511 | a.foo(); | |
512 | } | |
513 | "#, | |
514 | expect![[r#" | |
515 | 31..37 'FOO {}': FOO | |
516 | 63..67 'self': &FOO | |
517 | 69..71 '{}': () | |
518 | 85..119 '{ ...o(); }': () | |
519 | 95..96 'a': &FOO | |
520 | 99..103 '&FOO': &FOO | |
521 | 100..103 'FOO': FOO | |
522 | 109..110 'a': &FOO | |
523 | 109..116 'a.foo()': () | |
524 | "#]], | |
525 | ); | |
526 | } | |
527 | ||
528 | #[test] | |
529 | fn issue_4465_dollar_crate_at_type() { | |
530 | check_infer( | |
531 | r#" | |
532 | pub struct Foo {} | |
533 | pub fn anything<T>() -> T { | |
534 | loop {} | |
535 | } | |
536 | macro_rules! foo { | |
537 | () => {{ | |
538 | let r: $crate::Foo = anything(); | |
539 | r | |
540 | }}; | |
541 | } | |
542 | fn main() { | |
543 | let _a = foo!(); | |
544 | } | |
545 | "#, | |
546 | expect![[r#" | |
547 | 44..59 '{ loop {} }': T | |
548 | 50..57 'loop {}': ! | |
549 | 55..57 '{}': () | |
550 | !0..31 '{letr:...g();r}': Foo | |
551 | !4..5 'r': Foo | |
552 | !18..26 'anything': fn anything<Foo>() -> Foo | |
553 | !18..28 'anything()': Foo | |
554 | !29..30 'r': Foo | |
555 | 163..187 '{ ...!(); }': () | |
556 | 173..175 '_a': Foo | |
557 | "#]], | |
558 | ); | |
559 | } | |
560 | ||
561 | #[test] | |
562 | fn issue_6811() { | |
563 | check_infer( | |
564 | r#" | |
565 | macro_rules! profile_function { | |
566 | () => { | |
567 | let _a = 1; | |
568 | let _b = 1; | |
569 | }; | |
570 | } | |
571 | fn main() { | |
572 | profile_function!(); | |
573 | } | |
574 | "#, | |
575 | expect![[r#" | |
064997fb FG |
576 | !3..5 '_a': i32 |
577 | !6..7 '1': i32 | |
578 | !11..13 '_b': i32 | |
579 | !14..15 '1': i32 | |
580 | 103..131 '{ ...!(); }': () | |
581 | "#]], | |
582 | ); | |
583 | } | |
584 | ||
585 | #[test] | |
586 | fn issue_4053_diesel_where_clauses() { | |
587 | check_infer( | |
588 | r#" | |
589 | trait BoxedDsl<DB> { | |
590 | type Output; | |
591 | fn internal_into_boxed(self) -> Self::Output; | |
592 | } | |
593 | ||
594 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | |
595 | order: Order, | |
596 | } | |
597 | ||
598 | trait QueryFragment<DB: Backend> {} | |
599 | ||
600 | trait Into<T> { fn into(self) -> T; } | |
601 | ||
602 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | |
603 | for SelectStatement<F, S, D, W, O, LOf, G> | |
604 | where | |
605 | O: Into<dyn QueryFragment<DB>>, | |
606 | { | |
607 | type Output = XXX; | |
608 | ||
609 | fn internal_into_boxed(self) -> Self::Output { | |
610 | self.order.into(); | |
611 | } | |
612 | } | |
613 | "#, | |
614 | expect![[r#" | |
615 | 65..69 'self': Self | |
616 | 267..271 'self': Self | |
617 | 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | |
618 | 488..522 '{ ... }': () | |
619 | 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | |
620 | 498..508 'self.order': O | |
621 | 498..515 'self.o...into()': dyn QueryFragment<DB> | |
622 | "#]], | |
623 | ); | |
624 | } | |
625 | ||
626 | #[test] | |
627 | fn issue_4953() { | |
628 | check_infer( | |
629 | r#" | |
630 | pub struct Foo(pub i64); | |
631 | impl Foo { | |
632 | fn test() -> Self { Self(0i64) } | |
633 | } | |
634 | "#, | |
635 | expect![[r#" | |
636 | 58..72 '{ Self(0i64) }': Foo | |
637 | 60..64 'Self': Foo(i64) -> Foo | |
638 | 60..70 'Self(0i64)': Foo | |
639 | 65..69 '0i64': i64 | |
640 | "#]], | |
641 | ); | |
642 | check_infer( | |
643 | r#" | |
644 | pub struct Foo<T>(pub T); | |
645 | impl Foo<i64> { | |
646 | fn test() -> Self { Self(0i64) } | |
647 | } | |
648 | "#, | |
649 | expect![[r#" | |
650 | 64..78 '{ Self(0i64) }': Foo<i64> | |
651 | 66..70 'Self': Foo<i64>(i64) -> Foo<i64> | |
652 | 66..76 'Self(0i64)': Foo<i64> | |
653 | 71..75 '0i64': i64 | |
654 | "#]], | |
655 | ); | |
656 | } | |
657 | ||
658 | #[test] | |
659 | fn issue_4931() { | |
660 | check_infer( | |
661 | r#" | |
662 | trait Div<T> { | |
663 | type Output; | |
664 | } | |
665 | ||
666 | trait CheckedDiv: Div<()> {} | |
667 | ||
668 | trait PrimInt: CheckedDiv<Output = ()> { | |
669 | fn pow(self); | |
670 | } | |
671 | ||
672 | fn check<T: PrimInt>(i: T) { | |
673 | i.pow(); | |
674 | } | |
675 | "#, | |
676 | expect![[r#" | |
677 | 117..121 'self': Self | |
678 | 148..149 'i': T | |
679 | 154..170 '{ ...w(); }': () | |
680 | 160..161 'i': T | |
681 | 160..167 'i.pow()': () | |
682 | "#]], | |
683 | ); | |
684 | } | |
685 | ||
686 | #[test] | |
687 | fn issue_4885() { | |
688 | check_infer( | |
689 | r#" | |
690 | //- minicore: coerce_unsized, future | |
691 | use core::future::Future; | |
692 | trait Foo<R> { | |
693 | type Bar; | |
694 | } | |
695 | fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> | |
696 | where | |
697 | K: Foo<R>, | |
698 | { | |
699 | bar(key) | |
700 | } | |
701 | fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> | |
702 | where | |
703 | K: Foo<R>, | |
704 | { | |
705 | } | |
706 | "#, | |
707 | expect![[r#" | |
708 | 70..73 'key': &K | |
709 | 132..148 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> | |
710 | 138..141 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> | |
711 | 138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> | |
712 | 142..145 'key': &K | |
713 | 162..165 'key': &K | |
714 | 224..227 '{ }': () | |
715 | "#]], | |
716 | ); | |
717 | } | |
718 | ||
719 | #[test] | |
720 | fn issue_4800() { | |
721 | check_infer( | |
722 | r#" | |
723 | trait Debug {} | |
724 | ||
725 | struct Foo<T>; | |
726 | ||
727 | type E1<T> = (T, T, T); | |
728 | type E2<T> = E1<E1<E1<(T, T, T)>>>; | |
729 | ||
730 | impl Debug for Foo<E2<()>> {} | |
731 | ||
732 | struct Request; | |
733 | ||
734 | pub trait Future { | |
735 | type Output; | |
736 | } | |
737 | ||
738 | pub struct PeerSet<D>; | |
739 | ||
740 | impl<D> Service<Request> for PeerSet<D> | |
741 | where | |
742 | D: Discover, | |
743 | D::Key: Debug, | |
744 | { | |
745 | type Error = (); | |
746 | type Future = dyn Future<Output = Self::Error>; | |
747 | ||
748 | fn call(&mut self) -> Self::Future { | |
749 | loop {} | |
750 | } | |
751 | } | |
752 | ||
753 | pub trait Discover { | |
754 | type Key; | |
755 | } | |
756 | ||
757 | pub trait Service<Request> { | |
758 | type Error; | |
759 | type Future: Future<Output = Self::Error>; | |
760 | fn call(&mut self) -> Self::Future; | |
761 | } | |
762 | "#, | |
763 | expect![[r#" | |
764 | 379..383 'self': &mut PeerSet<D> | |
765 | 401..424 '{ ... }': dyn Future<Output = ()> | |
766 | 411..418 'loop {}': ! | |
767 | 416..418 '{}': () | |
768 | 575..579 'self': &mut Self | |
769 | "#]], | |
770 | ); | |
771 | } | |
772 | ||
773 | #[test] | |
774 | fn issue_4966() { | |
775 | check_infer( | |
776 | r#" | |
777 | //- minicore: deref | |
778 | pub trait IntoIterator { | |
779 | type Item; | |
780 | } | |
781 | ||
782 | struct Repeat<A> { element: A } | |
783 | ||
784 | struct Map<F> { f: F } | |
785 | ||
786 | struct Vec<T> {} | |
787 | ||
788 | impl<T> core::ops::Deref for Vec<T> { | |
789 | type Target = [T]; | |
790 | } | |
791 | ||
792 | fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} | |
793 | ||
794 | fn main() { | |
795 | let inner = Map { f: |_: &f64| 0.0 }; | |
796 | ||
797 | let repeat = Repeat { element: inner }; | |
798 | ||
799 | let vec = from_iter(repeat); | |
800 | ||
801 | vec.foo_bar(); | |
802 | } | |
803 | "#, | |
804 | expect![[r#" | |
805 | 225..229 'iter': T | |
806 | 244..246 '{}': Vec<A> | |
807 | 258..402 '{ ...r(); }': () | |
808 | 268..273 'inner': Map<|&f64| -> f64> | |
809 | 276..300 'Map { ... 0.0 }': Map<|&f64| -> f64> | |
810 | 285..298 '|_: &f64| 0.0': |&f64| -> f64 | |
811 | 286..287 '_': &f64 | |
812 | 295..298 '0.0': f64 | |
813 | 311..317 'repeat': Repeat<Map<|&f64| -> f64>> | |
814 | 320..345 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> | |
815 | 338..343 'inner': Map<|&f64| -> f64> | |
816 | 356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | |
817 | 362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | |
818 | 362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | |
819 | 372..378 'repeat': Repeat<Map<|&f64| -> f64>> | |
820 | 386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | |
821 | 386..399 'vec.foo_bar()': {unknown} | |
822 | "#]], | |
823 | ); | |
824 | } | |
825 | ||
826 | #[test] | |
827 | fn issue_6628() { | |
828 | check_infer( | |
829 | r#" | |
830 | //- minicore: fn | |
831 | struct S<T>(); | |
832 | impl<T> S<T> { | |
833 | fn f(&self, _t: T) {} | |
834 | fn g<F: FnOnce(&T)>(&self, _f: F) {} | |
835 | } | |
836 | fn main() { | |
837 | let s = S(); | |
838 | s.g(|_x| {}); | |
839 | s.f(10); | |
840 | } | |
841 | "#, | |
842 | expect![[r#" | |
843 | 40..44 'self': &S<T> | |
844 | 46..48 '_t': T | |
845 | 53..55 '{}': () | |
846 | 81..85 'self': &S<T> | |
847 | 87..89 '_f': F | |
848 | 94..96 '{}': () | |
849 | 109..160 '{ ...10); }': () | |
850 | 119..120 's': S<i32> | |
851 | 123..124 'S': S<i32>() -> S<i32> | |
852 | 123..126 'S()': S<i32> | |
853 | 132..133 's': S<i32> | |
854 | 132..144 's.g(|_x| {})': () | |
855 | 136..143 '|_x| {}': |&i32| -> () | |
856 | 137..139 '_x': &i32 | |
857 | 141..143 '{}': () | |
858 | 150..151 's': S<i32> | |
859 | 150..157 's.f(10)': () | |
860 | 154..156 '10': i32 | |
861 | "#]], | |
862 | ); | |
863 | } | |
864 | ||
865 | #[test] | |
866 | fn issue_6852() { | |
867 | check_infer( | |
868 | r#" | |
869 | //- minicore: deref | |
870 | use core::ops::Deref; | |
871 | ||
872 | struct BufWriter {} | |
873 | ||
874 | struct Mutex<T> {} | |
875 | struct MutexGuard<'a, T> {} | |
876 | impl<T> Mutex<T> { | |
877 | fn lock(&self) -> MutexGuard<'_, T> {} | |
878 | } | |
879 | impl<'a, T: 'a> Deref for MutexGuard<'a, T> { | |
880 | type Target = T; | |
881 | } | |
882 | fn flush(&self) { | |
883 | let w: &Mutex<BufWriter>; | |
884 | *(w.lock()); | |
885 | } | |
886 | "#, | |
887 | expect![[r#" | |
888 | 123..127 'self': &Mutex<T> | |
889 | 150..152 '{}': MutexGuard<T> | |
890 | 234..238 'self': &{unknown} | |
891 | 240..290 '{ ...()); }': () | |
892 | 250..251 'w': &Mutex<BufWriter> | |
893 | 276..287 '*(w.lock())': BufWriter | |
894 | 278..279 'w': &Mutex<BufWriter> | |
895 | 278..286 'w.lock()': MutexGuard<BufWriter> | |
896 | "#]], | |
897 | ); | |
898 | } | |
899 | ||
900 | #[test] | |
901 | fn param_overrides_fn() { | |
902 | check_types( | |
903 | r#" | |
904 | fn example(example: i32) { | |
905 | fn f() {} | |
906 | example; | |
907 | //^^^^^^^ i32 | |
908 | } | |
909 | "#, | |
910 | ) | |
911 | } | |
912 | ||
913 | #[test] | |
914 | fn lifetime_from_chalk_during_deref() { | |
915 | check_types( | |
916 | r#" | |
917 | //- minicore: deref | |
918 | struct Box<T: ?Sized> {} | |
919 | impl<T: ?Sized> core::ops::Deref for Box<T> { | |
920 | type Target = T; | |
921 | ||
922 | fn deref(&self) -> &Self::Target { | |
923 | loop {} | |
924 | } | |
925 | } | |
926 | ||
927 | trait Iterator { | |
928 | type Item; | |
929 | } | |
930 | ||
931 | pub struct Iter<'a, T: 'a> { | |
932 | inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>, | |
933 | } | |
934 | ||
935 | trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> { | |
936 | fn clone_box(&self); | |
937 | } | |
938 | ||
939 | fn clone_iter<T>(s: Iter<T>) { | |
940 | s.inner.clone_box(); | |
941 | //^^^^^^^^^^^^^^^^^^^ () | |
942 | } | |
943 | "#, | |
944 | ) | |
945 | } | |
946 | ||
947 | #[test] | |
948 | fn issue_8686() { | |
949 | check_infer( | |
950 | r#" | |
951 | pub trait Try: FromResidual { | |
952 | type Output; | |
953 | type Residual; | |
954 | } | |
955 | pub trait FromResidual<R = <Self as Try>::Residual> { | |
956 | fn from_residual(residual: R) -> Self; | |
957 | } | |
958 | ||
959 | struct ControlFlow<B, C>; | |
960 | impl<B, C> Try for ControlFlow<B, C> { | |
961 | type Output = C; | |
962 | type Residual = ControlFlow<B, !>; | |
963 | } | |
964 | impl<B, C> FromResidual for ControlFlow<B, C> { | |
965 | fn from_residual(r: ControlFlow<B, !>) -> Self { ControlFlow } | |
966 | } | |
967 | ||
968 | fn test() { | |
969 | ControlFlow::from_residual(ControlFlow::<u32, !>); | |
970 | } | |
971 | "#, | |
972 | expect![[r#" | |
973 | 144..152 'residual': R | |
974 | 365..366 'r': ControlFlow<B, !> | |
975 | 395..410 '{ ControlFlow }': ControlFlow<B, C> | |
976 | 397..408 'ControlFlow': ControlFlow<B, C> | |
977 | 424..482 '{ ...!>); }': () | |
978 | 430..456 'Contro...sidual': fn from_residual<ControlFlow<u32, {unknown}>, ControlFlow<u32, !>>(ControlFlow<u32, !>) -> ControlFlow<u32, {unknown}> | |
979 | 430..479 'Contro...2, !>)': ControlFlow<u32, {unknown}> | |
980 | 457..478 'Contro...32, !>': ControlFlow<u32, !> | |
981 | "#]], | |
982 | ); | |
983 | } | |
984 | ||
985 | #[test] | |
986 | fn cfg_tail() { | |
987 | // https://github.com/rust-lang/rust-analyzer/issues/8378 | |
988 | check_infer( | |
989 | r#" | |
990 | fn fake_tail(){ | |
991 | { "first" } | |
992 | #[cfg(never)] 9 | |
993 | } | |
994 | fn multiple_fake(){ | |
995 | { "fake" } | |
996 | { "fake" } | |
997 | { "second" } | |
998 | #[cfg(never)] { 11 } | |
999 | #[cfg(never)] 12; | |
1000 | #[cfg(never)] 13 | |
1001 | } | |
1002 | fn no_normal_tail(){ | |
1003 | { "third" } | |
1004 | #[cfg(never)] 14; | |
1005 | #[cfg(never)] 15; | |
1006 | } | |
1007 | fn no_actual_tail(){ | |
1008 | { "fourth" }; | |
1009 | #[cfg(never)] 14; | |
1010 | #[cfg(never)] 15 | |
1011 | } | |
1012 | "#, | |
1013 | expect![[r#" | |
1014 | 14..53 '{ ...)] 9 }': () | |
1015 | 20..31 '{ "first" }': () | |
1016 | 22..29 '"first"': &str | |
1017 | 72..190 '{ ...] 13 }': () | |
353b0b11 | 1018 | 78..88 '{ "fake" }': () |
064997fb | 1019 | 80..86 '"fake"': &str |
353b0b11 | 1020 | 93..103 '{ "fake" }': () |
064997fb FG |
1021 | 95..101 '"fake"': &str |
1022 | 108..120 '{ "second" }': () | |
1023 | 110..118 '"second"': &str | |
1024 | 210..273 '{ ... 15; }': () | |
1025 | 216..227 '{ "third" }': () | |
1026 | 218..225 '"third"': &str | |
1027 | 293..357 '{ ...] 15 }': () | |
1028 | 299..311 '{ "fourth" }': &str | |
1029 | 301..309 '"fourth"': &str | |
1030 | "#]], | |
1031 | ) | |
1032 | } | |
1033 | ||
1034 | #[test] | |
1035 | fn impl_trait_in_option_9530() { | |
1036 | check_types( | |
1037 | r#" | |
1038 | //- minicore: sized | |
1039 | struct Option<T>; | |
1040 | impl<T> Option<T> { | |
1041 | fn unwrap(self) -> T { loop {} } | |
1042 | } | |
1043 | fn make() -> Option<impl Copy> { Option } | |
1044 | trait Copy {} | |
1045 | fn test() { | |
1046 | let o = make(); | |
1047 | o.unwrap(); | |
1048 | //^^^^^^^^^^ impl Copy | |
1049 | } | |
1050 | "#, | |
1051 | ) | |
1052 | } | |
1053 | ||
1054 | #[test] | |
1055 | fn bare_dyn_trait_binders_9639() { | |
1056 | check_no_mismatches( | |
1057 | r#" | |
1058 | //- minicore: fn, coerce_unsized | |
1059 | fn infix_parse<T, S>(_state: S, _level_code: &Fn(S)) -> T { | |
1060 | loop {} | |
1061 | } | |
1062 | ||
1063 | fn parse_arule() { | |
1064 | infix_parse((), &(|_recurse| ())) | |
1065 | } | |
1066 | "#, | |
1067 | ) | |
1068 | } | |
1069 | ||
1070 | #[test] | |
1071 | fn call_expected_type_closure() { | |
1072 | check_types( | |
1073 | r#" | |
1074 | //- minicore: fn, option | |
1075 | ||
1076 | fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} } | |
1077 | struct S { | |
1078 | field: u32 | |
1079 | } | |
1080 | ||
1081 | fn test() { | |
1082 | let o = Some(S { field: 2 }); | |
1083 | let _: Option<()> = map(o, |s| { s.field; }); | |
1084 | // ^^^^^^^ u32 | |
1085 | } | |
1086 | "#, | |
1087 | ); | |
1088 | } | |
1089 | ||
1090 | #[test] | |
1091 | fn coerce_diesel_panic() { | |
1092 | check_no_mismatches( | |
1093 | r#" | |
1094 | //- minicore: option | |
1095 | ||
1096 | trait TypeMetadata { | |
1097 | type MetadataLookup; | |
1098 | } | |
1099 | ||
1100 | pub struct Output<'a, T, DB> | |
1101 | where | |
1102 | DB: TypeMetadata, | |
1103 | DB::MetadataLookup: 'a, | |
1104 | { | |
1105 | out: T, | |
1106 | metadata_lookup: Option<&'a DB::MetadataLookup>, | |
1107 | } | |
1108 | ||
1109 | impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> { | |
1110 | pub fn new(out: T, metadata_lookup: &'a DB::MetadataLookup) -> Self { | |
1111 | Output { | |
1112 | out, | |
1113 | metadata_lookup: Some(metadata_lookup), | |
1114 | } | |
1115 | } | |
1116 | } | |
1117 | "#, | |
1118 | ); | |
1119 | } | |
1120 | ||
1121 | #[test] | |
1122 | fn bitslice_panic() { | |
1123 | check_no_mismatches( | |
1124 | r#" | |
1125 | //- minicore: option, deref | |
1126 | ||
1127 | pub trait BitView { | |
1128 | type Store; | |
1129 | } | |
1130 | ||
1131 | pub struct Lsb0; | |
1132 | ||
1133 | pub struct BitArray<V: BitView> { } | |
1134 | ||
1135 | pub struct BitSlice<T> { } | |
1136 | ||
1137 | impl<V: BitView> core::ops::Deref for BitArray<V> { | |
1138 | type Target = BitSlice<V::Store>; | |
1139 | } | |
1140 | ||
1141 | impl<T> BitSlice<T> { | |
1142 | pub fn split_first(&self) -> Option<(T, &Self)> { loop {} } | |
1143 | } | |
1144 | ||
1145 | fn multiexp_inner() { | |
1146 | let exp: &BitArray<Foo>; | |
1147 | exp.split_first(); | |
1148 | } | |
1149 | "#, | |
1150 | ); | |
1151 | } | |
1152 | ||
1153 | #[test] | |
1154 | fn macro_expands_to_impl_trait() { | |
1155 | check_no_mismatches( | |
1156 | r#" | |
1157 | trait Foo {} | |
1158 | ||
1159 | macro_rules! ty { | |
1160 | () => { | |
1161 | impl Foo | |
1162 | } | |
1163 | } | |
1164 | ||
1165 | fn foo(_: ty!()) {} | |
1166 | ||
1167 | fn bar() { | |
1168 | foo(()); | |
1169 | } | |
1170 | "#, | |
1171 | ) | |
1172 | } | |
1173 | ||
1174 | #[test] | |
1175 | fn nested_macro_in_fn_params() { | |
1176 | check_no_mismatches( | |
1177 | r#" | |
1178 | macro_rules! U32Inner { | |
1179 | () => { | |
1180 | u32 | |
1181 | }; | |
1182 | } | |
1183 | ||
1184 | macro_rules! U32 { | |
1185 | () => { | |
1186 | U32Inner!() | |
1187 | }; | |
1188 | } | |
1189 | ||
1190 | fn mamba(a: U32!(), p: u32) -> u32 { | |
1191 | a | |
1192 | } | |
1193 | "#, | |
1194 | ) | |
1195 | } | |
1196 | ||
1197 | #[test] | |
1198 | fn for_loop_block_expr_iterable() { | |
1199 | check_infer( | |
1200 | r#" | |
1201 | fn test() { | |
1202 | for _ in { let x = 0; } { | |
1203 | let y = 0; | |
1204 | } | |
1205 | } | |
1206 | "#, | |
1207 | expect![[r#" | |
1208 | 10..68 '{ ... } }': () | |
1209 | 16..66 'for _ ... }': () | |
1210 | 20..21 '_': {unknown} | |
1211 | 25..39 '{ let x = 0; }': () | |
1212 | 31..32 'x': i32 | |
1213 | 35..36 '0': i32 | |
1214 | 40..66 '{ ... }': () | |
1215 | 54..55 'y': i32 | |
1216 | 58..59 '0': i32 | |
1217 | "#]], | |
1218 | ); | |
1219 | } | |
1220 | ||
1221 | #[test] | |
1222 | fn while_loop_block_expr_iterable() { | |
1223 | check_infer( | |
1224 | r#" | |
1225 | fn test() { | |
1226 | while { true } { | |
1227 | let y = 0; | |
1228 | } | |
1229 | } | |
1230 | "#, | |
1231 | expect![[r#" | |
1232 | 10..59 '{ ... } }': () | |
1233 | 16..57 'while ... }': () | |
1234 | 22..30 '{ true }': bool | |
1235 | 24..28 'true': bool | |
1236 | 31..57 '{ ... }': () | |
1237 | 45..46 'y': i32 | |
1238 | 49..50 '0': i32 | |
1239 | "#]], | |
1240 | ); | |
1241 | } | |
1242 | ||
1243 | #[test] | |
1244 | fn bug_11242() { | |
1245 | // FIXME: wrong, should be u32 | |
1246 | check_types( | |
1247 | r#" | |
1248 | fn foo<A, B>() | |
1249 | where | |
1250 | A: IntoIterator<Item = u32>, | |
1251 | B: IntoIterator<Item = usize>, | |
1252 | { | |
1253 | let _x: <A as IntoIterator>::Item; | |
1254 | // ^^ {unknown} | |
1255 | } | |
1256 | ||
1257 | pub trait Iterator { | |
1258 | type Item; | |
1259 | } | |
1260 | ||
1261 | pub trait IntoIterator { | |
1262 | type Item; | |
1263 | type IntoIter: Iterator<Item = Self::Item>; | |
1264 | } | |
1265 | ||
1266 | impl<I: Iterator> IntoIterator for I { | |
1267 | type Item = I::Item; | |
1268 | type IntoIter = I; | |
1269 | } | |
1270 | "#, | |
1271 | ); | |
1272 | } | |
1273 | ||
1274 | #[test] | |
1275 | fn bug_11659() { | |
1276 | check_no_mismatches( | |
1277 | r#" | |
1278 | struct LinkArray<const N: usize, LD>(LD); | |
1279 | fn f<const N: usize, LD>(x: LD) -> LinkArray<N, LD> { | |
1280 | let r = LinkArray::<N, LD>(x); | |
1281 | r | |
1282 | } | |
1283 | ||
1284 | fn test() { | |
1285 | let x = f::<2, i32>(5); | |
1286 | let y = LinkArray::<52, LinkArray<2, i32>>(x); | |
1287 | } | |
1288 | "#, | |
1289 | ); | |
1290 | check_no_mismatches( | |
1291 | r#" | |
1292 | struct LinkArray<LD, const N: usize>(LD); | |
1293 | fn f<const N: usize, LD>(x: LD) -> LinkArray<LD, N> { | |
1294 | let r = LinkArray::<LD, N>(x); | |
1295 | r | |
1296 | } | |
1297 | ||
1298 | fn test() { | |
1299 | let x = f::<i32, 2>(5); | |
1300 | let y = LinkArray::<LinkArray<i32, 2>, 52>(x); | |
1301 | } | |
1302 | "#, | |
1303 | ); | |
1304 | } | |
1305 | ||
1306 | #[test] | |
1307 | fn const_generic_error_tolerance() { | |
1308 | check_no_mismatches( | |
1309 | r#" | |
1310 | #[lang = "sized"] | |
1311 | pub trait Sized {} | |
1312 | ||
1313 | struct CT<const N: usize, T>(T); | |
1314 | struct TC<T, const N: usize>(T); | |
1315 | fn f<const N: usize, T>(x: T) -> (CT<N, T>, TC<T, N>) { | |
1316 | let l = CT::<N, T>(x); | |
1317 | let r = TC::<N, T>(x); | |
1318 | (l, r) | |
1319 | } | |
1320 | ||
1321 | trait TR1<const N: usize>; | |
1322 | trait TR2<const N: usize>; | |
1323 | ||
1324 | impl<const N: usize, T> TR1<N> for CT<N, T>; | |
1325 | impl<const N: usize, T> TR1<5> for TC<T, N>; | |
1326 | impl<const N: usize, T> TR2<N> for CT<T, N>; | |
1327 | ||
1328 | trait TR3<const N: usize> { | |
1329 | fn tr3(&self) -> &Self; | |
1330 | } | |
1331 | ||
1332 | impl<const N: usize, T> TR3<5> for TC<T, N> { | |
1333 | fn tr3(&self) -> &Self { | |
1334 | self | |
1335 | } | |
1336 | } | |
1337 | ||
1338 | impl<const N: usize, T> TR3<Item = 5> for TC<T, N> {} | |
1339 | impl<const N: usize, T> TR3<T> for TC<T, N> {} | |
1340 | ||
1341 | fn impl_trait<const N: usize>(inp: impl TR1<N>) {} | |
1342 | fn dyn_trait<const N: usize>(inp: &dyn TR2<N>) {} | |
1343 | fn impl_trait_bad<'a, const N: usize>(inp: impl TR1<i32>) -> impl TR1<'a, i32> {} | |
1344 | fn impl_trait_very_bad<const N: usize>(inp: impl TR1<Item = i32>) -> impl TR1<'a, Item = i32, 5, Foo = N> {} | |
1345 | ||
1346 | fn test() { | |
1347 | f::<2, i32>(5); | |
1348 | f::<2, 2>(5); | |
1349 | f(5); | |
1350 | f::<i32>(5); | |
1351 | CT::<52, CT<2, i32>>(x); | |
1352 | CT::<CT<2, i32>>(x); | |
1353 | impl_trait_bad(5); | |
1354 | impl_trait_bad(12); | |
1355 | TR3<5>::tr3(); | |
1356 | TR3<{ 2+3 }>::tr3(); | |
1357 | TC::<i32, 10>(5).tr3(); | |
1358 | TC::<i32, 20>(5).tr3(); | |
1359 | TC::<i32, i32>(5).tr3(); | |
1360 | TC::<i32, { 7 + 3 }>(5).tr3(); | |
1361 | } | |
1362 | "#, | |
1363 | ); | |
1364 | } | |
1365 | ||
1366 | #[test] | |
1367 | fn const_generic_impl_trait() { | |
1368 | check_no_mismatches( | |
1369 | r#" | |
1370 | //- minicore: from | |
1371 | ||
1372 | struct Foo<T, const M: usize>; | |
1373 | ||
1374 | trait Tr<T> { | |
1375 | fn f(T) -> Self; | |
1376 | } | |
1377 | ||
1378 | impl<T, const M: usize> Tr<[T; M]> for Foo<T, M> { | |
1379 | fn f(_: [T; M]) -> Self { | |
1380 | Self | |
1381 | } | |
1382 | } | |
1383 | ||
1384 | fn test() { | |
1385 | Foo::f([1, 2, 7, 10]); | |
1386 | } | |
1387 | "#, | |
1388 | ); | |
1389 | } | |
1390 | ||
1391 | #[test] | |
1392 | fn nalgebra_factorial() { | |
1393 | check_no_mismatches( | |
1394 | r#" | |
1395 | const FACTORIAL: [u128; 4] = [1, 1, 2, 6]; | |
1396 | ||
1397 | fn factorial(n: usize) -> u128 { | |
1398 | match FACTORIAL.get(n) { | |
1399 | Some(f) => *f, | |
1400 | None => panic!("{}! is greater than u128::MAX", n), | |
1401 | } | |
1402 | } | |
1403 | "#, | |
1404 | ) | |
1405 | } | |
1406 | ||
1407 | #[test] | |
1408 | fn regression_11688_1() { | |
1409 | check_no_mismatches( | |
1410 | r#" | |
1411 | pub struct Buffer<T>(T); | |
1412 | type Writer = Buffer<u8>; | |
1413 | impl<T> Buffer<T> { | |
1414 | fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) { | |
1415 | loop {} | |
1416 | } | |
1417 | } | |
1418 | trait Encode<S> { | |
1419 | fn encode(self, w: &mut Writer, s: &mut S); | |
1420 | } | |
1421 | impl<S> Encode<S> for u8 { | |
1422 | fn encode(self, w: &mut Writer, _: &mut S) { | |
1423 | w.extend_from_array(&self.to_le_bytes()); | |
1424 | } | |
1425 | } | |
1426 | "#, | |
1427 | ); | |
1428 | } | |
1429 | ||
1430 | #[test] | |
1431 | fn regression_11688_2() { | |
1432 | check_types( | |
1433 | r#" | |
1434 | union MaybeUninit<T> { | |
1435 | uninit: (), | |
1436 | value: T, | |
1437 | } | |
1438 | ||
1439 | impl<T> MaybeUninit<T> { | |
1440 | fn uninit_array<const LEN: usize>() -> [Self; LEN] { | |
1441 | loop {} | |
1442 | } | |
1443 | } | |
1444 | ||
1445 | fn main() { | |
1446 | let x = MaybeUninit::<i32>::uninit_array::<1>(); | |
1447 | //^ [MaybeUninit<i32>; 1] | |
1448 | } | |
1449 | "#, | |
1450 | ); | |
1451 | } | |
1452 | ||
1453 | #[test] | |
1454 | fn regression_11688_3() { | |
1455 | check_types( | |
1456 | r#" | |
1457 | //- minicore: iterator | |
1458 | struct Ar<T, const N: u8>(T); | |
1459 | fn f<const LEN: usize, T, const BASE: u8>( | |
1460 | num_zeros: usize, | |
1461 | ) -> dyn Iterator<Item = [Ar<T, BASE>; LEN]> { | |
1462 | loop {} | |
1463 | } | |
1464 | fn dynamic_programming() { | |
1465 | for board in f::<9, u8, 7>(1) { | |
1466 | //^^^^^ [Ar<u8, 7>; 9] | |
1467 | } | |
1468 | } | |
1469 | "#, | |
1470 | ); | |
1471 | } | |
1472 | ||
1473 | #[test] | |
1474 | fn regression_11688_4() { | |
1475 | check_types( | |
1476 | r#" | |
1477 | trait Bar<const C: usize> { | |
1478 | fn baz(&self) -> [i32; C]; | |
1479 | } | |
1480 | ||
1481 | fn foo(x: &dyn Bar<2>) { | |
1482 | x.baz(); | |
1483 | //^^^^^^^ [i32; 2] | |
1484 | } | |
1485 | "#, | |
1486 | ) | |
1487 | } | |
1488 | ||
1489 | #[test] | |
1490 | fn gat_crash_1() { | |
064997fb FG |
1491 | check_no_mismatches( |
1492 | r#" | |
1493 | trait ATrait {} | |
1494 | ||
1495 | trait Crash { | |
1496 | type Member<const N: usize>: ATrait; | |
1497 | fn new<const N: usize>() -> Self::Member<N>; | |
1498 | } | |
1499 | ||
1500 | fn test<T: Crash>() { | |
1501 | T::new(); | |
1502 | } | |
1503 | "#, | |
1504 | ); | |
1505 | } | |
1506 | ||
1507 | #[test] | |
1508 | fn gat_crash_2() { | |
1509 | check_no_mismatches( | |
1510 | r#" | |
1511 | pub struct InlineStorage {} | |
1512 | ||
1513 | pub struct InlineStorageHandle<T: ?Sized> {} | |
1514 | ||
1515 | pub unsafe trait Storage { | |
1516 | type Handle<T: ?Sized>; | |
1517 | fn create<T: ?Sized>() -> Self::Handle<T>; | |
1518 | } | |
1519 | ||
1520 | unsafe impl Storage for InlineStorage { | |
1521 | type Handle<T: ?Sized> = InlineStorageHandle<T>; | |
1522 | } | |
1523 | "#, | |
1524 | ); | |
1525 | } | |
1526 | ||
f2b60f7d FG |
1527 | #[test] |
1528 | fn gat_crash_3() { | |
2b03887a FG |
1529 | check_no_mismatches( |
1530 | r#" | |
f2b60f7d | 1531 | trait Collection { |
2b03887a FG |
1532 | type Item; |
1533 | type Member<T>: Collection<Item = T>; | |
1534 | fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>; | |
f2b60f7d FG |
1535 | } |
1536 | struct ConstGen<T, const N: usize> { | |
2b03887a | 1537 | data: [T; N], |
f2b60f7d FG |
1538 | } |
1539 | impl<T, const N: usize> Collection for ConstGen<T, N> { | |
2b03887a FG |
1540 | type Item = T; |
1541 | type Member<U> = ConstGen<U, N>; | |
f2b60f7d | 1542 | } |
2b03887a FG |
1543 | "#, |
1544 | ); | |
f2b60f7d FG |
1545 | } |
1546 | ||
064997fb FG |
1547 | #[test] |
1548 | fn cfgd_out_self_param() { | |
1549 | cov_mark::check!(cfgd_out_self_param); | |
1550 | check_no_mismatches( | |
1551 | r#" | |
1552 | struct S; | |
1553 | impl S { | |
1554 | fn f(#[cfg(never)] &self) {} | |
1555 | } | |
1556 | ||
1557 | fn f(s: S) { | |
1558 | s.f(); | |
1559 | } | |
1560 | "#, | |
1561 | ); | |
1562 | } | |
1563 | ||
1564 | #[test] | |
1565 | fn rust_161_option_clone() { | |
1566 | check_types( | |
1567 | r#" | |
1568 | //- minicore: option, drop | |
1569 | ||
1570 | fn test(o: &Option<i32>) { | |
1571 | o.my_clone(); | |
1572 | //^^^^^^^^^^^^ Option<i32> | |
1573 | } | |
1574 | ||
1575 | pub trait MyClone: Sized { | |
1576 | fn my_clone(&self) -> Self; | |
1577 | } | |
1578 | ||
1579 | impl<T> const MyClone for Option<T> | |
1580 | where | |
1581 | T: ~const MyClone + ~const Drop + ~const Destruct, | |
1582 | { | |
1583 | fn my_clone(&self) -> Self { | |
1584 | match self { | |
1585 | Some(x) => Some(x.my_clone()), | |
1586 | None => None, | |
1587 | } | |
1588 | } | |
1589 | } | |
1590 | ||
1591 | impl const MyClone for i32 { | |
1592 | fn my_clone(&self) -> Self { | |
1593 | *self | |
1594 | } | |
1595 | } | |
1596 | ||
1597 | pub trait Destruct {} | |
1598 | ||
1599 | impl<T: ?Sized> const Destruct for T {} | |
1600 | "#, | |
1601 | ); | |
1602 | } | |
1603 | ||
1604 | #[test] | |
1605 | fn rust_162_option_clone() { | |
1606 | check_types( | |
1607 | r#" | |
1608 | //- minicore: option, drop | |
1609 | ||
1610 | fn test(o: &Option<i32>) { | |
1611 | o.my_clone(); | |
1612 | //^^^^^^^^^^^^ Option<i32> | |
1613 | } | |
1614 | ||
1615 | pub trait MyClone: Sized { | |
1616 | fn my_clone(&self) -> Self; | |
1617 | } | |
1618 | ||
1619 | impl<T> const MyClone for Option<T> | |
1620 | where | |
1621 | T: ~const MyClone + ~const Destruct, | |
1622 | { | |
1623 | fn my_clone(&self) -> Self { | |
1624 | match self { | |
1625 | Some(x) => Some(x.my_clone()), | |
1626 | None => None, | |
1627 | } | |
1628 | } | |
1629 | } | |
1630 | ||
1631 | impl const MyClone for i32 { | |
1632 | fn my_clone(&self) -> Self { | |
1633 | *self | |
1634 | } | |
1635 | } | |
1636 | ||
1637 | #[lang = "destruct"] | |
1638 | pub trait Destruct {} | |
1639 | "#, | |
1640 | ); | |
1641 | } | |
1642 | ||
1643 | #[test] | |
1644 | fn tuple_struct_pattern_with_unmatched_args_crash() { | |
1645 | check_infer( | |
1646 | r#" | |
1647 | struct S(usize); | |
1648 | fn main() { | |
1649 | let S(.., a, b) = S(1); | |
1650 | let (.., a, b) = (1,); | |
1651 | } | |
1652 | "#, | |
1653 | expect![[r#" | |
1654 | 27..85 '{ ...1,); }': () | |
1655 | 37..48 'S(.., a, b)': S | |
1656 | 43..44 'a': usize | |
1657 | 46..47 'b': {unknown} | |
1658 | 51..52 'S': S(usize) -> S | |
1659 | 51..55 'S(1)': S | |
1660 | 53..54 '1': usize | |
1661 | 65..75 '(.., a, b)': (i32, {unknown}) | |
1662 | 70..71 'a': i32 | |
1663 | 73..74 'b': {unknown} | |
1664 | 78..82 '(1,)': (i32,) | |
1665 | 79..80 '1': i32 | |
1666 | "#]], | |
1667 | ); | |
1668 | } | |
f2b60f7d FG |
1669 | |
1670 | #[test] | |
1671 | fn trailing_empty_macro() { | |
1672 | check_no_mismatches( | |
1673 | r#" | |
1674 | macro_rules! m2 { | |
1675 | ($($t:tt)*) => {$($t)*}; | |
1676 | } | |
1677 | ||
1678 | fn macrostmts() -> u8 { | |
1679 | m2! { 0 } | |
1680 | m2! {} | |
1681 | } | |
1682 | "#, | |
1683 | ); | |
1684 | } | |
2b03887a FG |
1685 | |
1686 | #[test] | |
1687 | fn dyn_with_unresolved_trait() { | |
1688 | check_types( | |
1689 | r#" | |
1690 | fn foo(a: &dyn DoesNotExist) { | |
1691 | a.bar(); | |
1692 | //^&{unknown} | |
1693 | } | |
1694 | "#, | |
1695 | ); | |
1696 | } | |
1697 | ||
1698 | #[test] | |
1699 | fn self_assoc_with_const_generics_crash() { | |
1700 | check_no_mismatches( | |
1701 | r#" | |
1702 | trait Trait { type Item; } | |
1703 | impl<T, const N: usize> Trait for [T; N] { | |
1704 | type Item = (); | |
1705 | fn f<U>(_: Self::Item) {} | |
1706 | } | |
1707 | "#, | |
1708 | ); | |
1709 | } | |
487cf647 FG |
1710 | |
1711 | #[test] | |
1712 | fn unsize_array_with_inference_variable() { | |
1713 | check_types( | |
1714 | r#" | |
1715 | //- minicore: try, slice | |
1716 | use core::ops::ControlFlow; | |
1717 | fn foo() -> ControlFlow<(), [usize; 1]> { loop {} } | |
1718 | fn bar() -> ControlFlow<(), ()> { | |
1719 | let a = foo()?.len(); | |
1720 | //^ usize | |
1721 | ControlFlow::Continue(()) | |
1722 | } | |
1723 | "#, | |
1724 | ); | |
1725 | } | |
9c376795 FG |
1726 | |
1727 | #[test] | |
1728 | fn assoc_type_shorthand_with_gats_in_binders() { | |
1729 | // c.f. test `issue_4885()` | |
1730 | check_no_mismatches( | |
1731 | r#" | |
1732 | trait Gats { | |
1733 | type Assoc<T>; | |
1734 | } | |
1735 | trait Foo<T> {} | |
1736 | ||
1737 | struct Bar<'a, B: Gats, A> { | |
1738 | field: &'a dyn Foo<B::Assoc<A>>, | |
1739 | } | |
1740 | ||
1741 | fn foo(b: Bar) { | |
1742 | let _ = b.field; | |
1743 | } | |
1744 | "#, | |
1745 | ); | |
1746 | } | |
353b0b11 FG |
1747 | |
1748 | #[test] | |
1749 | fn regression_14305() { | |
1750 | check_no_mismatches( | |
1751 | r#" | |
1752 | //- minicore: add | |
1753 | trait Tr {} | |
1754 | impl Tr for [u8; C] {} | |
1755 | const C: usize = 2 + 2; | |
1756 | "#, | |
1757 | ); | |
1758 | } | |
1759 | ||
1760 | #[test] | |
1761 | fn regression_14164() { | |
1762 | check_types( | |
1763 | r#" | |
1764 | trait Rec { | |
1765 | type K; | |
1766 | type Rebind<Tok>: Rec<K = Tok>; | |
1767 | } | |
1768 | ||
1769 | trait Expr<K> { | |
1770 | type Part: Rec<K = K>; | |
1771 | fn foo(_: <Self::Part as Rec>::Rebind<i32>) {} | |
1772 | } | |
1773 | ||
1774 | struct Head<K>(K); | |
1775 | impl<K> Rec for Head<K> { | |
1776 | type K = K; | |
1777 | type Rebind<Tok> = Head<Tok>; | |
1778 | } | |
1779 | ||
1780 | fn test<E>() | |
1781 | where | |
1782 | E: Expr<usize, Part = Head<usize>>, | |
1783 | { | |
1784 | let head; | |
1785 | //^^^^ Head<i32> | |
1786 | E::foo(head); | |
1787 | } | |
1788 | "#, | |
1789 | ); | |
1790 | } |