use expect_test::expect; use super::{check_infer, check_types}; #[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 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() { 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 infer_std_crash_1() { // caused stack overflow, taken from std check_infer( r#" enum Maybe { 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#" 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... }': () 36..43 'content': {unknown} 47..60 'doesnt_matter': {unknown} 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 { value: V, } struct QueryResponse { value: V, } fn test(query_response: Canonical>) { &query_response.value; } "#, expect![[r#" 91..105 'query_response': Canonical> 136..166 '{ ...lue; }': () 142..163 '&query....value': &QueryResponse 143..157 'query_response': Canonical> 143..163 'query_....value': QueryResponse "#]], ); } #[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; struct FxHasher; type FxHashSet = HashSet; impl HashSet { fn default() -> HashSet {} } pub fn main_loop() { FxHashSet::default(); } "#, expect![[r#" 143..145 '{}': () 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 {} trait D { fn foo(); } impl D for Response { fn foo() { end(); fn end() { let _x: T = loop {}; } } } "#, expect![[r#" 119..214 '{ ... }': () 129..132 'end': fn end<{unknown}>() 129..134 'end()': () 163..208 '{ ... }': () 181..183 '_x': ! 190..197 'loop {}': ! 195..197 '{}': () "#]], ) } #[test] fn issue_2705() { check_infer( r#" trait Trait {} fn test() { >::foo() } "#, expect![[r#" 25..52 '{ ...oo() }': () 31..48 '::foo': {unknown} 31..50 '; (chars.next(), chars.nth(1)); } //^ (Option, Option) //- /std.rs crate:std #[prelude_import] use self::prelude::rust_2018::*; pub mod prelude { pub mod rust_2018 { pub use crate::iter::Iterator; pub use crate::option::Option; } } pub mod iter { pub use self::traits::Iterator; pub mod traits { pub use self::iterator::Iterator; pub mod iterator { pub trait Iterator { type Item; fn next(&mut self) -> Option; fn nth(&mut self, n: usize) -> Option {} } } } } pub mod option { pub enum Option {} } pub mod str { pub struct Chars<'a> {} impl<'a> Iterator for Chars<'a> { type Item = char; fn next(&mut self) -> Option {} } } "#, ); } #[test] fn issue_3642_bad_macro_stackover() { check_types( r#" #[macro_export] macro_rules! match_ast { (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; (match ($node:expr) { $( ast::$ast:ident($it:ident) => $res:expr, )* _ => $catch_all:expr $(,)? }) => {{ $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )* { $catch_all } }}; } fn main() { let anchor = match_ast! { //^ () match parent { as => {}, _ => return None } }; }"#, ); } #[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 { 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 !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 { type Output; fn internal_into_boxed(self) -> Self::Output; } struct SelectStatement { order: Order, } trait QueryFragment {} trait Into { fn into(self) -> T; } impl BoxedDsl for SelectStatement where O: Into>, { type Output = XXX; fn internal_into_boxed(self) -> Self::Output { self.order.into(); } } "#, expect![[r#" 65..69 'self': Self 267..271 'self': Self 466..470 'self': SelectStatement 488..522 '{ ... }': () 498..502 'self': SelectStatement 498..508 'self.order': O 498..515 'self.o...into()': dyn QueryFragment "#]], ); } #[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': Foo(i64) -> Foo 60..70 'Self(0i64)': Foo 65..69 '0i64': i64 "#]], ); check_infer( r#" pub struct Foo(pub T); impl Foo { fn test() -> Self { Self(0i64) } } "#, expect![[r#" 64..78 '{ Self(0i64) }': Foo 66..70 'Self': Foo(i64) -> Foo 66..76 'Self(0i64)': Foo 71..75 '0i64': i64 "#]], ); } #[test] fn issue_4931() { check_infer( r#" trait Div { type Output; } trait CheckedDiv: Div<()> {} trait PrimInt: CheckedDiv { fn pow(self); } fn check(i: T) { i.pow(); } "#, expect![[r#" 117..121 'self': Self 148..149 'i': T 154..170 '{ ...w(); }': () 160..161 'i': T 160..167 'i.pow()': () "#]], ); } #[test] fn issue_4885() { check_infer( r#" #[lang = "coerce_unsized"] pub trait CoerceUnsized {} trait Future { type Output; } trait Foo { type Bar; } fn foo(key: &K) -> impl Future where K: Foo, { bar(key) } fn bar(key: &K) -> impl Future where K: Foo, { } "#, expect![[r#" 136..139 'key': &K 198..214 '{ ...key) }': impl Future>::Bar> 204..207 'bar': fn bar(&K) -> impl Future>::Bar> 204..212 'bar(key)': impl Future>::Bar> 208..211 'key': &K 228..231 'key': &K 290..293 '{ }': () "#]], ); } #[test] fn issue_4800() { check_infer( r#" trait Debug {} struct Foo; type E1 = (T, T, T); type E2 = E1>>; impl Debug for Foo> {} struct Request; pub trait Future { type Output; } pub struct PeerSet; impl Service for PeerSet where D: Discover, D::Key: Debug, { type Error = (); type Future = dyn Future; fn call(&mut self) -> Self::Future { loop {} } } pub trait Discover { type Key; } pub trait Service { type Error; type Future: Future; fn call(&mut self) -> Self::Future; } "#, expect![[r#" 379..383 'self': &mut PeerSet 401..424 '{ ... }': dyn Future 411..418 'loop {}': ! 416..418 '{}': () 575..579 'self': &mut Self "#]], ); } #[test] fn issue_4966() { check_infer( r#" pub trait IntoIterator { type Item; } struct Repeat { element: A } struct Map { f: F } struct Vec {} #[lang = "deref"] pub trait Deref { type Target; } impl Deref for Vec { type Target = [T]; } fn from_iter>(iter: T) -> Vec {} fn main() { let inner = Map { f: |_: &f64| 0.0 }; let repeat = Repeat { element: inner }; let vec = from_iter(repeat); vec.foo_bar(); } "#, expect![[r#" 270..274 'iter': T 289..291 '{}': () 303..447 '{ ...r(); }': () 313..318 'inner': Map<|&f64| -> f64> 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> 330..343 '|_: &f64| 0.0': |&f64| -> f64 331..332 '_': &f64 340..343 '0.0': f64 356..362 'repeat': Repeat f64>> 365..390 'Repeat...nner }': Repeat f64>> 383..388 'inner': Map<|&f64| -> f64> 401..404 'vec': Vec f64>>>> 407..416 'from_iter': fn from_iter f64>>>, Repeat f64>>>(Repeat f64>>) -> Vec f64>>>> 407..424 'from_i...epeat)': Vec f64>>>> 417..423 'repeat': Repeat f64>> 431..434 'vec': Vec f64>>>> 431..444 'vec.foo_bar()': {unknown} "#]], ); } #[test] fn issue_6628() { check_infer( r#" //- minicore: fn struct S(); impl S { fn f(&self, _t: T) {} fn g(&self, _f: F) {} } fn main() { let s = S(); s.g(|_x| {}); s.f(10); } "#, expect![[r#" 40..44 'self': &S 46..48 '_t': T 53..55 '{}': () 81..85 'self': &S 87..89 '_f': F 94..96 '{}': () 109..160 '{ ...10); }': () 119..120 's': S 123..124 'S': S() -> S 123..126 'S()': S 132..133 's': S 132..144 's.g(|_x| {})': () 136..143 '|_x| {}': |&i32| -> () 137..139 '_x': &i32 141..143 '{}': () 150..151 's': S 150..157 's.f(10)': () 154..156 '10': i32 "#]], ); } #[test] fn issue_6852() { check_infer( r#" //- minicore: deref use core::ops::Deref; struct BufWriter {} struct Mutex {} struct MutexGuard<'a, T> {} impl Mutex { fn lock(&self) -> MutexGuard<'_, T> {} } impl<'a, T: 'a> Deref for MutexGuard<'a, T> { type Target = T; } fn flush(&self) { let w: &Mutex; *(w.lock()); } "#, expect![[r#" 123..127 'self': &Mutex 150..152 '{}': () 234..238 'self': &{unknown} 240..290 '{ ...()); }': () 250..251 'w': &Mutex 276..287 '*(w.lock())': BufWriter 278..279 'w': &Mutex 278..286 'w.lock()': MutexGuard "#]], ); } #[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 {} impl core::ops::Deref for Box { type Target = T; fn deref(&self) -> &Self::Target { loop {} } } trait Iterator { type Item; } pub struct Iter<'a, T: 'a> { inner: Box + 'a>, } trait IterTrait<'a, T: 'a>: Iterator { fn clone_box(&self); } fn clone_iter(s: Iter) { s.inner.clone_box(); //^^^^^^^^^^^^^^^^^^^ () } "#, ) } #[test] fn issue_8686() { check_infer( r#" pub trait Try: FromResidual { type Output; type Residual; } pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; } struct ControlFlow; impl Try for ControlFlow { type Output = C; type Residual = ControlFlow; } impl FromResidual for ControlFlow { fn from_residual(r: ControlFlow) -> Self { ControlFlow } } fn test() { ControlFlow::from_residual(ControlFlow::); } "#, expect![[r#" 144..152 'residual': R 365..366 'r': ControlFlow 395..410 '{ ControlFlow }': ControlFlow 397..408 'ControlFlow': ControlFlow 424..482 '{ ...!>); }': () 430..456 'Contro...sidual': fn from_residual, ControlFlow>(ControlFlow) -> ControlFlow 430..479 'Contro...2, !>)': ControlFlow 457..478 'Contro...32, !>': ControlFlow "#]], ); } #[test] fn cfg_tail() { // https://github.com/rust-analyzer/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 }': &str 20..31 '{ "first" }': &str 22..29 '"first"': &str 72..190 '{ ...] 13 }': &str 78..88 '{ "fake" }': &str 80..86 '"fake"': &str 93..103 '{ "fake" }': &str 95..101 '"fake"': &str 108..120 '{ "second" }': &str 110..118 '"second"': &str 210..273 '{ ... 15; }': &str 216..227 '{ "third" }': &str 218..225 '"third"': &str 293..357 '{ ...] 15 }': () 299..311 '{ "fourth" }': &str 301..309 '"fourth"': &str "#]], ) }