diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 61 |
2 files changed, 71 insertions, 10 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 573115321..887153484 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -27,8 +27,9 @@ use test_utils::tested_by; | |||
27 | 27 | ||
28 | use crate::{ | 28 | use crate::{ |
29 | Function, StructField, Path, Name, | 29 | Function, StructField, Path, Name, |
30 | FnSignature, AdtDef, | 30 | FnSignature, AdtDef,ConstSignature, |
31 | HirDatabase, | 31 | HirDatabase, |
32 | DefWithBody, | ||
32 | ImplItem, | 33 | ImplItem, |
33 | type_ref::{TypeRef, Mutability}, | 34 | type_ref::{TypeRef, Mutability}, |
34 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, | 35 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, |
@@ -43,14 +44,17 @@ use crate::{ | |||
43 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 44 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; |
44 | 45 | ||
45 | /// The entry point of type inference. | 46 | /// The entry point of type inference. |
46 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 47 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { |
47 | db.check_canceled(); | 48 | db.check_canceled(); |
48 | let body = func.body(db); | 49 | let body = def.body(db); |
49 | let resolver = func.resolver(db); | 50 | let resolver = def.resolver(db); |
50 | let mut ctx = InferenceContext::new(db, body, resolver); | 51 | let mut ctx = InferenceContext::new(db, body, resolver); |
51 | 52 | ||
52 | let signature = func.signature(db); | 53 | match def { |
53 | ctx.collect_fn_signature(&signature); | 54 | DefWithBody::Const(ref c) => ctx.collect_const_signature(&c.signature(db)), |
55 | DefWithBody::Function(ref f) => ctx.collect_fn_signature(&f.signature(db)), | ||
56 | DefWithBody::Static(ref s) => ctx.collect_const_signature(&s.signature(db)), | ||
57 | } | ||
54 | 58 | ||
55 | ctx.infer_body(); | 59 | ctx.infer_body(); |
56 | 60 | ||
@@ -1142,6 +1146,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1142 | ty | 1146 | ty |
1143 | } | 1147 | } |
1144 | 1148 | ||
1149 | fn collect_const_signature(&mut self, signature: &ConstSignature) { | ||
1150 | self.return_ty = self.make_ty(signature.type_ref()); | ||
1151 | } | ||
1152 | |||
1145 | fn collect_fn_signature(&mut self, signature: &FnSignature) { | 1153 | fn collect_fn_signature(&mut self, signature: &FnSignature) { |
1146 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1154 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1147 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | 1155 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 943c5499b..0b7c841df 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -11,6 +11,8 @@ use crate::{ | |||
11 | source_binder, | 11 | source_binder, |
12 | mock::MockDatabase, | 12 | mock::MockDatabase, |
13 | ty::display::HirDisplay, | 13 | ty::display::HirDisplay, |
14 | ty::InferenceResult, | ||
15 | expr::BodySourceMap | ||
14 | }; | 16 | }; |
15 | 17 | ||
16 | // 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 |
@@ -1267,6 +1269,9 @@ fn test() { | |||
1267 | } | 1269 | } |
1268 | "#), | 1270 | "#), |
1269 | @r###" | 1271 | @r###" |
1272 | [52; 53) '1': u32 | ||
1273 | [103; 104) '2': u32 | ||
1274 | [211; 212) '5': u32 | ||
1270 | [227; 305) '{ ...:ID; }': () | 1275 | [227; 305) '{ ...:ID; }': () |
1271 | [237; 238) 'x': u32 | 1276 | [237; 238) 'x': u32 |
1272 | [241; 252) 'Struct::FOO': u32 | 1277 | [241; 252) 'Struct::FOO': u32 |
@@ -1855,6 +1860,9 @@ fn test() { | |||
1855 | } | 1860 | } |
1856 | "#), | 1861 | "#), |
1857 | @r###" | 1862 | @r###" |
1863 | [49; 50) '0': u32 | ||
1864 | [80; 83) '101': u32 | ||
1865 | [126; 128) '99': u32 | ||
1858 | [95; 213) '{ ...NST; }': () | 1866 | [95; 213) '{ ...NST; }': () |
1859 | [138; 139) 'x': {unknown} | 1867 | [138; 139) 'x': {unknown} |
1860 | [142; 153) 'LOCAL_CONST': {unknown} | 1868 | [142; 153) 'LOCAL_CONST': {unknown} |
@@ -1881,6 +1889,10 @@ fn test() { | |||
1881 | } | 1889 | } |
1882 | "#), | 1890 | "#), |
1883 | @r###" | 1891 | @r###" |
1892 | [29; 32) '101': u32 | ||
1893 | [70; 73) '101': u32 | ||
1894 | [118; 120) '99': u32 | ||
1895 | [161; 163) '99': u32 | ||
1884 | [85; 280) '{ ...MUT; }': () | 1896 | [85; 280) '{ ...MUT; }': () |
1885 | [173; 174) 'x': {unknown} | 1897 | [173; 174) 'x': {unknown} |
1886 | [177; 189) 'LOCAL_STATIC': {unknown} | 1898 | [177; 189) 'LOCAL_STATIC': {unknown} |
@@ -2212,6 +2224,24 @@ fn test<T: Iterable<Item=u32>>() { | |||
2212 | ); | 2224 | ); |
2213 | } | 2225 | } |
2214 | 2226 | ||
2227 | #[test] | ||
2228 | fn infer_const_body() { | ||
2229 | assert_snapshot_matches!( | ||
2230 | infer(r#" | ||
2231 | const A: u32 = 1 + 1; | ||
2232 | static B: u64 = { let x = 1; x }; | ||
2233 | "#), | ||
2234 | @r###" | ||
2235 | [16; 17) '1': u32 | ||
2236 | [16; 21) '1 + 1': u32 | ||
2237 | [20; 21) '1': u32 | ||
2238 | [39; 55) '{ let ...1; x }': u64 | ||
2239 | [45; 46) 'x': u64 | ||
2240 | [49; 50) '1': u64 | ||
2241 | [52; 53) 'x': u64"### | ||
2242 | ); | ||
2243 | } | ||
2244 | |||
2215 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2245 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
2216 | let func = source_binder::function_from_position(db, pos).unwrap(); | 2246 | let func = source_binder::function_from_position(db, pos).unwrap(); |
2217 | let body_source_map = func.body_source_map(db); | 2247 | let body_source_map = func.body_source_map(db); |
@@ -2228,11 +2258,11 @@ fn infer(content: &str) -> String { | |||
2228 | let source_file = db.parse(file_id); | 2258 | let source_file = db.parse(file_id); |
2229 | let mut acc = String::new(); | 2259 | let mut acc = String::new(); |
2230 | acc.push_str("\n"); | 2260 | acc.push_str("\n"); |
2231 | for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) { | 2261 | |
2232 | let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); | 2262 | let mut infer_def = |inference_result: Arc<InferenceResult>, |
2233 | let inference_result = func.infer(&db); | 2263 | body_source_map: Arc<BodySourceMap>| { |
2234 | let body_source_map = func.body_source_map(&db); | ||
2235 | let mut types = Vec::new(); | 2264 | let mut types = Vec::new(); |
2265 | |||
2236 | for (pat, ty) in inference_result.type_of_pat.iter() { | 2266 | for (pat, ty) in inference_result.type_of_pat.iter() { |
2237 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 2267 | let syntax_ptr = match body_source_map.pat_syntax(pat) { |
2238 | Some(sp) => sp, | 2268 | Some(sp) => sp, |
@@ -2240,6 +2270,7 @@ fn infer(content: &str) -> String { | |||
2240 | }; | 2270 | }; |
2241 | types.push((syntax_ptr, ty)); | 2271 | types.push((syntax_ptr, ty)); |
2242 | } | 2272 | } |
2273 | |||
2243 | for (expr, ty) in inference_result.type_of_expr.iter() { | 2274 | for (expr, ty) in inference_result.type_of_expr.iter() { |
2244 | let syntax_ptr = match body_source_map.expr_syntax(expr) { | 2275 | let syntax_ptr = match body_source_map.expr_syntax(expr) { |
2245 | Some(sp) => sp, | 2276 | Some(sp) => sp, |
@@ -2258,7 +2289,29 @@ fn infer(content: &str) -> String { | |||
2258 | }; | 2289 | }; |
2259 | write!(acc, "{} '{}': {}\n", range, ellipsize(text, 15), ty.display(&db)).unwrap(); | 2290 | write!(acc, "{} '{}': {}\n", range, ellipsize(text, 15), ty.display(&db)).unwrap(); |
2260 | } | 2291 | } |
2292 | }; | ||
2293 | |||
2294 | for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) { | ||
2295 | let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap(); | ||
2296 | let inference_result = konst.infer(&db); | ||
2297 | let body_source_map = konst.body_source_map(&db); | ||
2298 | infer_def(inference_result, body_source_map) | ||
2261 | } | 2299 | } |
2300 | |||
2301 | for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) { | ||
2302 | let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap(); | ||
2303 | let inference_result = static_.infer(&db); | ||
2304 | let body_source_map = static_.body_source_map(&db); | ||
2305 | infer_def(inference_result, body_source_map) | ||
2306 | } | ||
2307 | |||
2308 | for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) { | ||
2309 | let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); | ||
2310 | let inference_result = func.infer(&db); | ||
2311 | let body_source_map = func.body_source_map(&db); | ||
2312 | infer_def(inference_result, body_source_map) | ||
2313 | } | ||
2314 | |||
2262 | acc.truncate(acc.trim_end().len()); | 2315 | acc.truncate(acc.trim_end().len()); |
2263 | acc | 2316 | acc |
2264 | } | 2317 | } |