aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs20
-rw-r--r--crates/ra_hir/src/ty/tests.rs61
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
28use crate::{ 28use 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::{
43use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; 44use 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.
46pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 47pub 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 655f3c522..1e84e2d06 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]
2228fn infer_const_body() {
2229 assert_snapshot_matches!(
2230 infer(r#"
2231const A: u32 = 1 + 1;
2232static 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
2215fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2245fn 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,
@@ -2260,7 +2291,29 @@ fn infer(content: &str) -> String {
2260 ) 2291 )
2261 .unwrap(); 2292 .unwrap();
2262 } 2293 }
2294 };
2295
2296 for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) {
2297 let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap();
2298 let inference_result = konst.infer(&db);
2299 let body_source_map = konst.body_source_map(&db);
2300 infer_def(inference_result, body_source_map)
2263 } 2301 }
2302
2303 for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) {
2304 let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap();
2305 let inference_result = static_.infer(&db);
2306 let body_source_map = static_.body_source_map(&db);
2307 infer_def(inference_result, body_source_map)
2308 }
2309
2310 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
2311 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
2312 let inference_result = func.infer(&db);
2313 let body_source_map = func.body_source_map(&db);
2314 infer_def(inference_result, body_source_map)
2315 }
2316
2264 acc.truncate(acc.trim_end().len()); 2317 acc.truncate(acc.trim_end().len());
2265 acc 2318 acc
2266} 2319}