| mod new_solver; | |
| use expect_test::expect; | |
| use crate::tests::check; | |
| use super::{check_infer, check_no_mismatches, check_types}; | |
| #[test] | |
| fn closure_in_enum_discriminant_does_not_panic() { | |
| check( | |
| r#" | |
| enum Enum { X = || {} } | |
| // ^^^^^ expected isize, got impl Fn() | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn bug_484() { | |
| check_infer( | |
| r#" | |
| fn test() { | |
| let x = if true {}; | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..37 '{ ... {}; }': () | |
| 20..21 'x': () | |
| 24..34 'if true {}': () | |
| 27..31 'true': bool | |
| 32..34 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn no_panic_on_field_of_enum() { | |
| check_infer( | |
| r#" | |
| enum X {} | |
| fn test(x: X) { | |
| x.some_field; | |
| } | |
| "#, | |
| expect![[r#" | |
| 19..20 'x': X | |
| 25..46 '{ ...eld; }': () | |
| 31..32 'x': X | |
| 31..43 'x.some_field': {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn anon_const_projection_in_impl_predicate() { | |
| check_no_mismatches( | |
| r#" | |
| trait Trait { | |
| type Assoc; | |
| } | |
| struct S<const N: usize>; | |
| impl<const N: usize> S<N> | |
| where | |
| S<{ N }>: Trait, | |
| { | |
| fn new(_: <S<N> as Trait>::Assoc) {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn bug_585() { | |
| check_infer( | |
| r#" | |
| fn test() { | |
| X {}; | |
| match x { | |
| A::B {} => (), | |
| A::Y() => (), | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..88 '{ ... } }': () | |
| 16..20 'X {}': {unknown} | |
| 26..86 'match ... }': () | |
| 32..33 'x': {unknown} | |
| 44..51 'A::B {}': {unknown} | |
| 55..57 '()': () | |
| 67..73 'A::Y()': {unknown} | |
| 77..79 '()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn bug_651() { | |
| check_infer( | |
| r#" | |
| fn quux() { | |
| let y = 92; | |
| 1 + y; | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..40 '{ ...+ y; }': () | |
| 20..21 'y': i32 | |
| 24..26 '92': i32 | |
| 32..33 '1': i32 | |
| 32..37 '1 + y': i32 | |
| 36..37 'y': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn recursive_vars() { | |
| // FIXME: This isn't nice, but I guess as long as we don't hang/crash that's fine? | |
| check_infer( | |
| r#" | |
| fn test() { | |
| let y = unknown; | |
| [y, &y]; | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..47 '{ ...&y]; }': () | |
| 20..21 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 24..31 'unknown': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 37..44 '[y, &y]': [&'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}; 2] | |
| 38..39 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 41..43 '&y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 42..43 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn recursive_vars_2() { | |
| check_infer( | |
| r#" | |
| fn test() { | |
| let x = unknown; | |
| let y = unknown; | |
| [(x, y), (&y, &x)]; | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..79 '{ ...x)]; }': () | |
| 20..21 'x': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 24..31 'unknown': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 41..42 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 45..52 'unknown': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 58..76 '[(x, y..., &x)]': [(&'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}, &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}); 2] | |
| 59..65 '(x, y)': (&'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}, &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}) | |
| 60..61 'x': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 63..64 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 67..75 '(&y, &x)': (&'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}, &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}) | |
| 68..70 '&y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 69..70 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 72..74 '&x': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 73..74 'x': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn array_elements_expected_type() { | |
| check_no_mismatches( | |
| r#" | |
| fn test() { | |
| let x: [[u32; 2]; 2] = [[1, 2], [3, 4]]; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn infer_std_crash_1() { | |
| // caused stack overflow, taken from std | |
| check_infer( | |
| r#" | |
| enum Maybe<T> { | |
| Real(T), | |
| Fake, | |
| } | |
| fn write() { | |
| match something_unknown { | |
| Maybe::Real(ref mut something) => (), | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 53..138 '{ ... } }': () | |
| 59..136 'match ... }': () | |
| 65..82 'someth...nknown': Maybe<{unknown}> | |
| 93..123 'Maybe:...thing)': Maybe<{unknown}> | |
| 105..122 'ref mu...ething': &'? mut {unknown} | |
| 127..129 '()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_std_crash_2() { | |
| // caused "equating two type variables, ...", taken from std | |
| check_infer( | |
| r#" | |
| fn test_line_buffer() { | |
| &[0, b'\n', 1, b'\n']; | |
| } | |
| "#, | |
| expect![[r#" | |
| 22..52 '{ ...n']; }': () | |
| 28..49 '&[0, b...b'\n']': &'? [u8; 4] | |
| 29..49 '[0, b'...b'\n']': [u8; 4] | |
| 30..31 '0': u8 | |
| 33..38 'b'\n'': u8 | |
| 40..41 '1': u8 | |
| 43..48 'b'\n'': u8 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_std_crash_3() { | |
| // taken from rustc | |
| check_infer( | |
| r#" | |
| pub fn compute() { | |
| match nope!() { | |
| SizeSkeleton::Pointer { non_zero: true, tail } => {} | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 17..107 '{ ... } }': () | |
| 23..105 'match ... }': () | |
| 29..36 'nope!()': {unknown} | |
| 47..93 'SizeSk...tail }': {unknown} | |
| 81..85 'true': bool | |
| 81..85 'true': bool | |
| 87..91 'tail': {unknown} | |
| 97..99 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_std_crash_4() { | |
| // taken from rustc | |
| check_infer( | |
| r#" | |
| pub fn primitive_type() { | |
| match *self { | |
| BorrowedRef { type_: Primitive(p), ..} => {}, | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 24..105 '{ ... } }': () | |
| 30..103 'match ... }': () | |
| 36..41 '*self': {unknown} | |
| 37..41 'self': {unknown} | |
| 52..90 'Borrow...), ..}': {unknown} | |
| 73..85 'Primitive(p)': {unknown} | |
| 83..84 'p': {unknown} | |
| 94..96 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_std_crash_5() { | |
| // taken from rustc | |
| check_infer( | |
| r#" | |
| //- minicore: iterator | |
| fn extra_compiler_flags() { | |
| for content in doesnt_matter { | |
| let name = if doesnt_matter { | |
| first | |
| } else { | |
| &content | |
| }; | |
| let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { | |
| name | |
| } else { | |
| content | |
| }; | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 26..322 '{ ... } }': () | |
| 32..320 'for co... }': ! | |
| 32..320 'for co... }': {unknown} | |
| 32..320 'for co... }': &'? mut {unknown} | |
| 32..320 'for co... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | |
| 32..320 'for co... }': Option<<{unknown} as Iterator>::Item> | |
| 32..320 'for co... }': () | |
| 32..320 'for co... }': () | |
| 32..320 'for co... }': () | |
| 32..320 'for co... }': () | |
| 36..43 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 47..60 'doesnt_matter': {unknown} | |
| 47..60 'doesnt_matter': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | |
| 47..60 'doesnt_matter': <{unknown} as IntoIterator>::IntoIter | |
| 61..320 '{ ... }': () | |
| 75..79 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 82..166 'if doe... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 85..98 'doesnt_matter': bool | |
| 99..128 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 113..118 'first': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 134..166 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 148..156 '&content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 149..156 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 181..188 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 191..313 'if ICE... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 194..231 'ICE_RE..._VALUE': {unknown} | |
| 194..247 'ICE_RE...&name)': bool | |
| 241..246 '&name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 242..246 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 248..276 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 262..266 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 282..313 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| 296..303 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_nested_generics_crash() { | |
| // another crash found typechecking rustc | |
| check_infer( | |
| r#" | |
| struct Canonical<V> { | |
| value: V, | |
| } | |
| struct QueryResponse<V> { | |
| value: V, | |
| } | |
| fn test<R>(query_response: Canonical<QueryResponse<R>>) { | |
| &query_response.value; | |
| } | |
| "#, | |
| expect![[r#" | |
| 91..105 'query_response': Canonical<QueryResponse<R>> | |
| 136..166 '{ ...lue; }': () | |
| 142..163 '&query....value': &'? QueryResponse<R> | |
| 143..157 'query_response': Canonical<QueryResponse<R>> | |
| 143..163 'query_....value': QueryResponse<R> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_paren_macro_call() { | |
| check_infer( | |
| r#" | |
| macro_rules! bar { () => {0u32} } | |
| fn test() { | |
| let a = (bar!()); | |
| } | |
| "#, | |
| expect![[r#" | |
| !0..4 '0u32': u32 | |
| 44..69 '{ ...()); }': () | |
| 54..55 'a': u32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn infer_array_macro_call() { | |
| check_infer( | |
| r#" | |
| macro_rules! bar { () => {0u32} } | |
| fn test() { | |
| let a = [bar!()]; | |
| } | |
| "#, | |
| expect![[r#" | |
| !0..4 '0u32': u32 | |
| 44..69 '{ ...()]; }': () | |
| 54..55 'a': [u32; 1] | |
| 58..66 '[bar!()]': [u32; 1] | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn bug_1030() { | |
| check_infer( | |
| r#" | |
| struct HashSet<T, H>; | |
| struct FxHasher; | |
| type FxHashSet<T> = HashSet<T, FxHasher>; | |
| impl<T, H> HashSet<T, H> { | |
| fn default() -> HashSet<T, H> {} | |
| } | |
| pub fn main_loop() { | |
| FxHashSet::default(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 143..145 '{}': HashSet<T, H> | |
| 168..197 '{ ...t(); }': () | |
| 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> | |
| 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_2669() { | |
| check_infer( | |
| r#" | |
| trait A {} | |
| trait Write {} | |
| struct Response<T>(T); | |
| trait D { | |
| fn foo(); | |
| } | |
| impl<T:A> D for Response<T> { | |
| fn foo() { | |
| end(); | |
| fn end<W: Write>() { | |
| let _x: T = loop {}; | |
| } | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 120..215 '{ ... }': () | |
| 130..133 'end': fn end<{unknown}>() | |
| 130..135 'end()': () | |
| 164..209 '{ ... }': ! | |
| 182..184 '_x': ! | |
| 191..198 'loop {}': ! | |
| 196..198 '{}': () | |
| "#]], | |
| ) | |
| } | |
| #[test] | |
| fn issue_2705() { | |
| check_infer( | |
| r#" | |
| trait Trait {} | |
| fn test() { | |
| <Trait<u32>>::foo() | |
| } | |
| "#, | |
| expect![[r#" | |
| 25..52 '{ ...oo() }': () | |
| 31..48 '<Trait...>::foo': {unknown} | |
| 31..50 '<Trait...:foo()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_2683_chars_impl() { | |
| check_types( | |
| r#" | |
| //- minicore: iterator | |
| pub struct Chars<'a> {} | |
| impl<'a> Iterator for Chars<'a> { | |
| type Item = char; | |
| fn next(&mut self) -> Option<char> { loop {} } | |
| } | |
| fn test() { | |
| let chars: Chars<'_>; | |
| (chars.next(), chars.nth(1)); | |
| } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>) | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_3999_slice() { | |
| check_infer( | |
| r#" | |
| fn foo(params: &[usize]) { | |
| match params { | |
| [ps @ .., _] => {} | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 7..13 'params': &'? [usize] | |
| 25..80 '{ ... } }': () | |
| 31..78 'match ... }': () | |
| 37..43 'params': &'? [usize] | |
| 54..66 '[ps @ .., _]': [usize] | |
| 55..62 'ps @ ..': &'? [usize] | |
| 60..62 '..': [usize] | |
| 64..65 '_': usize | |
| 70..72 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_3999_struct() { | |
| // rust-analyzer should not panic on seeing this malformed | |
| // record pattern. | |
| check_infer( | |
| r#" | |
| struct Bar { | |
| a: bool, | |
| } | |
| fn foo(b: Bar) { | |
| match b { | |
| Bar { a: .. } => {}, | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 35..36 'b': Bar | |
| 43..95 '{ ... } }': () | |
| 49..93 'match ... }': () | |
| 55..56 'b': Bar | |
| 67..80 'Bar { a: .. }': Bar | |
| 76..78 '..': bool | |
| 84..86 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4235_name_conflicts() { | |
| check_infer( | |
| r#" | |
| struct FOO {} | |
| static FOO:FOO = FOO {}; | |
| impl FOO { | |
| fn foo(&self) {} | |
| } | |
| fn main() { | |
| let a = &FOO; | |
| a.foo(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 31..37 'FOO {}': FOO | |
| 63..67 'self': &'? FOO | |
| 69..71 '{}': () | |
| 85..119 '{ ...o(); }': () | |
| 95..96 'a': &'? FOO | |
| 99..103 '&FOO': &'? FOO | |
| 100..103 'FOO': FOO | |
| 109..110 'a': &'? FOO | |
| 109..116 'a.foo()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4465_dollar_crate_at_type() { | |
| check_infer( | |
| r#" | |
| pub struct Foo {} | |
| pub fn anything<T>() -> T { | |
| loop {} | |
| } | |
| macro_rules! foo { | |
| () => {{ | |
| let r: $crate::Foo = anything(); | |
| r | |
| }}; | |
| } | |
| fn main() { | |
| let _a = foo!(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 44..59 '{ loop {} }': T | |
| 50..57 'loop {}': ! | |
| 55..57 '{}': () | |
| !0..31 '{letr:...g();r}': Foo | |
| !4..5 'r': Foo | |
| !18..26 'anything': fn anything<Foo>() -> Foo | |
| !18..28 'anything()': Foo | |
| !29..30 'r': Foo | |
| 163..187 '{ ...!(); }': () | |
| 173..175 '_a': Foo | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_6811() { | |
| check_infer( | |
| r#" | |
| macro_rules! profile_function { | |
| () => { | |
| let _a = 1; | |
| let _b = 1; | |
| }; | |
| } | |
| fn main() { | |
| profile_function!(); | |
| } | |
| "#, | |
| expect![[r#" | |
| !3..5 '_a': i32 | |
| !6..7 '1': i32 | |
| !11..13 '_b': i32 | |
| !14..15 '1': i32 | |
| 103..131 '{ ...!(); }': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4053_diesel_where_clauses() { | |
| check_infer( | |
| r#" | |
| trait BoxedDsl<DB> { | |
| type Output; | |
| fn internal_into_boxed(self) -> Self::Output; | |
| } | |
| struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | |
| order: Order, | |
| } | |
| trait QueryFragment<DB: Backend> {} | |
| trait Into<T> { fn into(self) -> T; } | |
| impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | |
| for SelectStatement<F, S, D, W, O, LOf, G> | |
| where | |
| O: Into<dyn QueryFragment<DB>>, | |
| { | |
| type Output = XXX; | |
| fn internal_into_boxed(self) -> Self::Output { | |
| self.order.into(); | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | |
| 488..522 '{ ... }': () | |
| 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | |
| 498..508 'self.order': O | |
| 498..515 'self.o...into()': dyn QueryFragment<DB> + 'static | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4953() { | |
| check_infer( | |
| r#" | |
| pub struct Foo(pub i64); | |
| impl Foo { | |
| fn test() -> Self { Self(0i64) } | |
| } | |
| "#, | |
| expect![[r#" | |
| 58..72 '{ Self(0i64) }': Foo | |
| 60..64 'Self': fn Foo(i64) -> Foo | |
| 60..70 'Self(0i64)': Foo | |
| 65..69 '0i64': i64 | |
| "#]], | |
| ); | |
| check_infer( | |
| r#" | |
| pub struct Foo<T>(pub T); | |
| impl Foo<i64> { | |
| fn test() -> Self { Self(0i64) } | |
| } | |
| "#, | |
| expect![[r#" | |
| 64..78 '{ Self(0i64) }': Foo<i64> | |
| 66..70 'Self': fn Foo<i64>(i64) -> Foo<i64> | |
| 66..76 'Self(0i64)': Foo<i64> | |
| 71..75 '0i64': i64 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4931() { | |
| check_infer( | |
| r#" | |
| trait Div<T> { | |
| type Output; | |
| } | |
| trait CheckedDiv: Div<()> {} | |
| trait PrimInt: CheckedDiv<Output = ()> { | |
| fn pow(self); | |
| } | |
| fn check<T: PrimInt>(i: T) { | |
| i.pow(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 148..149 'i': T | |
| 154..170 '{ ...w(); }': () | |
| 160..161 'i': T | |
| 160..167 'i.pow()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4885() { | |
| check_infer( | |
| r#" | |
| //- minicore: coerce_unsized, future | |
| use core::future::Future; | |
| trait Foo<R> { | |
| type Bar; | |
| } | |
| fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> | |
| where | |
| K: Foo<R>, | |
| { | |
| bar(key) | |
| } | |
| fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> | |
| where | |
| K: Foo<R>, | |
| { | |
| } | |
| "#, | |
| expect![[r#" | |
| 70..73 'key': &'? K | |
| 132..148 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> | |
| 138..141 'bar': fn bar<R, K>(&'? K) -> impl Future<Output = <K as Foo<R>>::Bar> | |
| 138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> | |
| 142..145 'key': &'? K | |
| 162..165 'key': &'? K | |
| 224..227 '{ }': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_4800() { | |
| check_infer( | |
| r#" | |
| trait Debug {} | |
| struct Foo<T>; | |
| type E1<T> = (T, T, T); | |
| type E2<T> = E1<E1<E1<(T, T, T)>>>; | |
| impl Debug for Foo<E2<()>> {} | |
| struct Request; | |
| pub trait Future { | |
| type Output; | |
| } | |
| pub struct PeerSet<D>; | |
| impl<D> Service<Request> for PeerSet<D> | |
| where | |
| D: Discover, | |
| D::Key: Debug, | |
| { | |
| type Error = (); | |
| type Future = dyn Future<Output = Self::Error>; | |
| fn call(&mut self) -> Self::Future { | |
| loop {} | |
| } | |
| } | |
| pub trait Discover { | |
| type Key; | |
| } | |
| pub trait Service<Request> { | |
| type Error; | |
| type Future: Future<Output = Self::Error>; | |
| fn call(&mut self) -> Self::Future; | |
| } | |
| "#, | |
| expect![[r#" | |
| 379..383 'self': &'? mut PeerSet<D> | |
| 401..424 '{ ... }': dyn Future<Output = ()> + 'static | |
| 411..418 'loop {}': ! | |
| 416..418 '{}': () | |
| "#]], | |
| ); | |
| } | |
| // FIXME(next-solver): Though `Repeat: IntoIterator` does not hold here, we | |
| // should be able to do better at given type hints (with Chalk, we did `IntoIterator::Item<Repeat<...>>`) | |
| // From what I can tell, the point of this test is to not panic though. | |
| #[test] | |
| fn issue_4966() { | |
| check_infer( | |
| r#" | |
| //- minicore: deref | |
| pub trait IntoIterator { | |
| type Item; | |
| } | |
| struct Repeat<A> { element: A } | |
| struct Map<F> { f: F } | |
| struct Vec<T> { p: *mut T } | |
| impl<T> core::ops::Deref for Vec<T> { | |
| type Target = [T]; | |
| } | |
| fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} | |
| fn main() { | |
| let inner = Map { f: |_: &f64| 0.0 }; | |
| let repeat = Repeat { element: inner }; | |
| let vec = from_iter(repeat); | |
| vec.foo_bar(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 236..240 'iter': T | |
| 255..257 '{}': Vec<A> | |
| 269..413 '{ ...r(); }': () | |
| 279..284 'inner': Map<impl Fn(&'? f64) -> f64> | |
| 287..311 'Map { ... 0.0 }': Map<impl Fn(&'? f64) -> f64> | |
| 296..309 '|_: &f64| 0.0': impl Fn(&'? f64) -> f64 | |
| 297..298 '_': &'? f64 | |
| 306..309 '0.0': f64 | |
| 322..328 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>> | |
| 331..356 'Repeat...nner }': Repeat<Map<impl Fn(&'? f64) -> f64>> | |
| 349..354 'inner': Map<impl Fn(&'? f64) -> f64> | |
| 367..370 'vec': Vec<{unknown}> | |
| 373..382 'from_iter': fn from_iter<{unknown}, Repeat<Map<impl Fn(&'? f64) -> f64>>>(Repeat<Map<impl Fn(&'? f64) -> f64>>) -> Vec<{unknown}> | |
| 373..390 'from_i...epeat)': Vec<{unknown}> | |
| 383..389 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>> | |
| 397..400 'vec': Vec<{unknown}> | |
| 397..410 'vec.foo_bar()': {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_6628() { | |
| check_infer( | |
| r#" | |
| //- minicore: fn, phantom_data | |
| use core::marker::PhantomData; | |
| struct S<T>(PhantomData<T>); | |
| impl<T> S<T> { | |
| fn f(&self, _t: T) {} | |
| fn g<F: FnOnce(&T)>(&self, _f: F) {} | |
| } | |
| fn main() { | |
| let s = S(PhantomData); | |
| s.g(|_x| {}); | |
| s.f(10); | |
| } | |
| "#, | |
| expect![[r#" | |
| 86..90 'self': &'? S<T> | |
| 92..94 '_t': T | |
| 99..101 '{}': () | |
| 127..131 'self': &'? S<T> | |
| 133..135 '_f': F | |
| 140..142 '{}': () | |
| 155..217 '{ ...10); }': () | |
| 165..166 's': S<i32> | |
| 169..170 'S': fn S<i32>(PhantomData<i32>) -> S<i32> | |
| 169..183 'S(PhantomData)': S<i32> | |
| 171..182 'PhantomData': PhantomData<i32> | |
| 189..190 's': S<i32> | |
| 189..201 's.g(|_x| {})': () | |
| 193..200 '|_x| {}': impl FnOnce(&'? i32) | |
| 194..196 '_x': &'? i32 | |
| 198..200 '{}': () | |
| 207..208 's': S<i32> | |
| 207..214 's.f(10)': () | |
| 211..213 '10': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_6852() { | |
| check_infer( | |
| r#" | |
| //- minicore: deref | |
| use core::ops::Deref; | |
| struct BufWriter {} | |
| struct Mutex<T>(T); | |
| struct MutexGuard<'a, T>(&'a T); | |
| impl<T> Mutex<T> { | |
| fn lock(&self) -> MutexGuard<'_, T> {} | |
| } | |
| impl<'a, T: 'a> Deref for MutexGuard<'a, T> { | |
| type Target = T; | |
| fn deref(&self) -> &Self::Target { loop {} } | |
| } | |
| fn flush(&self) { | |
| let w: &Mutex<BufWriter>; | |
| *(w.lock()); | |
| } | |
| "#, | |
| expect![[r#" | |
| 129..133 'self': &'? Mutex<T> | |
| 156..158 '{}': MutexGuard<'?, T> | |
| 242..246 'self': &'? MutexGuard<'a, T> | |
| 265..276 '{ loop {} }': &'? T | |
| 267..274 'loop {}': ! | |
| 272..274 '{}': () | |
| 289..293 'self': &'? {unknown} | |
| 295..345 '{ ...()); }': () | |
| 305..306 'w': &'? Mutex<BufWriter> | |
| 331..342 '*(w.lock())': BufWriter | |
| 333..334 'w': &'? Mutex<BufWriter> | |
| 333..341 'w.lock()': MutexGuard<'?, BufWriter> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn param_overrides_fn() { | |
| check_types( | |
| r#" | |
| fn example(example: i32) { | |
| fn f() {} | |
| example; | |
| //^^^^^^^ i32 | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn lifetime_from_chalk_during_deref() { | |
| check_types( | |
| r#" | |
| //- minicore: deref | |
| struct Box<T: ?Sized>(T); | |
| impl<T: ?Sized> core::ops::Deref for Box<T> { | |
| type Target = T; | |
| fn deref(&self) -> &Self::Target { | |
| loop {} | |
| } | |
| } | |
| trait Iterator { | |
| type Item; | |
| } | |
| pub struct Iter<'a, T: 'a> { | |
| inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>, | |
| } | |
| trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> { | |
| fn clone_box(&self); | |
| } | |
| fn clone_iter<T>(s: Iter<T>) { | |
| s.inner.clone_box(); | |
| //^^^^^^^^^^^^^^^^^^^ () | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn issue_8686() { | |
| check_infer( | |
| r#" | |
| //- minicore: phantom_data | |
| use core::marker::PhantomData; | |
| pub trait Try: FromResidual { | |
| type Output; | |
| type Residual; | |
| } | |
| pub trait FromResidual<R = <Self as Try>::Residual> { | |
| fn from_residual(residual: R) -> Self; | |
| } | |
| struct ControlFlow<B, C>(PhantomData<(B, C)>); | |
| impl<B, C> Try for ControlFlow<B, C> { | |
| type Output = C; | |
| type Residual = ControlFlow<B, !>; | |
| } | |
| impl<B, C> FromResidual for ControlFlow<B, C> { | |
| fn from_residual(r: ControlFlow<B, !>) -> Self { ControlFlow(PhantomData) } | |
| } | |
| fn test() { | |
| ControlFlow::from_residual(ControlFlow::<u32, !>(PhantomData)); | |
| } | |
| "#, | |
| expect![[r#" | |
| 418..419 'r': ControlFlow<B, !> | |
| 448..476 '{ Cont...ata) }': ControlFlow<B, C> | |
| 450..461 'ControlFlow': fn ControlFlow<B, C>(PhantomData<(B, C)>) -> ControlFlow<B, C> | |
| 450..474 'Contro...mData)': ControlFlow<B, C> | |
| 462..473 'PhantomData': PhantomData<(B, C)> | |
| 490..561 '{ ...a)); }': () | |
| 496..522 'Contro...sidual': fn from_residual<ControlFlow<u32, {unknown}>, ControlFlow<u32, !>>(ControlFlow<u32, !>) -> ControlFlow<u32, {unknown}> | |
| 496..558 'Contro...Data))': ControlFlow<u32, {unknown}> | |
| 523..544 'Contro...32, !>': fn ControlFlow<u32, !>(PhantomData<(u32, !)>) -> ControlFlow<u32, !> | |
| 523..557 'Contro...mData)': ControlFlow<u32, !> | |
| 545..556 'PhantomData': PhantomData<(u32, !)> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn cfg_tail() { | |
| // https://github.com/rust-lang/rust-analyzer/issues/8378 | |
| check_infer( | |
| r#" | |
| fn fake_tail(){ | |
| { "first" } | |
| #[cfg(never)] 9 | |
| } | |
| fn multiple_fake(){ | |
| { "fake" } | |
| { "fake" } | |
| { "second" } | |
| #[cfg(never)] { 11 } | |
| #[cfg(never)] 12; | |
| #[cfg(never)] 13 | |
| } | |
| fn no_normal_tail(){ | |
| { "third" } | |
| #[cfg(never)] 14; | |
| #[cfg(never)] 15; | |
| } | |
| fn no_actual_tail(){ | |
| { "fourth" }; | |
| #[cfg(never)] 14; | |
| #[cfg(never)] 15 | |
| } | |
| "#, | |
| expect![[r#" | |
| 14..53 '{ ...)] 9 }': () | |
| 20..31 '{ "first" }': () | |
| 22..29 '"first"': &'static str | |
| 72..190 '{ ...] 13 }': () | |
| 78..88 '{ "fake" }': () | |
| 80..86 '"fake"': &'static str | |
| 93..103 '{ "fake" }': () | |
| 95..101 '"fake"': &'static str | |
| 108..120 '{ "second" }': () | |
| 110..118 '"second"': &'static str | |
| 210..273 '{ ... 15; }': () | |
| 216..227 '{ "third" }': () | |
| 218..225 '"third"': &'static str | |
| 293..357 '{ ...] 15 }': () | |
| 299..311 '{ "fourth" }': &'? str | |
| 301..309 '"fourth"': &'static str | |
| "#]], | |
| ) | |
| } | |
| #[test] | |
| fn impl_trait_in_option_9530() { | |
| check_types( | |
| r#" | |
| //- minicore: sized | |
| struct Option<T>(T); | |
| impl<T> Option<T> { | |
| fn unwrap(self) -> T { loop {} } | |
| } | |
| fn make() -> Option<impl Copy> { Option(()) } | |
| trait Copy {} | |
| impl Copy for () {} | |
| fn test() { | |
| let o = make(); | |
| o.unwrap(); | |
| //^^^^^^^^^^ impl Copy | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn bare_dyn_trait_binders_9639() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: fn, coerce_unsized, dispatch_from_dyn | |
| fn infix_parse<T, S>(_state: S, _level_code: &Fn(S)) -> T { | |
| loop {} | |
| } | |
| fn parse_a_rule() { | |
| infix_parse((), &(|_recurse| ())) | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn nested_closure() { | |
| check_types( | |
| r#" | |
| //- minicore: fn, option | |
| fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} } | |
| fn test() { | |
| let o = Some(Some(2)); | |
| map(o, |s| map(s, |x| x)); | |
| // ^ i32 | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn call_expected_type_closure() { | |
| check_types( | |
| r#" | |
| //- minicore: fn, option | |
| fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} } | |
| struct S { | |
| field: u32 | |
| } | |
| fn test() { | |
| let o = Some(S { field: 2 }); | |
| let _: Option<()> = map(o, |s| { s.field; }); | |
| // ^^^^^^^ u32 | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn coerce_diesel_panic() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: option | |
| trait TypeMetadata { | |
| type MetadataLookup; | |
| } | |
| pub struct Output<'a, T, DB> | |
| where | |
| DB: TypeMetadata, | |
| DB::MetadataLookup: 'a, | |
| { | |
| out: T, | |
| metadata_lookup: Option<&'a DB::MetadataLookup>, | |
| } | |
| impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> { | |
| pub fn new(out: T, metadata_lookup: &'a DB::MetadataLookup) -> Self { | |
| Output { | |
| out, | |
| metadata_lookup: Some(metadata_lookup), | |
| } | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn bitslice_panic() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: option, deref | |
| pub trait BitView { | |
| type Store; | |
| } | |
| pub struct Lsb0; | |
| pub struct BitArray<V: BitView>(V); | |
| pub struct BitSlice<T>(T); | |
| impl<V: BitView> core::ops::Deref for BitArray<V> { | |
| type Target = BitSlice<V::Store>; | |
| } | |
| impl<T> BitSlice<T> { | |
| pub fn split_first(&self) -> Option<(T, &Self)> { loop {} } | |
| } | |
| fn multiexp_inner() { | |
| let exp: &BitArray<Foo>; | |
| exp.split_first(); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn macro_expands_to_impl_trait() { | |
| check_no_mismatches( | |
| r#" | |
| trait Foo {} | |
| macro_rules! ty { | |
| () => { | |
| impl Foo | |
| } | |
| } | |
| fn foo(_: ty!()) {} | |
| fn bar() { | |
| foo(()); | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn nested_macro_in_fn_params() { | |
| check_no_mismatches( | |
| r#" | |
| macro_rules! U32Inner { | |
| () => { | |
| u32 | |
| }; | |
| } | |
| macro_rules! U32 { | |
| () => { | |
| U32Inner!() | |
| }; | |
| } | |
| fn mamba(a: U32!(), p: u32) -> u32 { | |
| a | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn for_loop_block_expr_iterable() { | |
| // FIXME(next-solver): it would be nice to be able to hint `IntoIterator::IntoIter<()>` instead of just `{unknown}` | |
| // (even though `(): IntoIterator` does not hold) | |
| check_infer( | |
| r#" | |
| //- minicore: iterator | |
| fn test() { | |
| for _ in { let x = 0; } { | |
| let y = 0; | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..68 '{ ... } }': () | |
| 16..66 'for _ ... }': ! | |
| 16..66 'for _ ... }': {unknown} | |
| 16..66 'for _ ... }': &'? mut {unknown} | |
| 16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | |
| 16..66 'for _ ... }': Option<<{unknown} as Iterator>::Item> | |
| 16..66 'for _ ... }': () | |
| 16..66 'for _ ... }': () | |
| 16..66 'for _ ... }': () | |
| 16..66 'for _ ... }': () | |
| 20..21 '_': {unknown} | |
| 25..39 '{ let x = 0; }': () | |
| 25..39 '{ let x = 0; }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter | |
| 25..39 '{ let x = 0; }': <() as IntoIterator>::IntoIter | |
| 31..32 'x': i32 | |
| 35..36 '0': i32 | |
| 40..66 '{ ... }': () | |
| 54..55 'y': i32 | |
| 58..59 '0': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn while_loop_block_expr_iterable() { | |
| check_infer( | |
| r#" | |
| fn test() { | |
| while { true } { | |
| let y = 0; | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 10..59 '{ ... } }': () | |
| 16..57 'while ... }': ! | |
| 16..57 'while ... }': () | |
| 16..57 'while ... }': () | |
| 22..30 '{ true }': bool | |
| 24..28 'true': bool | |
| 31..57 '{ ... }': () | |
| 45..46 'y': i32 | |
| 49..50 '0': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn bug_11242() { | |
| check_types( | |
| r#" | |
| fn foo<A, B>() | |
| where | |
| A: IntoIterator<Item = u32>, | |
| B: IntoIterator<Item = usize>, | |
| { | |
| let _x: <A as IntoIterator>::Item; | |
| // ^^ u32 | |
| } | |
| pub trait Iterator { | |
| type Item; | |
| } | |
| pub trait IntoIterator { | |
| type Item; | |
| type IntoIter: Iterator<Item = Self::Item>; | |
| } | |
| impl<I: Iterator> IntoIterator for I { | |
| type Item = I::Item; | |
| type IntoIter = I; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn bug_11659() { | |
| check_no_mismatches( | |
| r#" | |
| struct LinkArray<const N: usize, LD>(LD); | |
| fn f<const N: usize, LD>(x: LD) -> LinkArray<N, LD> { | |
| let r = LinkArray::<N, LD>(x); | |
| r | |
| } | |
| fn test() { | |
| let x = f::<2, i32>(5); | |
| let y = LinkArray::<52, LinkArray<2, i32>>(x); | |
| } | |
| "#, | |
| ); | |
| check_no_mismatches( | |
| r#" | |
| struct LinkArray<LD, const N: usize>(LD); | |
| fn f<const N: usize, LD>(x: LD) -> LinkArray<LD, N> { | |
| let r = LinkArray::<LD, N>(x); | |
| r | |
| } | |
| fn test() { | |
| let x = f::<i32, 2>(5); | |
| let y = LinkArray::<LinkArray<i32, 2>, 52>(x); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn const_generic_error_tolerance() { | |
| check_no_mismatches( | |
| r#" | |
| #[lang = "sized"] | |
| pub trait Sized {} | |
| struct CT<const N: usize, T>(T); | |
| struct TC<T, const N: usize>(T); | |
| fn f<const N: usize, T>(x: T) -> (CT<N, T>, TC<T, N>) { | |
| let l = CT::<N, T>(x); | |
| let r = TC::<N, T>(x); | |
| (l, r) | |
| } | |
| trait TR1<const N: usize>; | |
| trait TR2<const N: usize>; | |
| impl<const N: usize, T> TR1<N> for CT<N, T>; | |
| impl<const N: usize, T> TR1<5> for TC<T, N>; | |
| impl<const N: usize, T> TR2<N> for CT<T, N>; | |
| trait TR3<const N: usize> { | |
| fn tr3(&self) -> &Self; | |
| } | |
| impl<const N: usize, T> TR3<5> for TC<T, N> { | |
| fn tr3(&self) -> &Self { | |
| self | |
| } | |
| } | |
| impl<const N: usize, T> TR3<Item = 5> for TC<T, N> {} | |
| impl<const N: usize, T> TR3<T> for TC<T, N> {} | |
| fn impl_trait<const N: usize>(inp: impl TR1<N>) {} | |
| fn dyn_trait<const N: usize>(inp: &dyn TR2<N>) {} | |
| fn impl_trait_bad<'a, const N: usize>(inp: impl TR1<i32>) -> impl TR1<'a, i32> {} | |
| fn impl_trait_very_bad<const N: usize>(inp: impl TR1<Item = i32>) -> impl TR1<'a, Item = i32, 5, Foo = N> {} | |
| fn test() { | |
| f::<2, i32>(5); | |
| f::<2, 2>(5); | |
| f(5); | |
| f::<i32>(5); | |
| CT::<52, CT<2, i32>>(x); | |
| CT::<CT<2, i32>>(x); | |
| impl_trait_bad(5); | |
| impl_trait_bad(12); | |
| TR3<5>::tr3(); | |
| TR3<{ 2+3 }>::tr3(); | |
| TC::<i32, 10>(5).tr3(); | |
| TC::<i32, 20>(5).tr3(); | |
| TC::<i32, i32>(5).tr3(); | |
| TC::<i32, { 7 + 3 }>(5).tr3(); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn const_generic_impl_trait() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: from | |
| struct Foo<T, const M: usize>; | |
| trait Tr<T> { | |
| fn f(T) -> Self; | |
| } | |
| impl<T, const M: usize> Tr<[T; M]> for Foo<T, M> { | |
| fn f(_: [T; M]) -> Self { | |
| Self | |
| } | |
| } | |
| fn test() { | |
| Foo::f([1, 2, 7, 10]); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn nalgebra_factorial() { | |
| check_no_mismatches( | |
| r#" | |
| const FACTORIAL: [u128; 4] = [1, 1, 2, 6]; | |
| fn factorial(n: usize) -> u128 { | |
| match FACTORIAL.get(n) { | |
| Some(f) => *f, | |
| None => panic!("{}! is greater than u128::MAX", n), | |
| } | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn regression_11688_1() { | |
| check_no_mismatches( | |
| r#" | |
| pub struct Buffer<T>(T); | |
| type Writer = Buffer<u8>; | |
| impl<T> Buffer<T> { | |
| fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) { | |
| loop {} | |
| } | |
| } | |
| trait Encode<S> { | |
| fn encode(self, w: &mut Writer, s: &mut S); | |
| } | |
| impl<S> Encode<S> for u8 { | |
| fn encode(self, w: &mut Writer, _: &mut S) { | |
| w.extend_from_array(&self.to_le_bytes()); | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_11688_2() { | |
| check_types( | |
| r#" | |
| union MaybeUninit<T> { | |
| uninit: (), | |
| value: T, | |
| } | |
| impl<T> MaybeUninit<T> { | |
| fn uninit_array<const LEN: usize>() -> [Self; LEN] { | |
| loop {} | |
| } | |
| } | |
| fn main() { | |
| let x = MaybeUninit::<i32>::uninit_array::<1>(); | |
| //^ [MaybeUninit<i32>; 1] | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_11688_3() { | |
| check_types( | |
| r#" | |
| //- minicore: iterator, dispatch_from_dyn | |
| struct Ar<T, const N: u8>(T); | |
| fn f<const LEN: usize, T, const BASE: u8>( | |
| num_zeros: usize, | |
| ) -> &dyn Iterator<Item = [Ar<T, BASE>; LEN]> { | |
| loop {} | |
| } | |
| fn dynamic_programming() { | |
| let board = f::<9, u8, 7>(1).next(); | |
| //^^^^^ Option<[Ar<u8, 7>; 9]> | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_11688_4() { | |
| check_types( | |
| r#" | |
| //- minicore: dispatch_from_dyn | |
| trait Bar<const C: usize> { | |
| fn baz(&self) -> [i32; C]; | |
| } | |
| fn foo(x: &dyn Bar<2>) { | |
| x.baz(); | |
| //^^^^^^^ [i32; 2] | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn gat_crash_1() { | |
| check_no_mismatches( | |
| r#" | |
| trait ATrait {} | |
| trait Crash { | |
| type Member<const N: usize>: ATrait; | |
| fn new<const N: usize>() -> Self::Member<N>; | |
| } | |
| fn test<T: Crash>() { | |
| T::new(); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn gat_crash_2() { | |
| check_no_mismatches( | |
| r#" | |
| pub struct InlineStorage {} | |
| pub struct InlineStorageHandle<T: ?Sized> {} | |
| pub unsafe trait Storage { | |
| type Handle<T: ?Sized>; | |
| fn create<T: ?Sized>() -> Self::Handle<T>; | |
| } | |
| unsafe impl Storage for InlineStorage { | |
| type Handle<T: ?Sized> = InlineStorageHandle<T>; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn gat_crash_3() { | |
| check_no_mismatches( | |
| r#" | |
| trait Collection { | |
| type Item; | |
| type Member<T>: Collection<Item = T>; | |
| fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>; | |
| } | |
| struct ConstGen<T, const N: usize> { | |
| data: [T; N], | |
| } | |
| impl<T, const N: usize> Collection for ConstGen<T, N> { | |
| type Item = T; | |
| type Member<U> = ConstGen<U, N>; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn tuple_struct_pattern_with_unmatched_args_crash() { | |
| check_infer( | |
| r#" | |
| struct S(usize); | |
| fn main() { | |
| let S(.., a, b) = S(1); | |
| let (.., a, b) = (1,); | |
| } | |
| "#, | |
| expect![[r#" | |
| 27..85 '{ ...1,); }': () | |
| 37..48 'S(.., a, b)': S | |
| 43..44 'a': usize | |
| 46..47 'b': {unknown} | |
| 51..52 'S': fn S(usize) -> S | |
| 51..55 'S(1)': S | |
| 53..54 '1': usize | |
| 65..75 '(.., a, b)': (i32, {unknown}) | |
| 70..71 'a': i32 | |
| 73..74 'b': {unknown} | |
| 78..82 '(1,)': (i32,) | |
| 79..80 '1': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn trailing_empty_macro() { | |
| check_no_mismatches( | |
| r#" | |
| macro_rules! m2 { | |
| ($($t:tt)*) => {$($t)*}; | |
| } | |
| fn macrostmts() -> u8 { | |
| m2! { 0 } | |
| m2! {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn dyn_with_unresolved_trait() { | |
| check_types( | |
| r#" | |
| fn foo(a: &dyn DoesNotExist) { | |
| a.bar(); | |
| //^&'? {unknown} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn self_assoc_with_const_generics_crash() { | |
| check_no_mismatches( | |
| r#" | |
| trait Trait { type Item; } | |
| impl<T, const N: usize> Trait for [T; N] { | |
| type Item = (); | |
| fn f<U>(_: Self::Item) {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn unsize_array_with_inference_variable() { | |
| check_types( | |
| r#" | |
| //- minicore: try, slice | |
| use core::ops::ControlFlow; | |
| fn foo() -> ControlFlow<(), [usize; 1]> { loop {} } | |
| fn bar() -> ControlFlow<(), ()> { | |
| let a = foo()?.len(); | |
| //^ usize | |
| ControlFlow::Continue(()) | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn assoc_type_shorthand_with_gats_in_binders() { | |
| // c.f. test `issue_4885()` | |
| check_no_mismatches( | |
| r#" | |
| trait Gats { | |
| type Assoc<T>; | |
| } | |
| trait Foo<T> {} | |
| struct Bar<'a, B: Gats, A> { | |
| field: &'a dyn Foo<B::Assoc<A>>, | |
| } | |
| fn foo(b: Bar) { | |
| let _ = b.field; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_14305() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: add | |
| trait Tr {} | |
| impl Tr for [u8; C] {} | |
| const C: usize = 2 + 2; | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_14456() { | |
| check_types( | |
| r#" | |
| //- minicore: future | |
| async fn x() {} | |
| fn f() { | |
| let fut = x(); | |
| let t = [0u8; { let a = 2 + 2; a }]; | |
| //^ [u8; 4] | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_14164() { | |
| check_types( | |
| r#" | |
| trait Rec { | |
| type K; | |
| type Rebind<Tok>: Rec<K = Tok>; | |
| } | |
| trait Expr<K> { | |
| type Part: Rec<K = K>; | |
| fn foo(_: <Self::Part as Rec>::Rebind<i32>) {} | |
| } | |
| struct Head<K>(K); | |
| impl<K> Rec for Head<K> { | |
| type K = K; | |
| type Rebind<Tok> = Head<Tok>; | |
| } | |
| fn test<E>() | |
| where | |
| E: Expr<usize, Part = Head<usize>>, | |
| { | |
| let head; | |
| //^^^^ Head<i32> | |
| E::foo(head); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn match_ergonomics_with_binding_modes_interaction() { | |
| check_types( | |
| r" | |
| enum E { A } | |
| fn foo() { | |
| match &E::A { | |
| b @ (x @ E::A | x) => { | |
| b; | |
| //^ &'? E | |
| x; | |
| //^ &'? E | |
| } | |
| } | |
| }", | |
| ); | |
| } | |
| #[test] | |
| fn regression_14844() { | |
| check_no_mismatches( | |
| r#" | |
| pub type Ty = Unknown; | |
| pub struct Inner<T>(T); | |
| pub struct Outer { | |
| pub inner: Inner<Ty>, | |
| } | |
| fn main() { | |
| _ = Outer { | |
| inner: Inner::<i32>(0), | |
| }; | |
| } | |
| "#, | |
| ); | |
| check_no_mismatches( | |
| r#" | |
| pub const ONE: usize = 1; | |
| pub struct Inner<const P: usize>(); | |
| pub struct Outer { | |
| pub inner: Inner<ONE>, | |
| } | |
| fn main() { | |
| _ = Outer { | |
| inner: Inner::<1>(), | |
| }; | |
| } | |
| "#, | |
| ); | |
| check_no_mismatches( | |
| r#" | |
| pub const ONE: usize = unknown(); | |
| pub struct Inner<const P: usize>(); | |
| pub struct Outer { | |
| pub inner: Inner<ONE>, | |
| } | |
| fn main() { | |
| _ = Outer { | |
| inner: Inner::<1>(), | |
| }; | |
| } | |
| "#, | |
| ); | |
| check_no_mismatches( | |
| r#" | |
| pub const N: usize = 2 + 2; | |
| fn f(t: [u8; N]) {} | |
| fn main() { | |
| let a = [1, 2, 3, 4]; | |
| f(a); | |
| let b = [1; 4]; | |
| let c: [u8; N] = b; | |
| let d = [1; N]; | |
| let e: [u8; N] = d; | |
| let f = [1; N]; | |
| let g = match f { | |
| [a, b, c, d] => a + b + c + d, | |
| }; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_14844_2() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: fn | |
| pub const ONE: usize = 1; | |
| pub type MyInner = Inner<ONE>; | |
| pub struct Inner<const P: usize>(); | |
| impl Inner<1> { | |
| fn map<F>(&self, func: F) -> bool | |
| where | |
| F: Fn(&MyInner) -> bool, | |
| { | |
| func(self) | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn dont_crash_on_slice_unsizing() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: slice, unsize, coerce_unsized | |
| trait Tr { | |
| fn f(self); | |
| } | |
| impl Tr for [i32] { | |
| fn f(self) { | |
| let t; | |
| x(t); | |
| } | |
| } | |
| fn x(a: [i32; 4]) { | |
| let b = a.f(); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn dont_unify_on_casts() { | |
| // #15246 | |
| check_types( | |
| r#" | |
| //- minicore: sized | |
| fn unify(_: [bool; 1]) {} | |
| fn casted(_: *const bool) {} | |
| fn default<T>() -> T { loop {} } | |
| fn test() { | |
| let foo = default(); | |
| //^^^ [bool; 1] | |
| casted(&foo as *const _); | |
| unify(foo); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn rustc_test_issue_52437() { | |
| check_types( | |
| r#" | |
| //- minicore: sized | |
| fn main() { | |
| let x = [(); &(&'static: loop { |x| {}; }) as *const _ as usize] | |
| //^ [(); _] | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn incorrect_variant_form_through_alias_caught() { | |
| check_types( | |
| r#" | |
| enum Enum { Braced {}, Unit, Tuple() } | |
| type Alias = Enum; | |
| fn main() { | |
| Alias::Braced; | |
| //^^^^^^^^^^^^^ {unknown} | |
| let Alias::Braced = loop {}; | |
| //^^^^^^^^^^^^^ {unknown} | |
| let Alias::Braced(..) = loop {}; | |
| //^^^^^^^^^^^^^^^^^ Enum | |
| Alias::Unit(); | |
| //^^^^^^^^^^^^^ {unknown} | |
| Alias::Unit{}; | |
| //^^^^^^^^^^^^^ Enum | |
| let Alias::Unit() = loop {}; | |
| //^^^^^^^^^^^^^ Enum | |
| let Alias::Unit{} = loop {}; | |
| //^^^^^^^^^^^^^ Enum | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn cfg_first_trait_param_16141() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: sized, coerce_unsized | |
| trait Bar { | |
| fn bar(&self) {} | |
| } | |
| impl<#[cfg(feature = "a-feature")] A> Bar for (){} | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn nested_anon_generics_and_where_bounds_17173() { | |
| check_types( | |
| r#" | |
| //- minicore: sized, fn | |
| pub trait Lookup { | |
| type Data; | |
| fn lookup(&self) -> Self::Data; | |
| } | |
| pub trait ItemTreeLoc { | |
| type Id; | |
| } | |
| fn id_to_generics(id: impl Lookup<Data = impl ItemTreeLoc<Id = ()>>, | |
| //^^ impl Lookup<Data = impl ItemTreeLoc<Id = ()>> | |
| enabled_params: impl Fn(), | |
| //^^^^^^^^^^^^^^ impl Fn() | |
| ) | |
| where | |
| (): Sized, | |
| {} | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn tait_async_stack_overflow_17199() { | |
| // The error here is because we don't support TAITs. | |
| check( | |
| r#" | |
| //- minicore: fmt, future | |
| type Foo = impl core::fmt::Debug; | |
| async fn foo() -> Foo { | |
| () | |
| // ^^ expected impl Debug, got () | |
| } | |
| async fn test() { | |
| let t = foo().await; | |
| // ^ type: impl Debug | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn lifetime_params_move_param_defaults() { | |
| check_types( | |
| r#" | |
| pub struct Thing<'s, T = u32>(&'s T); | |
| impl <'s> Thing<'s> { | |
| pub fn new() -> Thing<'s> { | |
| Thing(&0) | |
| //^^^^^^^^^ Thing<'?, u32> | |
| } | |
| } | |
| fn main() { | |
| let scope = | |
| //^^^^^ &'? Thing<'?, u32> | |
| &Thing::new(); | |
| //^^^^^^^^^^^^ Thing<'?, u32> | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_17734() { | |
| check_types( | |
| r#" | |
| fn test() { | |
| let x = S::foo::<'static, &()>(&S); | |
| // ^ Wrap<'?, ()> | |
| let x = S::foo::<&()>(&S); | |
| // ^ Wrap<'?, ()> | |
| let x = S.foo::<'static, &()>(); | |
| // ^ Wrap<'?, ()> | |
| let x = S.foo::<&()>(); | |
| // ^ Wrap<'?, ()> | |
| } | |
| struct S; | |
| impl S { | |
| pub fn foo<'a, T: Trait<'a>>(&'a self) -> T::Proj { | |
| loop {} | |
| } | |
| } | |
| struct Wrap<'a, T>(&'a T); | |
| trait Trait<'a> { | |
| type Proj; | |
| } | |
| impl<'a, T> Trait<'a> for &'a T { | |
| type Proj = Wrap<'a, T>; | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn issue_17738() { | |
| check_types( | |
| r#" | |
| //- minicore: index | |
| use core::ops::{Index, IndexMut}; | |
| struct Foo<K, V>(K, V); | |
| struct Bar; | |
| impl Bar { | |
| fn bar(&mut self) {} | |
| } | |
| impl<K, V> Foo<K, V> { | |
| fn new(_v: V) -> Self { | |
| loop {} | |
| } | |
| } | |
| impl<K, B, V> Index<B> for Foo<K, V> { | |
| type Output = V; | |
| fn index(&self, _index: B) -> &Self::Output { | |
| loop {} | |
| } | |
| } | |
| impl<K, V> IndexMut<K> for Foo<K, V> { | |
| fn index_mut(&mut self, _index: K) -> &mut Self::Output { | |
| loop {} | |
| } | |
| } | |
| fn test() { | |
| let mut t1 = Foo::new(Bar); | |
| // ^^^^^^ Foo<&'? (), Bar> | |
| t1[&()] = Bar; | |
| let mut t2 = Foo::new(Bar); | |
| // ^^^^^^ Foo<&'? (), Bar> | |
| t2[&()].bar(); | |
| } | |
| "#, | |
| ) | |
| } | |
| #[test] | |
| fn issue_17191() { | |
| check_types( | |
| r#" | |
| trait A { | |
| type Item; | |
| } | |
| trait B<T> {} | |
| fn foo<T: B<impl A>>() {} | |
| fn test() { | |
| let f = foo; | |
| //^ fn foo<{unknown}>() | |
| }"#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_17866() { | |
| check_infer( | |
| r#" | |
| trait T { | |
| type A; | |
| } | |
| type Foo = <S as T>::A; | |
| fn main() { | |
| Foo {}; | |
| } | |
| "#, | |
| expect![[r#" | |
| 60..75 '{ Foo {}; }': () | |
| 66..72 'Foo {}': {unknown} | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_17711() { | |
| check_infer( | |
| r#" | |
| //- minicore: deref | |
| use core::ops::Deref; | |
| struct Struct<'a, T>(&'a T); | |
| trait Trait {} | |
| impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> { | |
| fn foo(&self) -> &Self { self } | |
| fn bar(&self) { | |
| let _ = self.foo(); | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 137..141 'self': &'? Struct<'a, T> | |
| 152..160 '{ self }': &'? Struct<'a, T> | |
| 154..158 'self': &'? Struct<'a, T> | |
| 174..178 'self': &'? Struct<'a, T> | |
| 180..215 '{ ... }': () | |
| 194..195 '_': &'? Struct<'?, T> | |
| 198..202 'self': &'? Struct<'a, T> | |
| 198..208 'self.foo()': &'? Struct<'?, T> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_17767() { | |
| check_infer( | |
| r#" | |
| extern "C" { | |
| type Foo<T>; | |
| } | |
| fn f() -> Foo {} | |
| "#, | |
| expect![[r#" | |
| 47..49 '{}': Foo | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_17921() { | |
| check_infer( | |
| r#" | |
| //- minicore: future | |
| trait Foo {} | |
| type Bar = impl Foo; | |
| async fn f<A, B, C>() -> Bar {} | |
| "#, | |
| expect![[r#" | |
| 64..66 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_18109() { | |
| check_infer( | |
| r#" | |
| //- minicore: option | |
| struct Map<T, U>(T, U); | |
| impl<T, U> Map<T, U> { | |
| fn new() -> Self { loop {} } | |
| fn get(&self, _: &T) -> Option<&U> { loop {} } | |
| } | |
| fn test(x: bool) { | |
| let map = Map::new(); | |
| let _ = match x { | |
| true => { | |
| let Some(val) = map.get(&8) else { return }; | |
| *val | |
| } | |
| false => return, | |
| _ => 42, | |
| }; | |
| } | |
| "#, | |
| expect![[r#" | |
| 69..80 '{ loop {} }': Map<T, U> | |
| 71..78 'loop {}': ! | |
| 76..78 '{}': () | |
| 93..97 'self': &'? Map<T, U> | |
| 99..100 '_': &'? T | |
| 120..131 '{ loop {} }': Option<&'? U> | |
| 122..129 'loop {}': ! | |
| 127..129 '{}': () | |
| 143..144 'x': bool | |
| 152..354 '{ ... }; }': () | |
| 162..165 'map': Map<i32, i32> | |
| 168..176 'Map::new': fn new<i32, i32>() -> Map<i32, i32> | |
| 168..178 'Map::new()': Map<i32, i32> | |
| 188..189 '_': i32 | |
| 192..351 'match ... }': i32 | |
| 198..199 'x': bool | |
| 210..214 'true': bool | |
| 210..214 'true': bool | |
| 218..303 '{ ... }': i32 | |
| 236..245 'Some(val)': Option<&'? i32> | |
| 241..244 'val': &'? i32 | |
| 248..251 'map': Map<i32, i32> | |
| 248..259 'map.get(&8)': Option<&'? i32> | |
| 256..258 '&8': &'? i32 | |
| 257..258 '8': i32 | |
| 265..275 '{ return }': ! | |
| 267..273 'return': ! | |
| 289..293 '*val': i32 | |
| 290..293 'val': &'? i32 | |
| 312..317 'false': bool | |
| 312..317 'false': bool | |
| 321..327 'return': ! | |
| 337..338 '_': bool | |
| 342..344 '42': i32 | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn issue_19730() { | |
| check_infer( | |
| r#" | |
| trait Trait<T = Self> {} | |
| trait Foo { | |
| type Bar<A, B>: Trait; | |
| fn foo<A, B>(bar: Self::Bar<A, B>) { | |
| let _ = bar; | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 83..86 'bar': <Self as Foo>::Bar<A, B> | |
| 105..133 '{ ... }': () | |
| 119..120 '_': <Self as Foo>::Bar<A, B> | |
| 123..126 'bar': <Self as Foo>::Bar<A, B> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn no_panic_on_recursive_const() { | |
| check_infer( | |
| r#" | |
| struct Foo<const N: usize> {} | |
| impl<const N: Foo<N>> Foo<N> { | |
| fn foo(self) {} | |
| } | |
| fn test() { | |
| let _ = N; | |
| } | |
| "#, | |
| expect![[r#" | |
| 72..76 'self': Foo<N> | |
| 78..80 '{}': () | |
| 94..112 '{ ...= N; }': () | |
| 104..105 '_': {unknown} | |
| 108..109 'N': {unknown} | |
| "#]], | |
| ); | |
| check_infer( | |
| r#" | |
| struct Foo<const N: usize>; | |
| const N: Foo<N> = Foo; | |
| impl<const N: usize> Foo<N> { | |
| fn foo(self) -> usize { | |
| N | |
| } | |
| } | |
| fn test() { | |
| let _ = N; | |
| } | |
| "#, | |
| expect![[r#" | |
| 46..49 'Foo': Foo<_> | |
| 93..97 'self': Foo<N> | |
| 108..125 '{ ... }': usize | |
| 118..119 'N': usize | |
| 139..157 '{ ...= N; }': () | |
| 149..150 '_': Foo<_> | |
| 153..154 'N': Foo<_> | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn rust_destruct_option_clone() { | |
| check_types( | |
| r#" | |
| //- minicore: option, drop | |
| #![feature(lang_items)] | |
| fn test(o: &Option<i32>) { | |
| o.my_clone(); | |
| //^^^^^^^^^^^^ Option<i32> | |
| } | |
| pub trait MyClone: Sized { | |
| fn my_clone(&self) -> Self; | |
| } | |
| impl<T> const MyClone for Option<T> | |
| where | |
| T: ~const MyClone + ~const Destruct, | |
| { | |
| fn my_clone(&self) -> Self { | |
| match self { | |
| Some(x) => Some(x.my_clone()), | |
| None => None, | |
| } | |
| } | |
| } | |
| impl const MyClone for i32 { | |
| fn my_clone(&self) -> Self { | |
| *self | |
| } | |
| } | |
| #[lang = "destruct"] | |
| pub trait Destruct {} | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn no_duplicated_lang_item_metadata() { | |
| check_types( | |
| r#" | |
| //- minicore: pointee | |
| //- /main.rs crate:main deps:std,core | |
| use std::AtomicPtr; | |
| use std::null_mut; | |
| fn main() { | |
| let x: AtomicPtr<()> = AtomicPtr::new(null_mut()); | |
| //^ AtomicPtr<()> | |
| } | |
| //- /lib.rs crate:r#std deps:core | |
| #![no_std] | |
| pub use core::*; | |
| //- /lib.rs crate:r#core | |
| #![no_core] | |
| #[lang = "pointee_trait"] | |
| pub trait Pointee { | |
| #[lang = "metadata_type"] | |
| type Metadata; | |
| } | |
| pub struct AtomicPtr<T>(T); | |
| impl<T> AtomicPtr<T> { | |
| pub fn new(p: *mut T) -> AtomicPtr<T> { | |
| loop {} | |
| } | |
| } | |
| #[lang = "pointee_sized"] | |
| pub trait PointeeSized {} | |
| #[lang = "meta_sized"] | |
| pub trait MetaSized: PointeeSized {} | |
| #[lang = "sized"] | |
| pub trait Sized: MetaSized {} | |
| pub trait Thin = Pointee<Metadata = ()> + PointeeSized; | |
| pub fn null_mut<T: PointeeSized + Thin>() -> *mut T { | |
| loop {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_20484() { | |
| check_no_mismatches( | |
| r#" | |
| struct Eth; | |
| trait FullBlockBody { | |
| type Transaction; | |
| } | |
| impl FullBlockBody for () { | |
| type Transaction = (); | |
| } | |
| trait NodePrimitives { | |
| type BlockBody; | |
| type SignedTx; | |
| } | |
| impl NodePrimitives for () { | |
| type BlockBody = (); | |
| type SignedTx = (); | |
| } | |
| impl NodePrimitives for Eth { | |
| type BlockBody = (); | |
| type SignedTx = (); | |
| } | |
| trait FullNodePrimitives | |
| where | |
| Self: NodePrimitives<BlockBody: FullBlockBody<Transaction = Self::SignedTx>>, | |
| { | |
| } | |
| impl<T> FullNodePrimitives for T where | |
| T: NodePrimitives<BlockBody: FullBlockBody<Transaction = Self::SignedTx>>, | |
| { | |
| } | |
| fn node<N>(_: N) | |
| where | |
| N: FullNodePrimitives, | |
| { | |
| } | |
| fn main() { | |
| node(Eth); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn module_inside_block() { | |
| check_types( | |
| r#" | |
| fn foo() { | |
| mod my_mod { | |
| pub type Bool = bool; | |
| } | |
| let _: my_mod::Bool; | |
| // ^ bool | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_9881_super_trait_blanket_impl() { | |
| check_types( | |
| r#" | |
| pub trait TryStream: Stream { | |
| fn try_poll_next(&self) {} | |
| } | |
| pub trait Stream { | |
| type Item; | |
| fn poll_next(&self) {} | |
| } | |
| trait StreamAlias: Stream<Item = ()> {} | |
| impl<S: Stream<Item = ()>> TryStream for S {} | |
| impl<S: Stream<Item = ()>> StreamAlias for S {} | |
| struct StreamImpl; | |
| impl Stream for StreamImpl { | |
| type Item = (); | |
| } | |
| fn foo() -> impl StreamAlias { | |
| StreamImpl | |
| } | |
| fn main() { | |
| let alias = foo(); | |
| let _: () = alias.try_poll_next(); | |
| // ^ () | |
| let _: () = alias.poll_next(); | |
| // ^ () | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21429() { | |
| check_no_mismatches( | |
| r#" | |
| trait DatabaseLike { | |
| type ForeignKey: ForeignKeyLike<DB = Self>; | |
| } | |
| trait ForeignKeyLike { | |
| type DB: DatabaseLike; | |
| fn host_columns(&self, database: &Self::DB); | |
| } | |
| trait ColumnLike { | |
| type DB: DatabaseLike; | |
| fn foo() -> &&<<Self as ColumnLike>::DB as DatabaseLike>::ForeignKey { | |
| loop {} | |
| } | |
| fn foreign_keys(&self, database: &Self::DB) { | |
| let fk = Self::foo(); | |
| fk.host_columns(database); | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_21006_generic_predicates_for_param_supertrait_cycle() { | |
| check_no_mismatches( | |
| r#" | |
| trait VCipherSuite {} | |
| trait CipherSuite | |
| where | |
| OprfHash<Self>: Hash, | |
| { | |
| } | |
| type Bar<CS: CipherSuite> = <CS::Baz as VCipherSuite>::Hash; | |
| type OprfHash<CS: CipherSuite> = <CS::Baz as VCipherSuite>::Hash; | |
| impl<CS: CipherSuite> Foo<CS> { | |
| fn seal() {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_21006_self_assoc_trait() { | |
| check_types( | |
| r#" | |
| trait Baz { | |
| fn baz(&self); | |
| } | |
| trait Foo { | |
| type Assoc; | |
| } | |
| trait Bar: Foo | |
| where | |
| Self::Assoc: Baz, | |
| { | |
| fn bar(v: Self::Assoc) { | |
| let _ = v.baz(); | |
| // ^ () | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn issue_21560() { | |
| check_no_mismatches( | |
| r#" | |
| mod bindings { | |
| use super::*; | |
| pub type HRESULT = i32; | |
| } | |
| use bindings::*; | |
| mod error { | |
| use super::*; | |
| pub fn nonzero_hresult(hr: HRESULT) -> crate::HRESULT { | |
| hr | |
| } | |
| } | |
| pub use error::*; | |
| mod hresult { | |
| use super::*; | |
| pub struct HRESULT(pub i32); | |
| } | |
| pub use hresult::HRESULT; | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21577() { | |
| check_no_mismatches( | |
| r#" | |
| pub trait FilterT<F: FilterT<F, V = Self::V> = Self> { | |
| type V; | |
| fn foo() {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21605() { | |
| check_infer( | |
| r#" | |
| //- minicore: fn, coerce_unsized, dispatch_from_dyn, iterator, iterators | |
| pub struct Filter<'a, 'b, T> | |
| where | |
| T: 'b, | |
| 'a: 'b, | |
| { | |
| filter_fn: dyn Fn(&'a T) -> bool, | |
| t: Option<T>, | |
| b: &'b (), | |
| } | |
| impl<'a, 'b, T> Filter<'a, 'b, T> | |
| where | |
| T: 'b, | |
| 'a: 'b, | |
| { | |
| pub fn new(filter_fn: dyn Fn(&T) -> bool) -> Self { | |
| Self { | |
| filter_fn: filter_fn, | |
| t: None, | |
| b: &(), | |
| } | |
| } | |
| } | |
| pub trait FilterExt<T> { | |
| type Output; | |
| fn filter(&self, filter: &Filter<T>) -> Self::Output; | |
| } | |
| impl<const N: usize, T> FilterExt<T> for [T; N] | |
| where | |
| T: IntoIterator, | |
| { | |
| type Output = T; | |
| fn filter(&self, filter: &Filter<T>) -> Self::Output { | |
| let _ = self.into_iter().filter(filter.filter_fn); | |
| loop {} | |
| } | |
| } | |
| "#, | |
| expect![[r#" | |
| 214..223 'filter_fn': dyn Fn(&'? T) -> bool + 'static | |
| 253..360 '{ ... }': Filter<'a, 'b, T> | |
| 263..354 'Self {... }': Filter<'a, 'b, T> | |
| 293..302 'filter_fn': dyn Fn(&'? T) -> bool + 'static | |
| 319..323 'None': Option<T> | |
| 340..343 '&()': &'? () | |
| 341..343 '()': () | |
| 580..584 'self': &'? [T; N] | |
| 586..592 'filter': &'? Filter<'?, '?, T> | |
| 622..704 '{ ... }': T | |
| 636..637 '_': Filter<Iter<'?, T>, dyn Fn(&'? T) -> bool + '?> | |
| 640..644 'self': &'? [T; N] | |
| 640..656 'self.i...iter()': Iter<'?, T> | |
| 640..681 'self.i...er_fn)': Filter<Iter<'?, T>, dyn Fn(&'? T) -> bool + '?> | |
| 664..670 'filter': &'? Filter<'?, '?, T> | |
| 664..680 'filter...ter_fn': dyn Fn(&'? T) -> bool + 'static | |
| 691..698 'loop {}': ! | |
| 696..698 '{}': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn extern_fns_cannot_have_param_patterns() { | |
| check_no_mismatches( | |
| r#" | |
| macro_rules! m { | |
| () => { Builder }; | |
| } | |
| pub(crate) struct Builder; | |
| unsafe extern "C" { | |
| pub(crate) fn foo(Builder: (), m!(): ()); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn trait_assoc_fns_cannot_have_param_patterns() { | |
| check_no_mismatches( | |
| r#" | |
| macro_rules! m { | |
| () => { Builder }; | |
| } | |
| pub(crate) struct Builder; | |
| trait Trait { | |
| fn foo(Builder: (), m!(): ()); | |
| } | |
| "#, | |
| ); | |
| // But assoc fns with bodies do have patterns: | |
| check( | |
| r#" | |
| macro_rules! m { | |
| () => { Builder }; | |
| } | |
| pub(crate) struct Builder; | |
| trait Trait { | |
| fn foo(Builder: (), | |
| // ^^^^^^^ expected (), got Builder | |
| m!(): ()) {} | |
| // ^^ expected (), got Builder | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn infinitely_sized_type() { | |
| check_infer( | |
| r#" | |
| //- minicore: sized | |
| pub struct Recursive { | |
| pub content: Recursive, | |
| } | |
| fn is_sized<T: Sized>() {} | |
| fn foo() { | |
| is_sized::<Recursive>(); | |
| } | |
| "#, | |
| expect![[r#" | |
| 79..81 '{}': () | |
| 92..124 '{ ...>(); }': () | |
| 98..119 'is_siz...rsive>': fn is_sized<Recursive>() | |
| 98..121 'is_siz...ive>()': () | |
| "#]], | |
| ); | |
| } | |
| #[test] | |
| fn regression_21742() { | |
| check_no_mismatches( | |
| r#" | |
| pub trait IntoIterator { | |
| type Item; | |
| } | |
| pub trait Collection: IntoIterator<Item = <Self as Collection>::Item> { | |
| type Item; | |
| fn contains(&self, item: &<Self as Collection>::Item); | |
| } | |
| fn contains_0<S: Collection<Item = i32>>(points: &S) { | |
| points.contains(&0) | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21773() { | |
| check_no_mismatches( | |
| r#" | |
| trait Neg { | |
| type Output; | |
| } | |
| trait Abs: Neg { | |
| fn abs(&self) -> Self::Output; | |
| } | |
| trait SelfAbs: Abs + Neg | |
| where | |
| Self::Output: Neg<Output = Self::Output> + Abs, | |
| { | |
| } | |
| fn wrapped_abs<T: SelfAbs<Output = T>>(v: T) -> T { | |
| v.abs() | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21899() { | |
| check_no_mismatches( | |
| r#" | |
| trait B where | |
| Self::T: B, | |
| { | |
| type T; | |
| } | |
| fn foo<T: B>(v: T::T) {} | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22007() { | |
| check_types( | |
| r#" | |
| //- minicore: fn | |
| trait Super { | |
| type Assoc; | |
| fn foo(self) -> Self::Assoc | |
| where | |
| Self: Sub, | |
| { loop {} } | |
| } | |
| trait Sub: Super {} | |
| struct Struct; | |
| impl Super for Struct { | |
| type Assoc = u8; | |
| } | |
| impl Sub for Struct {} | |
| fn foo() { | |
| Struct.foo(); | |
| // ^^^^^^^^^^^^ u8 | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_21885() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: coerce_unsized, future, result | |
| use core::future::Future; | |
| trait Foo { | |
| type Assoc; | |
| fn foo() -> &dyn Future<Output = Result<Self::Assoc, ()>>; | |
| } | |
| struct Bar; | |
| impl Foo for Bar { | |
| type Assoc = NotFound; | |
| fn foo() -> &dyn Future<Output = Result<Self::Assoc, ()>> { | |
| &async { | |
| Err(()) | |
| } | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_unresolved_deferred_closure_call_resolution() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: fn | |
| fn caller() { | |
| let _: &[u8] = &(|| encode_fn())(); | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22772() { | |
| check_no_mismatches( | |
| r#" | |
| trait Resolve { | |
| type Prev; | |
| } | |
| fn migrations_preserve_index() { | |
| pub struct RefExpr1<'x> { | |
| pub foo: &'x schema::v0::_Ref0, | |
| } | |
| pub fn new_column<'x, C>() -> &'x C { | |
| loop {} | |
| } | |
| RefExpr1 { foo: new_column::<schema::Foo>() }; | |
| mod schema { | |
| pub struct Foo {} | |
| pub struct FooNew {} | |
| impl crate::Resolve for FooNew { | |
| type Prev = Foo; | |
| } | |
| pub mod v0 { | |
| pub type _Ref0 = <super::FooNew as crate::Resolve>::Prev; | |
| } | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn array_repeat_closure() { | |
| check( | |
| r#" | |
| fn f() {[_; || ()]} | |
| // ^^^^^^^^^^ expected (), got [{unknown}; _] | |
| // ^^^^^ expected usize, got impl Fn() | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22795() { | |
| check_no_mismatches( | |
| r#" | |
| trait T { fn m(&self); } | |
| impl T for Self::Self {} | |
| struct S; | |
| impl T for S { fn m(&self) {} } | |
| fn f(s: S) { s.m(); } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22799() { | |
| check_no_mismatches( | |
| r#" | |
| struct S; | |
| fn f() { | |
| <S as S>::S; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn braced_const_path() { | |
| check_types( | |
| r#" | |
| //- minicore: default, builtin_impls | |
| trait ToNum { | |
| type Num; | |
| } | |
| trait Bar { | |
| type Ty; | |
| } | |
| struct Gen<const B: bool>; | |
| struct Int<const B: bool>; | |
| impl<const B: bool> ToNum for Gen<{ B }> { | |
| type Num = Int<B>; | |
| } | |
| impl Bar for Int<true> { | |
| type Ty = i32; | |
| } | |
| impl Bar for Int<false> { | |
| type Ty = f32; | |
| } | |
| type A = <<Gen<true> as ToNum>::Num as Bar>::Ty; | |
| fn main() { | |
| let x = A::default(); | |
| // ^ i32 | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22820() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: copy | |
| trait MyTrait: Copy { | |
| const ASSOC: usize; | |
| } | |
| const fn output<T: MyTrait>(_: T) -> usize { | |
| <T as MyTrait>::ASSOC | |
| } | |
| const fn yeet() -> impl Clone { | |
| let x = [0u8; output(yeet())]; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn rpit_function_with_non_trivial_anon_const() { | |
| check_no_mismatches( | |
| r#" | |
| fn f() -> impl Sized { | |
| let x = [0u8; 1 + 2]; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_22986() { | |
| check_no_mismatches( | |
| r#" | |
| fn main() { | |
| let _: &[u8; 0] = b"\ | |
| "; | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_23065() { | |
| check_no_mismatches( | |
| r#" | |
| trait Trait { | |
| type Assoc<const N: usize>; | |
| } | |
| struct Struct; | |
| struct GenericStruct<'a>(&'a ()); | |
| impl<const X: usize> Trait for Struct { | |
| type Assoc<'a, const N: usize> = GenericStruct<'a>; | |
| fn g(&self) -> Self::Assoc<{ X }> { | |
| loop {} | |
| } | |
| } | |
| struct OtherStruct; | |
| impl Trait for OtherStruct { | |
| type Assoc<'a> = &'a (); | |
| } | |
| fn other() -> <OtherStruct as Trait>::Assoc<0> { | |
| loop {} | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_23083() { | |
| check_no_mismatches( | |
| r#" | |
| fn main() { | |
| match 2 { | |
| x if let true = return => { | |
| x; | |
| } | |
| _ => {} | |
| } | |
| } | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn dyn_trait_binder_inside_fn_ptr() { | |
| check_no_mismatches( | |
| r#" | |
| trait Trait<'a> {} | |
| fn f<'a>(_: fn() -> &'a dyn Trait<'a>) {} | |
| "#, | |
| ); | |
| } | |
| #[test] | |
| fn regression_23113() { | |
| check_no_mismatches( | |
| r#" | |
| //- minicore: range | |
| fn main() { | |
| 0..loop {}; | |
| } | |
| "#, | |
| ); | |
| } |