use insta::assert_snapshot; use ra_db::fixture::WithFixture; use test_utils::mark; use crate::test_db::TestDB; use super::infer; #[test] fn bug_484() { assert_snapshot!( infer(r#" fn test() { let x = if true {}; } "#), @r###" 11..37 '{ l... {}; }': () 20..21 'x': () 24..34 'if true {}': () 27..31 'true': bool 32..34 '{}': () "### ); } #[test] fn no_panic_on_field_of_enum() { assert_snapshot!( infer(r#" enum X {} fn test(x: X) { x.some_field; } "#), @r###" 20..21 'x': X 26..47 '{ ...eld; }': () 32..33 'x': X 32..44 'x.some_field': {unknown} "### ); } #[test] fn bug_585() { assert_snapshot!( infer(r#" fn test() { X {}; match x { A::B {} => (), A::Y() => (), } } "#), @r###" 11..89 '{ ... } }': () 17..21 'X {}': {unknown} 27..87 'match ... }': () 33..34 'x': {unknown} 45..52 'A::B {}': {unknown} 56..58 '()': () 68..74 'A::Y()': {unknown} 78..80 '()': () "### ); } #[test] fn bug_651() { assert_snapshot!( infer(r#" fn quux() { let y = 92; 1 + y; } "#), @r###" 11..41 '{ ...+ y; }': () 21..22 'y': i32 25..27 '92': i32 33..34 '1': i32 33..38 '1 + y': i32 37..38 'y': i32 "### ); } #[test] fn recursive_vars() { mark::check!(type_var_cycles_resolve_completely); mark::check!(type_var_cycles_resolve_as_possible); assert_snapshot!( infer(r#" fn test() { let y = unknown; [y, &y]; } "#), @r###" 11..48 '{ ...&y]; }': () 21..22 'y': &{unknown} 25..32 'unknown': &{unknown} 38..45 '[y, &y]': [&&{unknown}; _] 39..40 'y': &{unknown} 42..44 '&y': &&{unknown} 43..44 'y': &{unknown} "### ); } #[test] fn recursive_vars_2() { assert_snapshot!( infer(r#" fn test() { let x = unknown; let y = unknown; [(x, y), (&y, &x)]; } "#), @r###" 11..80 '{ ...x)]; }': () 21..22 'x': &&{unknown} 25..32 'unknown': &&{unknown} 42..43 'y': &&{unknown} 46..53 'unknown': &&{unknown} 59..77 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] 60..66 '(x, y)': (&&&{unknown}, &&&{unknown}) 61..62 'x': &&{unknown} 64..65 'y': &&{unknown} 68..76 '(&y, &x)': (&&&{unknown}, &&&{unknown}) 69..71 '&y': &&&{unknown} 70..71 'y': &&{unknown} 73..75 '&x': &&&{unknown} 74..75 'x': &&{unknown} "### ); } #[test] fn infer_std_crash_1() { // caused stack overflow, taken from std assert_snapshot!( infer(r#" enum Maybe { Real(T), Fake, } fn write() { match something_unknown { Maybe::Real(ref mut something) => (), } } "#), @r###" 54..139 '{ ... } }': () 60..137 'match ... }': () 66..83 'someth...nknown': Maybe<{unknown}> 94..124 'Maybe:...thing)': Maybe<{unknown}> 106..123 'ref mu...ething': &mut {unknown} 128..130 '()': () "### ); } #[test] fn infer_std_crash_2() { mark::check!(type_var_resolves_to_int_var); // caused "equating two type variables, ...", taken from std assert_snapshot!( infer(r#" fn test_line_buffer() { &[0, b'\n', 1, b'\n']; } "#), @r###" 23..53 '{ ...n']; }': () 29..50 '&[0, b...b'\n']': &[u8; _] 30..50 '[0, b'...b'\n']': [u8; _] 31..32 '0': u8 34..39 'b'\n'': u8 41..42 '1': u8 44..49 'b'\n'': u8 "### ); } #[test] fn infer_std_crash_3() { // taken from rustc assert_snapshot!( infer(r#" pub fn compute() { match nope!() { SizeSkeleton::Pointer { non_zero: true, tail } => {} } } "#), @r###" 18..108 '{ ... } }': () 24..106 'match ... }': () 30..37 'nope!()': {unknown} 48..94 'SizeSk...tail }': {unknown} 82..86 'true': bool 82..86 'true': bool 88..92 'tail': {unknown} 98..100 '{}': () "### ); } #[test] fn infer_std_crash_4() { // taken from rustc assert_snapshot!( infer(r#" pub fn primitive_type() { match *self { BorrowedRef { type_: Primitive(p), ..} => {}, } } "#), @r###" 25..106 '{ ... } }': () 31..104 'match ... }': () 37..42 '*self': {unknown} 38..42 'self': {unknown} 53..91 'Borrow...), ..}': {unknown} 74..86 'Primitive(p)': {unknown} 84..85 'p': {unknown} 95..97 '{}': () "### ); } #[test] fn infer_std_crash_5() { // taken from rustc assert_snapshot!( 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 }; } } "#), @r###" 27..323 '{ ... } }': () 33..321 'for co... }': () 37..44 'content': &{unknown} 48..61 'doesnt_matter': {unknown} 62..321 '{ ... }': () 76..80 'name': &&{unknown} 83..167 'if doe... }': &&{unknown} 86..99 'doesnt_matter': bool 100..129 '{ ... }': &&{unknown} 114..119 'first': &&{unknown} 135..167 '{ ... }': &&{unknown} 149..157 '&content': &&{unknown} 150..157 'content': &{unknown} 182..189 'content': &{unknown} 192..314 'if ICE... }': &{unknown} 195..232 'ICE_RE..._VALUE': {unknown} 195..248 'ICE_RE...&name)': bool 242..247 '&name': &&&{unknown} 243..247 'name': &&{unknown} 249..277 '{ ... }': &&{unknown} 263..267 'name': &&{unknown} 283..314 '{ ... }': &{unknown} 297..304 'content': &{unknown} "### ); } #[test] fn infer_nested_generics_crash() { // another crash found typechecking rustc assert_snapshot!( infer(r#" struct Canonical { value: V, } struct QueryResponse { value: V, } fn test(query_response: Canonical>) { &query_response.value; } "#), @r###" 92..106 'query_response': Canonical> 137..167 '{ ...lue; }': () 143..164 '&query....value': &QueryResponse 144..158 'query_response': Canonical> 144..164 'query_....value': QueryResponse "### ); } #[test] fn infer_paren_macro_call() { assert_snapshot!( infer(r#" macro_rules! bar { () => {0u32} } fn test() { let a = (bar!()); } "#), @r###" !0..4 '0u32': u32 45..70 '{ ...()); }': () 55..56 'a': u32 "### ); } #[test] fn bug_1030() { assert_snapshot!(infer(r#" struct HashSet; struct FxHasher; type FxHashSet = HashSet; impl HashSet { fn default() -> HashSet {} } pub fn main_loop() { FxHashSet::default(); } "#), @r###" 144..146 '{}': () 169..198 '{ ...t(); }': () 175..193 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> 175..195 'FxHash...ault()': HashSet<{unknown}, FxHasher> "### ); } #[test] fn issue_2669() { assert_snapshot!( 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 {}; } } }"# ), @r###" 147..262 '{ ... }': () 161..164 'end': fn end<{unknown}>() 161..166 'end()': () 199..252 '{ ... }': () 221..223 '_x': ! 230..237 'loop {}': ! 235..237 '{}': () "### ) } #[test] fn issue_2705() { assert_snapshot!( infer(r#" trait Trait {} fn test() { >::foo() } "#), @r###" 26..53 '{ ...oo() }': () 32..49 '::foo': {unknown} 32..51 '; (chars.next(), chars.nth(1))<|>; } //- /std.rs crate:std #[prelude_import] use prelude::*; pub mod prelude { 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 {} } } "#, ); assert_eq!("(Option, Option)", super::type_at_pos(&db, pos)); } #[test] fn issue_3642_bad_macro_stackover() { let (db, pos) = TestDB::with_position( r#" //- /main.rs #[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 } }; }"#, ); assert_eq!("()", super::type_at_pos(&db, pos)); } #[test] fn issue_3999_slice() { assert_snapshot!( infer(r#" fn foo(params: &[usize]) { match params { [ps @ .., _] => {} } } "#), @r###" 8..14 'params': &[usize] 26..81 '{ ... } }': () 32..79 'match ... }': () 38..44 'params': &[usize] 55..67 '[ps @ .., _]': [usize] 65..66 '_': usize 71..73 '{}': () "### ); } #[test] fn issue_3999_struct() { // rust-analyzer should not panic on seeing this malformed // record pattern. assert_snapshot!( infer(r#" struct Bar { a: bool, } fn foo(b: Bar) { match b { Bar { a: .. } => {}, } } "#), @r###" 36..37 'b': Bar 44..96 '{ ... } }': () 50..94 'match ... }': () 56..57 'b': Bar 68..81 'Bar { a: .. }': Bar 77..79 '..': bool 85..87 '{}': () "### ); } #[test] fn issue_4235_name_conflicts() { assert_snapshot!( infer(r#" struct FOO {} static FOO:FOO = FOO {}; impl FOO { fn foo(&self) {} } fn main() { let a = &FOO; a.foo(); } "#), @r###" 32..38 'FOO {}': FOO 64..68 'self': &FOO 70..72 '{}': () 86..120 '{ ...o(); }': () 96..97 'a': &FOO 100..104 '&FOO': &FOO 101..104 'FOO': FOO 110..111 'a': &FOO 110..117 'a.foo()': () "### ); } #[test] fn issue_4465_dollar_crate_at_type() { assert_snapshot!( infer(r#" pub struct Foo {} pub fn anything() -> T { loop {} } macro_rules! foo { () => {{ let r: $crate::Foo = anything(); r }}; } fn main() { let _a = foo!(); } "#), @r###" 45..60 '{ loop {} }': T 51..58 'loop {}': ! 56..58 '{}': () !0..31 '{letr:...g();r}': Foo !4..5 'r': Foo !18..26 'anything': fn anything() -> Foo !18..28 'anything()': Foo !29..30 'r': Foo 164..188 '{ ...!(); }': () 174..176 '_a': Foo "###); } #[test] fn issue_4053_diesel_where_clauses() { assert_snapshot!( 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(); } } "#), @r###" 66..70 'self': Self 268..272 'self': Self 467..471 'self': SelectStatement 489..523 '{ ... }': () 499..503 'self': SelectStatement 499..509 'self.order': O 499..516 'self.o...into()': dyn QueryFragment "### ); } #[test] fn issue_4953() { assert_snapshot!( infer(r#" pub struct Foo(pub i64); impl Foo { fn test() -> Self { Self(0i64) } } "#), @r###" 59..73 '{ Self(0i64) }': Foo 61..65 'Self': Foo(i64) -> Foo 61..71 'Self(0i64)': Foo 66..70 '0i64': i64 "### ); assert_snapshot!( infer(r#" pub struct Foo(pub T); impl Foo { fn test() -> Self { Self(0i64) } } "#), @r###" 65..79 '{ Self(0i64) }': Foo 67..71 'Self': Foo(i64) -> Foo 67..77 'Self(0i64)': Foo 72..76 '0i64': i64 "### ); } #[test] fn issue_4931() { assert_snapshot!( infer(r#" trait Div { type Output; } trait CheckedDiv: Div<()> {} trait PrimInt: CheckedDiv { fn pow(self); } fn check(i: T) { i.pow(); } "#), @r###" 118..122 'self': Self 149..150 'i': T 155..171 '{ ...w(); }': () 161..162 'i': T 161..168 'i.pow()': () "### ); } #[test] fn issue_4885() { assert_snapshot!( 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, { } "#), @r###" 137..140 'key': &K 199..215 '{ ...key) }': impl Future>::Bar> 205..208 'bar': fn bar(&K) -> impl Future>::Bar> 205..213 'bar(key)': impl Future>::Bar> 209..212 'key': &K 229..232 'key': &K 291..294 '{ }': () "### ); } #[test] fn issue_4800() { assert_snapshot!( 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; } "#), @r###" 380..384 'self': &mut PeerSet 402..425 '{ ... }': dyn Future 412..419 'loop {}': ! 417..419 '{}': () 576..580 'self': &mut Self "### ); }