aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/tests.rs')
-rw-r--r--crates/ra_hir/src/ty/tests.rs115
1 files changed, 69 insertions, 46 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f6a325033..291bc9ae5 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -4,15 +4,15 @@ use std::fmt::Write;
4use insta::assert_snapshot_matches; 4use insta::assert_snapshot_matches;
5 5
6use ra_db::{SourceDatabase, salsa::Database, FilePosition}; 6use ra_db::{SourceDatabase, salsa::Database, FilePosition};
7use ra_syntax::{algo, ast::{self, AstNode}}; 7use ra_syntax::{algo, ast::{self, AstNode}, SyntaxKind::*};
8use test_utils::covers; 8use test_utils::covers;
9 9
10use crate::{ 10use crate::{
11 source_binder,
12 mock::MockDatabase, 11 mock::MockDatabase,
13 ty::display::HirDisplay, 12 ty::display::HirDisplay,
14 ty::InferenceResult, 13 ty::InferenceResult,
15 expr::BodySourceMap 14 expr::BodySourceMap,
15 SourceAnalyzer,
16}; 16};
17 17
18// These tests compare the inference results for all expressions in a file 18// These tests compare the inference results for all expressions in a file
@@ -1862,14 +1862,14 @@ fn test() {
1862 @r###" 1862 @r###"
1863[49; 50) '0': u32 1863[49; 50) '0': u32
1864[80; 83) '101': u32 1864[80; 83) '101': u32
1865[126; 128) '99': u32
1866[95; 213) '{ ...NST; }': () 1865[95; 213) '{ ...NST; }': ()
1867[138; 139) 'x': {unknown} 1866[138; 139) 'x': {unknown}
1868[142; 153) 'LOCAL_CONST': {unknown} 1867[142; 153) 'LOCAL_CONST': {unknown}
1869[163; 164) 'z': u32 1868[163; 164) 'z': u32
1870[167; 179) 'GLOBAL_CONST': u32 1869[167; 179) 'GLOBAL_CONST': u32
1871[189; 191) 'id': u32 1870[189; 191) 'id': u32
1872[194; 210) 'Foo::A..._CONST': u32"### 1871[194; 210) 'Foo::A..._CONST': u32
1872[126; 128) '99': u32"###
1873 ); 1873 );
1874} 1874}
1875 1875
@@ -1891,8 +1891,6 @@ fn test() {
1891 @r###" 1891 @r###"
1892[29; 32) '101': u32 1892[29; 32) '101': u32
1893[70; 73) '101': u32 1893[70; 73) '101': u32
1894[118; 120) '99': u32
1895[161; 163) '99': u32
1896[85; 280) '{ ...MUT; }': () 1894[85; 280) '{ ...MUT; }': ()
1897[173; 174) 'x': {unknown} 1895[173; 174) 'x': {unknown}
1898[177; 189) 'LOCAL_STATIC': {unknown} 1896[177; 189) 'LOCAL_STATIC': {unknown}
@@ -1901,7 +1899,9 @@ fn test() {
1901[229; 230) 'z': u32 1899[229; 230) 'z': u32
1902[233; 246) 'GLOBAL_STATIC': u32 1900[233; 246) 'GLOBAL_STATIC': u32
1903[256; 257) 'w': u32 1901[256; 257) 'w': u32
1904[260; 277) 'GLOBAL...IC_MUT': u32"### 1902[260; 277) 'GLOBAL...IC_MUT': u32
1903[118; 120) '99': u32
1904[161; 163) '99': u32"###
1905 ); 1905 );
1906} 1906}
1907 1907
@@ -1926,8 +1926,8 @@ fn test() {
1926} 1926}
1927"#), 1927"#),
1928 @r###" 1928 @r###"
1929[31; 35) 'self': &{unknown} 1929[31; 35) 'self': &Self
1930[110; 114) 'self': &{unknown} 1930[110; 114) 'self': &Self
1931[170; 228) '{ ...i128 }': () 1931[170; 228) '{ ...i128 }': ()
1932[176; 178) 'S1': S1 1932[176; 178) 'S1': S1
1933[176; 187) 'S1.method()': u32 1933[176; 187) 'S1.method()': u32
@@ -1972,8 +1972,8 @@ mod bar_test {
1972} 1972}
1973"#), 1973"#),
1974 @r###" 1974 @r###"
1975[63; 67) 'self': &{unknown} 1975[63; 67) 'self': &Self
1976[169; 173) 'self': &{unknown} 1976[169; 173) 'self': &Self
1977[300; 337) '{ ... }': () 1977[300; 337) '{ ... }': ()
1978[310; 311) 'S': S 1978[310; 311) 'S': S
1979[310; 320) 'S.method()': u32 1979[310; 320) 'S.method()': u32
@@ -1998,10 +1998,45 @@ fn test() {
1998} 1998}
1999"#), 1999"#),
2000 @r###" 2000 @r###"
2001[33; 37) 'self': &{unknown} 2001[33; 37) 'self': &Self
2002[92; 111) '{ ...d(); }': () 2002[92; 111) '{ ...d(); }': ()
2003[98; 99) 'S': S 2003[98; 99) 'S': S
2004[98; 108) 'S.method()': {unknown}"### 2004[98; 108) 'S.method()': u32"###
2005 );
2006}
2007
2008#[test]
2009fn infer_trait_method_generic_more_params() {
2010 // the trait implementation is intentionally incomplete -- it shouldn't matter
2011 assert_snapshot_matches!(
2012 infer(r#"
2013trait Trait<T1, T2, T3> {
2014 fn method1(&self) -> (T1, T2, T3);
2015 fn method2(&self) -> (T3, T2, T1);
2016}
2017struct S1;
2018impl Trait<u8, u16, u32> for S1 {}
2019struct S2;
2020impl<T> Trait<i8, i16, T> for S2 {}
2021fn test() {
2022 S1.method1(); // u8, u16, u32
2023 S1.method2(); // u32, u16, u8
2024 S2.method1(); // i8, i16, {unknown}
2025 S2.method2(); // {unknown}, i16, i8
2026}
2027"#),
2028 @r###"
2029[43; 47) 'self': &Self
2030[82; 86) 'self': &Self
2031[210; 361) '{ ..., i8 }': ()
2032[216; 218) 'S1': S1
2033[216; 228) 'S1.method1()': (u8, u16, u32)
2034[250; 252) 'S1': S1
2035[250; 262) 'S1.method2()': (u32, u16, u8)
2036[284; 286) 'S2': S2
2037[284; 296) 'S2.method1()': (i8, i16, {unknown})
2038[324; 326) 'S2': S2
2039[324; 336) 'S2.method2()': ({unknown}, i16, i8)"###
2005 ); 2040 );
2006} 2041}
2007 2042
@@ -2020,7 +2055,7 @@ fn test() {
2020} 2055}
2021"#), 2056"#),
2022 @r###" 2057 @r###"
2023[33; 37) 'self': &{unknown} 2058[33; 37) 'self': &Self
2024[102; 127) '{ ...d(); }': () 2059[102; 127) '{ ...d(); }': ()
2025[108; 109) 'S': S<u32>(T) -> S<T> 2060[108; 109) 'S': S<u32>(T) -> S<T>
2026[108; 115) 'S(1u32)': S<u32> 2061[108; 115) 'S(1u32)': S<u32>
@@ -2168,7 +2203,7 @@ fn test() {
2168} 2203}
2169"#), 2204"#),
2170 @r###" 2205 @r###"
2171[29; 33) 'self': {unknown} 2206[29; 33) 'self': Self
2172[107; 198) '{ ...(S); }': () 2207[107; 198) '{ ...(S); }': ()
2173[117; 118) 'x': u32 2208[117; 118) 'x': u32
2174[126; 127) 'S': S 2209[126; 127) 'S': S
@@ -2302,13 +2337,10 @@ fn test() -> u64 {
2302} 2337}
2303 2338
2304fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2339fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2305 let func = source_binder::function_from_position(db, pos).unwrap(); 2340 let file = db.parse(pos.file_id);
2306 let body_source_map = func.body_source_map(db); 2341 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
2307 let inference_result = func.infer(db); 2342 let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset));
2308 let (_, syntax) = func.source(db); 2343 let ty = analyzer.type_of(db, expr).unwrap();
2309 let node = algo::find_node_at_offset::<ast::Expr>(syntax.syntax(), pos.offset).unwrap();
2310 let expr = body_source_map.node_expr(node).unwrap();
2311 let ty = &inference_result[expr];
2312 ty.display(db).to_string() 2344 ty.display(db).to_string()
2313} 2345}
2314 2346
@@ -2324,7 +2356,7 @@ fn infer(content: &str) -> String {
2324 2356
2325 for (pat, ty) in inference_result.type_of_pat.iter() { 2357 for (pat, ty) in inference_result.type_of_pat.iter() {
2326 let syntax_ptr = match body_source_map.pat_syntax(pat) { 2358 let syntax_ptr = match body_source_map.pat_syntax(pat) {
2327 Some(sp) => sp, 2359 Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()),
2328 None => continue, 2360 None => continue,
2329 }; 2361 };
2330 types.push((syntax_ptr, ty)); 2362 types.push((syntax_ptr, ty));
@@ -2350,25 +2382,11 @@ fn infer(content: &str) -> String {
2350 } 2382 }
2351 }; 2383 };
2352 2384
2353 for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) { 2385 for node in source_file.syntax().descendants() {
2354 let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap(); 2386 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
2355 let inference_result = konst.infer(&db); 2387 let analyzer = SourceAnalyzer::new(&db, file_id, node, None);
2356 let body_source_map = konst.body_source_map(&db); 2388 infer_def(analyzer.inference_result(), analyzer.body_source_map());
2357 infer_def(inference_result, body_source_map) 2389 }
2358 }
2359
2360 for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) {
2361 let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap();
2362 let inference_result = static_.infer(&db);
2363 let body_source_map = static_.body_source_map(&db);
2364 infer_def(inference_result, body_source_map)
2365 }
2366
2367 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
2368 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
2369 let inference_result = func.infer(&db);
2370 let body_source_map = func.body_source_map(&db);
2371 infer_def(inference_result, body_source_map)
2372 } 2390 }
2373 2391
2374 acc.truncate(acc.trim_end().len()); 2392 acc.truncate(acc.trim_end().len());
@@ -2403,10 +2421,12 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
2403 } 2421 }
2404 ", 2422 ",
2405 ); 2423 );
2406 let func = source_binder::function_from_position(&db, pos).unwrap();
2407 { 2424 {
2425 let file = db.parse(pos.file_id);
2426 let node =
2427 algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent();
2408 let events = db.log_executed(|| { 2428 let events = db.log_executed(|| {
2409 func.infer(&db); 2429 SourceAnalyzer::new(&db, pos.file_id, node, None);
2410 }); 2430 });
2411 assert!(format!("{:?}", events).contains("infer")) 2431 assert!(format!("{:?}", events).contains("infer"))
2412 } 2432 }
@@ -2423,8 +2443,11 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
2423 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); 2443 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text));
2424 2444
2425 { 2445 {
2446 let file = db.parse(pos.file_id);
2447 let node =
2448 algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent();
2426 let events = db.log_executed(|| { 2449 let events = db.log_executed(|| {
2427 func.infer(&db); 2450 SourceAnalyzer::new(&db, pos.file_id, node, None);
2428 }); 2451 });
2429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 2452 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
2430 } 2453 }