diff options
author | Igor Aleksanov <[email protected]> | 2020-08-14 05:34:07 +0100 |
---|---|---|
committer | Igor Aleksanov <[email protected]> | 2020-08-14 05:34:07 +0100 |
commit | c26c911ec1e6c2ad1dcb7d155a6a1d528839ad1a (patch) | |
tree | 7cff36c38234be0afb65273146d8247083a5cfeb /crates/hir_ty/src/tests/regression.rs | |
parent | 3c018bf84de5c693b5ee1c6bec0fed3b201c2060 (diff) | |
parent | f1f73649a686dc6e6449afc35e0fa6fed00e225d (diff) |
Merge branch 'master' into add-disable-diagnostics
Diffstat (limited to 'crates/hir_ty/src/tests/regression.rs')
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs new file mode 100644 index 000000000..b9ab0f357 --- /dev/null +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -0,0 +1,842 @@ | |||
1 | use expect::expect; | ||
2 | use test_utils::mark; | ||
3 | |||
4 | use super::{check_infer, check_types}; | ||
5 | |||
6 | #[test] | ||
7 | fn bug_484() { | ||
8 | check_infer( | ||
9 | r#" | ||
10 | fn test() { | ||
11 | let x = if true {}; | ||
12 | } | ||
13 | "#, | ||
14 | expect![[r#" | ||
15 | 10..37 '{ ... {}; }': () | ||
16 | 20..21 'x': () | ||
17 | 24..34 'if true {}': () | ||
18 | 27..31 'true': bool | ||
19 | 32..34 '{}': () | ||
20 | "#]], | ||
21 | ); | ||
22 | } | ||
23 | |||
24 | #[test] | ||
25 | fn no_panic_on_field_of_enum() { | ||
26 | check_infer( | ||
27 | r#" | ||
28 | enum X {} | ||
29 | |||
30 | fn test(x: X) { | ||
31 | x.some_field; | ||
32 | } | ||
33 | "#, | ||
34 | expect![[r#" | ||
35 | 19..20 'x': X | ||
36 | 25..46 '{ ...eld; }': () | ||
37 | 31..32 'x': X | ||
38 | 31..43 'x.some_field': {unknown} | ||
39 | "#]], | ||
40 | ); | ||
41 | } | ||
42 | |||
43 | #[test] | ||
44 | fn bug_585() { | ||
45 | check_infer( | ||
46 | r#" | ||
47 | fn test() { | ||
48 | X {}; | ||
49 | match x { | ||
50 | A::B {} => (), | ||
51 | A::Y() => (), | ||
52 | } | ||
53 | } | ||
54 | "#, | ||
55 | expect![[r#" | ||
56 | 10..88 '{ ... } }': () | ||
57 | 16..20 'X {}': {unknown} | ||
58 | 26..86 'match ... }': () | ||
59 | 32..33 'x': {unknown} | ||
60 | 44..51 'A::B {}': {unknown} | ||
61 | 55..57 '()': () | ||
62 | 67..73 'A::Y()': {unknown} | ||
63 | 77..79 '()': () | ||
64 | "#]], | ||
65 | ); | ||
66 | } | ||
67 | |||
68 | #[test] | ||
69 | fn bug_651() { | ||
70 | check_infer( | ||
71 | r#" | ||
72 | fn quux() { | ||
73 | let y = 92; | ||
74 | 1 + y; | ||
75 | } | ||
76 | "#, | ||
77 | expect![[r#" | ||
78 | 10..40 '{ ...+ y; }': () | ||
79 | 20..21 'y': i32 | ||
80 | 24..26 '92': i32 | ||
81 | 32..33 '1': i32 | ||
82 | 32..37 '1 + y': i32 | ||
83 | 36..37 'y': i32 | ||
84 | "#]], | ||
85 | ); | ||
86 | } | ||
87 | |||
88 | #[test] | ||
89 | fn recursive_vars() { | ||
90 | mark::check!(type_var_cycles_resolve_completely); | ||
91 | mark::check!(type_var_cycles_resolve_as_possible); | ||
92 | check_infer( | ||
93 | r#" | ||
94 | fn test() { | ||
95 | let y = unknown; | ||
96 | [y, &y]; | ||
97 | } | ||
98 | "#, | ||
99 | expect![[r#" | ||
100 | 10..47 '{ ...&y]; }': () | ||
101 | 20..21 'y': &{unknown} | ||
102 | 24..31 'unknown': &{unknown} | ||
103 | 37..44 '[y, &y]': [&&{unknown}; _] | ||
104 | 38..39 'y': &{unknown} | ||
105 | 41..43 '&y': &&{unknown} | ||
106 | 42..43 'y': &{unknown} | ||
107 | "#]], | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn recursive_vars_2() { | ||
113 | check_infer( | ||
114 | r#" | ||
115 | fn test() { | ||
116 | let x = unknown; | ||
117 | let y = unknown; | ||
118 | [(x, y), (&y, &x)]; | ||
119 | } | ||
120 | "#, | ||
121 | expect![[r#" | ||
122 | 10..79 '{ ...x)]; }': () | ||
123 | 20..21 'x': &&{unknown} | ||
124 | 24..31 'unknown': &&{unknown} | ||
125 | 41..42 'y': &&{unknown} | ||
126 | 45..52 'unknown': &&{unknown} | ||
127 | 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] | ||
128 | 59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) | ||
129 | 60..61 'x': &&{unknown} | ||
130 | 63..64 'y': &&{unknown} | ||
131 | 67..75 '(&y, &x)': (&&&{unknown}, &&&{unknown}) | ||
132 | 68..70 '&y': &&&{unknown} | ||
133 | 69..70 'y': &&{unknown} | ||
134 | 72..74 '&x': &&&{unknown} | ||
135 | 73..74 'x': &&{unknown} | ||
136 | "#]], | ||
137 | ); | ||
138 | } | ||
139 | |||
140 | #[test] | ||
141 | fn infer_std_crash_1() { | ||
142 | // caused stack overflow, taken from std | ||
143 | check_infer( | ||
144 | r#" | ||
145 | enum Maybe<T> { | ||
146 | Real(T), | ||
147 | Fake, | ||
148 | } | ||
149 | |||
150 | fn write() { | ||
151 | match something_unknown { | ||
152 | Maybe::Real(ref mut something) => (), | ||
153 | } | ||
154 | } | ||
155 | "#, | ||
156 | expect![[r#" | ||
157 | 53..138 '{ ... } }': () | ||
158 | 59..136 'match ... }': () | ||
159 | 65..82 'someth...nknown': Maybe<{unknown}> | ||
160 | 93..123 'Maybe:...thing)': Maybe<{unknown}> | ||
161 | 105..122 'ref mu...ething': &mut {unknown} | ||
162 | 127..129 '()': () | ||
163 | "#]], | ||
164 | ); | ||
165 | } | ||
166 | |||
167 | #[test] | ||
168 | fn infer_std_crash_2() { | ||
169 | mark::check!(type_var_resolves_to_int_var); | ||
170 | // caused "equating two type variables, ...", taken from std | ||
171 | check_infer( | ||
172 | r#" | ||
173 | fn test_line_buffer() { | ||
174 | &[0, b'\n', 1, b'\n']; | ||
175 | } | ||
176 | "#, | ||
177 | expect![[r#" | ||
178 | 22..52 '{ ...n']; }': () | ||
179 | 28..49 '&[0, b...b'\n']': &[u8; _] | ||
180 | 29..49 '[0, b'...b'\n']': [u8; _] | ||
181 | 30..31 '0': u8 | ||
182 | 33..38 'b'\n'': u8 | ||
183 | 40..41 '1': u8 | ||
184 | 43..48 'b'\n'': u8 | ||
185 | "#]], | ||
186 | ); | ||
187 | } | ||
188 | |||
189 | #[test] | ||
190 | fn infer_std_crash_3() { | ||
191 | // taken from rustc | ||
192 | check_infer( | ||
193 | r#" | ||
194 | pub fn compute() { | ||
195 | match nope!() { | ||
196 | SizeSkeleton::Pointer { non_zero: true, tail } => {} | ||
197 | } | ||
198 | } | ||
199 | "#, | ||
200 | expect![[r#" | ||
201 | 17..107 '{ ... } }': () | ||
202 | 23..105 'match ... }': () | ||
203 | 29..36 'nope!()': {unknown} | ||
204 | 47..93 'SizeSk...tail }': {unknown} | ||
205 | 81..85 'true': bool | ||
206 | 81..85 'true': bool | ||
207 | 87..91 'tail': {unknown} | ||
208 | 97..99 '{}': () | ||
209 | "#]], | ||
210 | ); | ||
211 | } | ||
212 | |||
213 | #[test] | ||
214 | fn infer_std_crash_4() { | ||
215 | // taken from rustc | ||
216 | check_infer( | ||
217 | r#" | ||
218 | pub fn primitive_type() { | ||
219 | match *self { | ||
220 | BorrowedRef { type_: Primitive(p), ..} => {}, | ||
221 | } | ||
222 | } | ||
223 | "#, | ||
224 | expect![[r#" | ||
225 | 24..105 '{ ... } }': () | ||
226 | 30..103 'match ... }': () | ||
227 | 36..41 '*self': {unknown} | ||
228 | 37..41 'self': {unknown} | ||
229 | 52..90 'Borrow...), ..}': {unknown} | ||
230 | 73..85 'Primitive(p)': {unknown} | ||
231 | 83..84 'p': {unknown} | ||
232 | 94..96 '{}': () | ||
233 | "#]], | ||
234 | ); | ||
235 | } | ||
236 | |||
237 | #[test] | ||
238 | fn infer_std_crash_5() { | ||
239 | // taken from rustc | ||
240 | check_infer( | ||
241 | r#" | ||
242 | fn extra_compiler_flags() { | ||
243 | for content in doesnt_matter { | ||
244 | let name = if doesnt_matter { | ||
245 | first | ||
246 | } else { | ||
247 | &content | ||
248 | }; | ||
249 | |||
250 | let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { | ||
251 | name | ||
252 | } else { | ||
253 | content | ||
254 | }; | ||
255 | } | ||
256 | } | ||
257 | "#, | ||
258 | expect![[r#" | ||
259 | 26..322 '{ ... } }': () | ||
260 | 32..320 'for co... }': () | ||
261 | 36..43 'content': &{unknown} | ||
262 | 47..60 'doesnt_matter': {unknown} | ||
263 | 61..320 '{ ... }': () | ||
264 | 75..79 'name': &&{unknown} | ||
265 | 82..166 'if doe... }': &&{unknown} | ||
266 | 85..98 'doesnt_matter': bool | ||
267 | 99..128 '{ ... }': &&{unknown} | ||
268 | 113..118 'first': &&{unknown} | ||
269 | 134..166 '{ ... }': &&{unknown} | ||
270 | 148..156 '&content': &&{unknown} | ||
271 | 149..156 'content': &{unknown} | ||
272 | 181..188 'content': &{unknown} | ||
273 | 191..313 'if ICE... }': &{unknown} | ||
274 | 194..231 'ICE_RE..._VALUE': {unknown} | ||
275 | 194..247 'ICE_RE...&name)': bool | ||
276 | 241..246 '&name': &&&{unknown} | ||
277 | 242..246 'name': &&{unknown} | ||
278 | 248..276 '{ ... }': &&{unknown} | ||
279 | 262..266 'name': &&{unknown} | ||
280 | 282..313 '{ ... }': &{unknown} | ||
281 | 296..303 'content': &{unknown} | ||
282 | "#]], | ||
283 | ); | ||
284 | } | ||
285 | |||
286 | #[test] | ||
287 | fn infer_nested_generics_crash() { | ||
288 | // another crash found typechecking rustc | ||
289 | check_infer( | ||
290 | r#" | ||
291 | struct Canonical<V> { | ||
292 | value: V, | ||
293 | } | ||
294 | struct QueryResponse<V> { | ||
295 | value: V, | ||
296 | } | ||
297 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { | ||
298 | &query_response.value; | ||
299 | } | ||
300 | "#, | ||
301 | expect![[r#" | ||
302 | 91..105 'query_response': Canonical<QueryResponse<R>> | ||
303 | 136..166 '{ ...lue; }': () | ||
304 | 142..163 '&query....value': &QueryResponse<R> | ||
305 | 143..157 'query_response': Canonical<QueryResponse<R>> | ||
306 | 143..163 'query_....value': QueryResponse<R> | ||
307 | "#]], | ||
308 | ); | ||
309 | } | ||
310 | |||
311 | #[test] | ||
312 | fn infer_paren_macro_call() { | ||
313 | check_infer( | ||
314 | r#" | ||
315 | macro_rules! bar { () => {0u32} } | ||
316 | fn test() { | ||
317 | let a = (bar!()); | ||
318 | } | ||
319 | "#, | ||
320 | expect![[r#" | ||
321 | !0..4 '0u32': u32 | ||
322 | 44..69 '{ ...()); }': () | ||
323 | 54..55 'a': u32 | ||
324 | "#]], | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | #[test] | ||
329 | fn bug_1030() { | ||
330 | check_infer( | ||
331 | r#" | ||
332 | struct HashSet<T, H>; | ||
333 | struct FxHasher; | ||
334 | type FxHashSet<T> = HashSet<T, FxHasher>; | ||
335 | |||
336 | impl<T, H> HashSet<T, H> { | ||
337 | fn default() -> HashSet<T, H> {} | ||
338 | } | ||
339 | |||
340 | pub fn main_loop() { | ||
341 | FxHashSet::default(); | ||
342 | } | ||
343 | "#, | ||
344 | expect![[r#" | ||
345 | 143..145 '{}': () | ||
346 | 168..197 '{ ...t(); }': () | ||
347 | 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> | ||
348 | 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> | ||
349 | "#]], | ||
350 | ); | ||
351 | } | ||
352 | |||
353 | #[test] | ||
354 | fn issue_2669() { | ||
355 | check_infer( | ||
356 | r#" | ||
357 | trait A {} | ||
358 | trait Write {} | ||
359 | struct Response<T> {} | ||
360 | |||
361 | trait D { | ||
362 | fn foo(); | ||
363 | } | ||
364 | |||
365 | impl<T:A> D for Response<T> { | ||
366 | fn foo() { | ||
367 | end(); | ||
368 | fn end<W: Write>() { | ||
369 | let _x: T = loop {}; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | "#, | ||
374 | expect![[r#" | ||
375 | 119..214 '{ ... }': () | ||
376 | 129..132 'end': fn end<{unknown}>() | ||
377 | 129..134 'end()': () | ||
378 | 163..208 '{ ... }': () | ||
379 | 181..183 '_x': ! | ||
380 | 190..197 'loop {}': ! | ||
381 | 195..197 '{}': () | ||
382 | "#]], | ||
383 | ) | ||
384 | } | ||
385 | |||
386 | #[test] | ||
387 | fn issue_2705() { | ||
388 | check_infer( | ||
389 | r#" | ||
390 | trait Trait {} | ||
391 | fn test() { | ||
392 | <Trait<u32>>::foo() | ||
393 | } | ||
394 | "#, | ||
395 | expect![[r#" | ||
396 | 25..52 '{ ...oo() }': () | ||
397 | 31..48 '<Trait...>::foo': {unknown} | ||
398 | 31..50 '<Trait...:foo()': () | ||
399 | "#]], | ||
400 | ); | ||
401 | } | ||
402 | |||
403 | #[test] | ||
404 | fn issue_2683_chars_impl() { | ||
405 | check_types( | ||
406 | r#" | ||
407 | //- /main.rs crate:main deps:std | ||
408 | fn test() { | ||
409 | let chars: std::str::Chars<'_>; | ||
410 | (chars.next(), chars.nth(1)); | ||
411 | } //^ (Option<char>, Option<char>) | ||
412 | |||
413 | //- /std.rs crate:std | ||
414 | #[prelude_import] | ||
415 | use prelude::*; | ||
416 | |||
417 | pub mod prelude { | ||
418 | pub use crate::iter::Iterator; | ||
419 | pub use crate::option::Option; | ||
420 | } | ||
421 | |||
422 | pub mod iter { | ||
423 | pub use self::traits::Iterator; | ||
424 | pub mod traits { | ||
425 | pub use self::iterator::Iterator; | ||
426 | |||
427 | pub mod iterator { | ||
428 | pub trait Iterator { | ||
429 | type Item; | ||
430 | fn next(&mut self) -> Option<Self::Item>; | ||
431 | fn nth(&mut self, n: usize) -> Option<Self::Item> {} | ||
432 | } | ||
433 | } | ||
434 | } | ||
435 | } | ||
436 | |||
437 | pub mod option { | ||
438 | pub enum Option<T> {} | ||
439 | } | ||
440 | |||
441 | pub mod str { | ||
442 | pub struct Chars<'a> {} | ||
443 | impl<'a> Iterator for Chars<'a> { | ||
444 | type Item = char; | ||
445 | fn next(&mut self) -> Option<char> {} | ||
446 | } | ||
447 | } | ||
448 | "#, | ||
449 | ); | ||
450 | } | ||
451 | |||
452 | #[test] | ||
453 | fn issue_3642_bad_macro_stackover() { | ||
454 | check_types( | ||
455 | r#" | ||
456 | #[macro_export] | ||
457 | macro_rules! match_ast { | ||
458 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
459 | |||
460 | (match ($node:expr) { | ||
461 | $( ast::$ast:ident($it:ident) => $res:expr, )* | ||
462 | _ => $catch_all:expr $(,)? | ||
463 | }) => {{ | ||
464 | $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )* | ||
465 | { $catch_all } | ||
466 | }}; | ||
467 | } | ||
468 | |||
469 | fn main() { | ||
470 | let anchor = match_ast! { | ||
471 | //^ () | ||
472 | match parent { | ||
473 | as => {}, | ||
474 | _ => return None | ||
475 | } | ||
476 | }; | ||
477 | }"#, | ||
478 | ); | ||
479 | } | ||
480 | |||
481 | #[test] | ||
482 | fn issue_3999_slice() { | ||
483 | check_infer( | ||
484 | r#" | ||
485 | fn foo(params: &[usize]) { | ||
486 | match params { | ||
487 | [ps @ .., _] => {} | ||
488 | } | ||
489 | } | ||
490 | "#, | ||
491 | expect![[r#" | ||
492 | 7..13 'params': &[usize] | ||
493 | 25..80 '{ ... } }': () | ||
494 | 31..78 'match ... }': () | ||
495 | 37..43 'params': &[usize] | ||
496 | 54..66 '[ps @ .., _]': [usize] | ||
497 | 55..62 'ps @ ..': &[usize] | ||
498 | 60..62 '..': [usize] | ||
499 | 64..65 '_': usize | ||
500 | 70..72 '{}': () | ||
501 | "#]], | ||
502 | ); | ||
503 | } | ||
504 | |||
505 | #[test] | ||
506 | fn issue_3999_struct() { | ||
507 | // rust-analyzer should not panic on seeing this malformed | ||
508 | // record pattern. | ||
509 | check_infer( | ||
510 | r#" | ||
511 | struct Bar { | ||
512 | a: bool, | ||
513 | } | ||
514 | fn foo(b: Bar) { | ||
515 | match b { | ||
516 | Bar { a: .. } => {}, | ||
517 | } | ||
518 | } | ||
519 | "#, | ||
520 | expect![[r#" | ||
521 | 35..36 'b': Bar | ||
522 | 43..95 '{ ... } }': () | ||
523 | 49..93 'match ... }': () | ||
524 | 55..56 'b': Bar | ||
525 | 67..80 'Bar { a: .. }': Bar | ||
526 | 76..78 '..': bool | ||
527 | 84..86 '{}': () | ||
528 | "#]], | ||
529 | ); | ||
530 | } | ||
531 | |||
532 | #[test] | ||
533 | fn issue_4235_name_conflicts() { | ||
534 | check_infer( | ||
535 | r#" | ||
536 | struct FOO {} | ||
537 | static FOO:FOO = FOO {}; | ||
538 | |||
539 | impl FOO { | ||
540 | fn foo(&self) {} | ||
541 | } | ||
542 | |||
543 | fn main() { | ||
544 | let a = &FOO; | ||
545 | a.foo(); | ||
546 | } | ||
547 | "#, | ||
548 | expect![[r#" | ||
549 | 31..37 'FOO {}': FOO | ||
550 | 63..67 'self': &FOO | ||
551 | 69..71 '{}': () | ||
552 | 85..119 '{ ...o(); }': () | ||
553 | 95..96 'a': &FOO | ||
554 | 99..103 '&FOO': &FOO | ||
555 | 100..103 'FOO': FOO | ||
556 | 109..110 'a': &FOO | ||
557 | 109..116 'a.foo()': () | ||
558 | "#]], | ||
559 | ); | ||
560 | } | ||
561 | |||
562 | #[test] | ||
563 | fn issue_4465_dollar_crate_at_type() { | ||
564 | check_infer( | ||
565 | r#" | ||
566 | pub struct Foo {} | ||
567 | pub fn anything<T>() -> T { | ||
568 | loop {} | ||
569 | } | ||
570 | macro_rules! foo { | ||
571 | () => {{ | ||
572 | let r: $crate::Foo = anything(); | ||
573 | r | ||
574 | }}; | ||
575 | } | ||
576 | fn main() { | ||
577 | let _a = foo!(); | ||
578 | } | ||
579 | "#, | ||
580 | expect![[r#" | ||
581 | 44..59 '{ loop {} }': T | ||
582 | 50..57 'loop {}': ! | ||
583 | 55..57 '{}': () | ||
584 | !0..31 '{letr:...g();r}': Foo | ||
585 | !4..5 'r': Foo | ||
586 | !18..26 'anything': fn anything<Foo>() -> Foo | ||
587 | !18..28 'anything()': Foo | ||
588 | !29..30 'r': Foo | ||
589 | 163..187 '{ ...!(); }': () | ||
590 | 173..175 '_a': Foo | ||
591 | "#]], | ||
592 | ); | ||
593 | } | ||
594 | |||
595 | #[test] | ||
596 | fn issue_4053_diesel_where_clauses() { | ||
597 | check_infer( | ||
598 | r#" | ||
599 | trait BoxedDsl<DB> { | ||
600 | type Output; | ||
601 | fn internal_into_boxed(self) -> Self::Output; | ||
602 | } | ||
603 | |||
604 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | ||
605 | order: Order, | ||
606 | } | ||
607 | |||
608 | trait QueryFragment<DB: Backend> {} | ||
609 | |||
610 | trait Into<T> { fn into(self) -> T; } | ||
611 | |||
612 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | ||
613 | for SelectStatement<F, S, D, W, O, LOf, G> | ||
614 | where | ||
615 | O: Into<dyn QueryFragment<DB>>, | ||
616 | { | ||
617 | type Output = XXX; | ||
618 | |||
619 | fn internal_into_boxed(self) -> Self::Output { | ||
620 | self.order.into(); | ||
621 | } | ||
622 | } | ||
623 | "#, | ||
624 | expect![[r#" | ||
625 | 65..69 'self': Self | ||
626 | 267..271 'self': Self | ||
627 | 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
628 | 488..522 '{ ... }': () | ||
629 | 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
630 | 498..508 'self.order': O | ||
631 | 498..515 'self.o...into()': dyn QueryFragment<DB> | ||
632 | "#]], | ||
633 | ); | ||
634 | } | ||
635 | |||
636 | #[test] | ||
637 | fn issue_4953() { | ||
638 | check_infer( | ||
639 | r#" | ||
640 | pub struct Foo(pub i64); | ||
641 | impl Foo { | ||
642 | fn test() -> Self { Self(0i64) } | ||
643 | } | ||
644 | "#, | ||
645 | expect![[r#" | ||
646 | 58..72 '{ Self(0i64) }': Foo | ||
647 | 60..64 'Self': Foo(i64) -> Foo | ||
648 | 60..70 'Self(0i64)': Foo | ||
649 | 65..69 '0i64': i64 | ||
650 | "#]], | ||
651 | ); | ||
652 | check_infer( | ||
653 | r#" | ||
654 | pub struct Foo<T>(pub T); | ||
655 | impl Foo<i64> { | ||
656 | fn test() -> Self { Self(0i64) } | ||
657 | } | ||
658 | "#, | ||
659 | expect![[r#" | ||
660 | 64..78 '{ Self(0i64) }': Foo<i64> | ||
661 | 66..70 'Self': Foo<i64>(i64) -> Foo<i64> | ||
662 | 66..76 'Self(0i64)': Foo<i64> | ||
663 | 71..75 '0i64': i64 | ||
664 | "#]], | ||
665 | ); | ||
666 | } | ||
667 | |||
668 | #[test] | ||
669 | fn issue_4931() { | ||
670 | check_infer( | ||
671 | r#" | ||
672 | trait Div<T> { | ||
673 | type Output; | ||
674 | } | ||
675 | |||
676 | trait CheckedDiv: Div<()> {} | ||
677 | |||
678 | trait PrimInt: CheckedDiv<Output = ()> { | ||
679 | fn pow(self); | ||
680 | } | ||
681 | |||
682 | fn check<T: PrimInt>(i: T) { | ||
683 | i.pow(); | ||
684 | } | ||
685 | "#, | ||
686 | expect![[r#" | ||
687 | 117..121 'self': Self | ||
688 | 148..149 'i': T | ||
689 | 154..170 '{ ...w(); }': () | ||
690 | 160..161 'i': T | ||
691 | 160..167 'i.pow()': () | ||
692 | "#]], | ||
693 | ); | ||
694 | } | ||
695 | |||
696 | #[test] | ||
697 | fn issue_4885() { | ||
698 | check_infer( | ||
699 | r#" | ||
700 | #[lang = "coerce_unsized"] | ||
701 | pub trait CoerceUnsized<T> {} | ||
702 | |||
703 | trait Future { | ||
704 | type Output; | ||
705 | } | ||
706 | trait Foo<R> { | ||
707 | type Bar; | ||
708 | } | ||
709 | fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> | ||
710 | where | ||
711 | K: Foo<R>, | ||
712 | { | ||
713 | bar(key) | ||
714 | } | ||
715 | fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> | ||
716 | where | ||
717 | K: Foo<R>, | ||
718 | { | ||
719 | } | ||
720 | "#, | ||
721 | expect![[r#" | ||
722 | 136..139 'key': &K | ||
723 | 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> | ||
724 | 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> | ||
725 | 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> | ||
726 | 208..211 'key': &K | ||
727 | 228..231 'key': &K | ||
728 | 290..293 '{ }': () | ||
729 | "#]], | ||
730 | ); | ||
731 | } | ||
732 | |||
733 | #[test] | ||
734 | fn issue_4800() { | ||
735 | check_infer( | ||
736 | r#" | ||
737 | trait Debug {} | ||
738 | |||
739 | struct Foo<T>; | ||
740 | |||
741 | type E1<T> = (T, T, T); | ||
742 | type E2<T> = E1<E1<E1<(T, T, T)>>>; | ||
743 | |||
744 | impl Debug for Foo<E2<()>> {} | ||
745 | |||
746 | struct Request; | ||
747 | |||
748 | pub trait Future { | ||
749 | type Output; | ||
750 | } | ||
751 | |||
752 | pub struct PeerSet<D>; | ||
753 | |||
754 | impl<D> Service<Request> for PeerSet<D> | ||
755 | where | ||
756 | D: Discover, | ||
757 | D::Key: Debug, | ||
758 | { | ||
759 | type Error = (); | ||
760 | type Future = dyn Future<Output = Self::Error>; | ||
761 | |||
762 | fn call(&mut self) -> Self::Future { | ||
763 | loop {} | ||
764 | } | ||
765 | } | ||
766 | |||
767 | pub trait Discover { | ||
768 | type Key; | ||
769 | } | ||
770 | |||
771 | pub trait Service<Request> { | ||
772 | type Error; | ||
773 | type Future: Future<Output = Self::Error>; | ||
774 | fn call(&mut self) -> Self::Future; | ||
775 | } | ||
776 | "#, | ||
777 | expect![[r#" | ||
778 | 379..383 'self': &mut PeerSet<D> | ||
779 | 401..424 '{ ... }': dyn Future<Output = ()> | ||
780 | 411..418 'loop {}': ! | ||
781 | 416..418 '{}': () | ||
782 | 575..579 'self': &mut Self | ||
783 | "#]], | ||
784 | ); | ||
785 | } | ||
786 | |||
787 | #[test] | ||
788 | fn issue_4966() { | ||
789 | check_infer( | ||
790 | r#" | ||
791 | pub trait IntoIterator { | ||
792 | type Item; | ||
793 | } | ||
794 | |||
795 | struct Repeat<A> { element: A } | ||
796 | |||
797 | struct Map<F> { f: F } | ||
798 | |||
799 | struct Vec<T> {} | ||
800 | |||
801 | #[lang = "deref"] | ||
802 | pub trait Deref { | ||
803 | type Target; | ||
804 | } | ||
805 | |||
806 | impl<T> Deref for Vec<T> { | ||
807 | type Target = [T]; | ||
808 | } | ||
809 | |||
810 | fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} | ||
811 | |||
812 | fn main() { | ||
813 | let inner = Map { f: |_: &f64| 0.0 }; | ||
814 | |||
815 | let repeat = Repeat { element: inner }; | ||
816 | |||
817 | let vec = from_iter(repeat); | ||
818 | |||
819 | vec.foo_bar(); | ||
820 | } | ||
821 | "#, | ||
822 | expect![[r#" | ||
823 | 270..274 'iter': T | ||
824 | 289..291 '{}': () | ||
825 | 303..447 '{ ...r(); }': () | ||
826 | 313..318 'inner': Map<|&f64| -> f64> | ||
827 | 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> | ||
828 | 330..343 '|_: &f64| 0.0': |&f64| -> f64 | ||
829 | 331..332 '_': &f64 | ||
830 | 340..343 '0.0': f64 | ||
831 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> | ||
832 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> | ||
833 | 383..388 'inner': Map<|&f64| -> f64> | ||
834 | 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
835 | 407..416 '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>>>> | ||
836 | 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
837 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> | ||
838 | 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
839 | 431..444 'vec.foo_bar()': {unknown} | ||
840 | "#]], | ||
841 | ); | ||
842 | } | ||