diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 195 |
1 files changed, 127 insertions, 68 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 615a1caed..13ee6cb27 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -5,21 +5,17 @@ mod tests; | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use log; | ||
8 | use rustc_hash::{FxHashMap}; | 9 | use rustc_hash::{FxHashMap}; |
9 | 10 | ||
10 | use ra_db::LocalSyntaxPtr; | 11 | use ra_db::{LocalSyntaxPtr, Cancelable}; |
11 | use ra_syntax::{ | 12 | use ra_syntax::{ |
12 | SmolStr, | 13 | SmolStr, |
13 | ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, | 14 | ast::{self, AstNode, LoopBodyOwner, ArgListOwner}, |
14 | SyntaxNodeRef | 15 | SyntaxNodeRef |
15 | }; | 16 | }; |
16 | 17 | ||
17 | use crate::{ | 18 | use crate::{Def, DefId, FnScopes, Module, Function, Path, db::HirDatabase}; |
18 | FnScopes, | ||
19 | db::HirDatabase, | ||
20 | }; | ||
21 | |||
22 | // pub(crate) type TypeId = Id<Ty>; | ||
23 | 19 | ||
24 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 20 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
25 | pub enum Ty { | 21 | pub enum Ty { |
@@ -65,18 +61,6 @@ pub enum Ty { | |||
65 | /// `&'a mut T` or `&'a T`. | 61 | /// `&'a mut T` or `&'a T`. |
66 | // Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), | 62 | // Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), |
67 | 63 | ||
68 | /// The anonymous type of a function declaration/definition. Each | ||
69 | /// function has a unique type, which is output (for a function | ||
70 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
71 | /// | ||
72 | /// For example the type of `bar` here: | ||
73 | /// | ||
74 | /// ```rust | ||
75 | /// fn foo() -> i32 { 1 } | ||
76 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
77 | /// ``` | ||
78 | // FnDef(DefId, &'tcx Substs<'tcx>), | ||
79 | |||
80 | /// A pointer to a function. Written as `fn() -> i32`. | 64 | /// A pointer to a function. Written as `fn() -> i32`. |
81 | /// | 65 | /// |
82 | /// For example the type of `bar` here: | 66 | /// For example the type of `bar` here: |
@@ -85,7 +69,7 @@ pub enum Ty { | |||
85 | /// fn foo() -> i32 { 1 } | 69 | /// fn foo() -> i32 { 1 } |
86 | /// let bar: fn() -> i32 = foo; | 70 | /// let bar: fn() -> i32 = foo; |
87 | /// ``` | 71 | /// ``` |
88 | // FnPtr(PolyFnSig<'tcx>), | 72 | FnPtr(Arc<FnSig>), |
89 | 73 | ||
90 | /// A trait, defined with `trait`. | 74 | /// A trait, defined with `trait`. |
91 | // Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), | 75 | // Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), |
@@ -139,6 +123,12 @@ pub enum Ty { | |||
139 | 123 | ||
140 | type TyRef = Arc<Ty>; | 124 | type TyRef = Arc<Ty>; |
141 | 125 | ||
126 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | ||
127 | pub struct FnSig { | ||
128 | input: Vec<Ty>, | ||
129 | output: Ty, | ||
130 | } | ||
131 | |||
142 | impl Ty { | 132 | impl Ty { |
143 | pub fn new(node: ast::TypeRef) -> Self { | 133 | pub fn new(node: ast::TypeRef) -> Self { |
144 | use ra_syntax::ast::TypeRef::*; | 134 | use ra_syntax::ast::TypeRef::*; |
@@ -208,11 +198,55 @@ impl fmt::Display for Ty { | |||
208 | } | 198 | } |
209 | write!(f, ")") | 199 | write!(f, ")") |
210 | } | 200 | } |
201 | Ty::FnPtr(sig) => { | ||
202 | write!(f, "fn(")?; | ||
203 | for t in &sig.input { | ||
204 | write!(f, "{},", t)?; | ||
205 | } | ||
206 | write!(f, ") -> {}", sig.output) | ||
207 | } | ||
211 | Ty::Unknown => write!(f, "[unknown]"), | 208 | Ty::Unknown => write!(f, "[unknown]"), |
212 | } | 209 | } |
213 | } | 210 | } |
214 | } | 211 | } |
215 | 212 | ||
213 | pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | ||
214 | eprintln!("type_for_fn {:?}", f.fn_id); | ||
215 | let syntax = f.syntax(db); | ||
216 | let node = syntax.borrowed(); | ||
217 | // TODO we ignore type parameters for now | ||
218 | let input = node | ||
219 | .param_list() | ||
220 | .map(|pl| { | ||
221 | pl.params() | ||
222 | .map(|p| p.type_ref().map(|t| Ty::new(t)).unwrap_or(Ty::Unknown)) | ||
223 | .collect() | ||
224 | }) | ||
225 | .unwrap_or_else(Vec::new); | ||
226 | let output = node | ||
227 | .ret_type() | ||
228 | .and_then(|rt| rt.type_ref()) | ||
229 | .map(|t| Ty::new(t)) | ||
230 | .unwrap_or(Ty::Unknown); | ||
231 | let sig = FnSig { input, output }; | ||
232 | Ok(Ty::FnPtr(Arc::new(sig))) | ||
233 | } | ||
234 | |||
235 | pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | ||
236 | let def = def_id.resolve(db)?; | ||
237 | match def { | ||
238 | Def::Module(..) => { | ||
239 | log::debug!("trying to get type for module {:?}", def_id); | ||
240 | Ok(Ty::Unknown) | ||
241 | } | ||
242 | Def::Function(f) => type_for_fn(db, f), | ||
243 | Def::Item => { | ||
244 | log::debug!("trying to get type for item of unknown type {:?}", def_id); | ||
245 | Ok(Ty::Unknown) | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
216 | #[derive(Clone, PartialEq, Eq, Debug)] | 250 | #[derive(Clone, PartialEq, Eq, Debug)] |
217 | pub struct InferenceResult { | 251 | pub struct InferenceResult { |
218 | type_for: FxHashMap<LocalSyntaxPtr, Ty>, | 252 | type_for: FxHashMap<LocalSyntaxPtr, Ty>, |
@@ -224,18 +258,22 @@ impl InferenceResult { | |||
224 | } | 258 | } |
225 | } | 259 | } |
226 | 260 | ||
227 | #[derive(Clone, PartialEq, Eq, Debug)] | 261 | #[derive(Clone, Debug)] |
228 | pub struct InferenceContext { | 262 | pub struct InferenceContext<'a, D: HirDatabase> { |
263 | db: &'a D, | ||
229 | scopes: Arc<FnScopes>, | 264 | scopes: Arc<FnScopes>, |
265 | module: Module, | ||
230 | // TODO unification tables... | 266 | // TODO unification tables... |
231 | type_for: FxHashMap<LocalSyntaxPtr, Ty>, | 267 | type_for: FxHashMap<LocalSyntaxPtr, Ty>, |
232 | } | 268 | } |
233 | 269 | ||
234 | impl InferenceContext { | 270 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
235 | fn new(scopes: Arc<FnScopes>) -> Self { | 271 | fn new(db: &'a D, scopes: Arc<FnScopes>, module: Module) -> Self { |
236 | InferenceContext { | 272 | InferenceContext { |
237 | type_for: FxHashMap::default(), | 273 | type_for: FxHashMap::default(), |
274 | db, | ||
238 | scopes, | 275 | scopes, |
276 | module, | ||
239 | } | 277 | } |
240 | } | 278 | } |
241 | 279 | ||
@@ -262,36 +300,42 @@ impl InferenceContext { | |||
262 | self.unify(ty1, ty2) | 300 | self.unify(ty1, ty2) |
263 | } | 301 | } |
264 | 302 | ||
265 | fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Option<Ty> { | 303 | fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Cancelable<Option<Ty>> { |
266 | let p = expr.path()?; | 304 | let ast_path = ctry!(expr.path()); |
267 | if p.qualifier().is_none() { | 305 | let path = ctry!(Path::from_ast(ast_path)); |
268 | let name = p.segment().and_then(|s| s.name_ref())?; | 306 | if path.is_ident() { |
269 | let scope_entry = self.scopes.resolve_local_name(name)?; | 307 | // resolve locally |
270 | let ty = self.type_for.get(&scope_entry.ptr())?; | 308 | let name = ctry!(ast_path.segment().and_then(|s| s.name_ref())); |
271 | Some(ty.clone()) | 309 | if let Some(scope_entry) = self.scopes.resolve_local_name(name) { |
272 | } else { | 310 | let ty = ctry!(self.type_for.get(&scope_entry.ptr())); |
273 | // TODO resolve path | 311 | return Ok(Some(ty.clone())); |
274 | Some(Ty::Unknown) | 312 | }; |
275 | } | 313 | }; |
314 | |||
315 | // resolve in module | ||
316 | let resolved = ctry!(self.module.resolve_path(self.db, path)?); | ||
317 | let ty = self.db.type_for_def(resolved)?; | ||
318 | // TODO we will need to add type variables for type parameters etc. here | ||
319 | Ok(Some(ty)) | ||
276 | } | 320 | } |
277 | 321 | ||
278 | fn infer_expr(&mut self, expr: ast::Expr) -> Ty { | 322 | fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> { |
279 | let ty = match expr { | 323 | let ty = match expr { |
280 | ast::Expr::IfExpr(e) => { | 324 | ast::Expr::IfExpr(e) => { |
281 | if let Some(condition) = e.condition() { | 325 | if let Some(condition) = e.condition() { |
282 | if let Some(e) = condition.expr() { | 326 | if let Some(e) = condition.expr() { |
283 | // TODO if no pat, this should be bool | 327 | // TODO if no pat, this should be bool |
284 | self.infer_expr(e); | 328 | self.infer_expr(e)?; |
285 | } | 329 | } |
286 | // TODO write type for pat | 330 | // TODO write type for pat |
287 | }; | 331 | }; |
288 | let if_ty = if let Some(block) = e.then_branch() { | 332 | let if_ty = if let Some(block) = e.then_branch() { |
289 | self.infer_block(block) | 333 | self.infer_block(block)? |
290 | } else { | 334 | } else { |
291 | Ty::Unknown | 335 | Ty::Unknown |
292 | }; | 336 | }; |
293 | let else_ty = if let Some(block) = e.else_branch() { | 337 | let else_ty = if let Some(block) = e.else_branch() { |
294 | self.infer_block(block) | 338 | self.infer_block(block)? |
295 | } else { | 339 | } else { |
296 | Ty::Unknown | 340 | Ty::Unknown |
297 | }; | 341 | }; |
@@ -304,14 +348,14 @@ impl InferenceContext { | |||
304 | } | 348 | } |
305 | ast::Expr::BlockExpr(e) => { | 349 | ast::Expr::BlockExpr(e) => { |
306 | if let Some(block) = e.block() { | 350 | if let Some(block) = e.block() { |
307 | self.infer_block(block) | 351 | self.infer_block(block)? |
308 | } else { | 352 | } else { |
309 | Ty::Unknown | 353 | Ty::Unknown |
310 | } | 354 | } |
311 | } | 355 | } |
312 | ast::Expr::LoopExpr(e) => { | 356 | ast::Expr::LoopExpr(e) => { |
313 | if let Some(block) = e.loop_body() { | 357 | if let Some(block) = e.loop_body() { |
314 | self.infer_block(block); | 358 | self.infer_block(block)?; |
315 | }; | 359 | }; |
316 | // TODO never, or the type of the break param | 360 | // TODO never, or the type of the break param |
317 | Ty::Unknown | 361 | Ty::Unknown |
@@ -320,59 +364,69 @@ impl InferenceContext { | |||
320 | if let Some(condition) = e.condition() { | 364 | if let Some(condition) = e.condition() { |
321 | if let Some(e) = condition.expr() { | 365 | if let Some(e) = condition.expr() { |
322 | // TODO if no pat, this should be bool | 366 | // TODO if no pat, this should be bool |
323 | self.infer_expr(e); | 367 | self.infer_expr(e)?; |
324 | } | 368 | } |
325 | // TODO write type for pat | 369 | // TODO write type for pat |
326 | }; | 370 | }; |
327 | if let Some(block) = e.loop_body() { | 371 | if let Some(block) = e.loop_body() { |
328 | // TODO | 372 | // TODO |
329 | self.infer_block(block); | 373 | self.infer_block(block)?; |
330 | }; | 374 | }; |
331 | // TODO always unit? | 375 | // TODO always unit? |
332 | Ty::Unknown | 376 | Ty::Unknown |
333 | } | 377 | } |
334 | ast::Expr::ForExpr(e) => { | 378 | ast::Expr::ForExpr(e) => { |
335 | if let Some(expr) = e.iterable() { | 379 | if let Some(expr) = e.iterable() { |
336 | self.infer_expr(expr); | 380 | self.infer_expr(expr)?; |
337 | } | 381 | } |
338 | if let Some(_pat) = e.pat() { | 382 | if let Some(_pat) = e.pat() { |
339 | // TODO write type for pat | 383 | // TODO write type for pat |
340 | } | 384 | } |
341 | if let Some(block) = e.loop_body() { | 385 | if let Some(block) = e.loop_body() { |
342 | self.infer_block(block); | 386 | self.infer_block(block)?; |
343 | } | 387 | } |
344 | // TODO always unit? | 388 | // TODO always unit? |
345 | Ty::Unknown | 389 | Ty::Unknown |
346 | } | 390 | } |
347 | ast::Expr::LambdaExpr(e) => { | 391 | ast::Expr::LambdaExpr(e) => { |
348 | let _body_ty = if let Some(body) = e.body() { | 392 | let _body_ty = if let Some(body) = e.body() { |
349 | self.infer_expr(body) | 393 | self.infer_expr(body)? |
350 | } else { | 394 | } else { |
351 | Ty::Unknown | 395 | Ty::Unknown |
352 | }; | 396 | }; |
353 | Ty::Unknown | 397 | Ty::Unknown |
354 | } | 398 | } |
355 | ast::Expr::CallExpr(e) => { | 399 | ast::Expr::CallExpr(e) => { |
400 | let _callee_ty = if let Some(e) = e.expr() { | ||
401 | self.infer_expr(e)? | ||
402 | } else { | ||
403 | Ty::Unknown | ||
404 | }; | ||
356 | if let Some(arg_list) = e.arg_list() { | 405 | if let Some(arg_list) = e.arg_list() { |
357 | for arg in arg_list.args() { | 406 | for arg in arg_list.args() { |
358 | // TODO unify / expect argument type | 407 | // TODO unify / expect argument type |
359 | self.infer_expr(arg); | 408 | self.infer_expr(arg)?; |
360 | } | 409 | } |
361 | } | 410 | } |
362 | Ty::Unknown | 411 | Ty::Unknown |
363 | } | 412 | } |
364 | ast::Expr::MethodCallExpr(e) => { | 413 | ast::Expr::MethodCallExpr(e) => { |
414 | let _receiver_ty = if let Some(e) = e.expr() { | ||
415 | self.infer_expr(e)? | ||
416 | } else { | ||
417 | Ty::Unknown | ||
418 | }; | ||
365 | if let Some(arg_list) = e.arg_list() { | 419 | if let Some(arg_list) = e.arg_list() { |
366 | for arg in arg_list.args() { | 420 | for arg in arg_list.args() { |
367 | // TODO unify / expect argument type | 421 | // TODO unify / expect argument type |
368 | self.infer_expr(arg); | 422 | self.infer_expr(arg)?; |
369 | } | 423 | } |
370 | } | 424 | } |
371 | Ty::Unknown | 425 | Ty::Unknown |
372 | } | 426 | } |
373 | ast::Expr::MatchExpr(e) => { | 427 | ast::Expr::MatchExpr(e) => { |
374 | let _ty = if let Some(match_expr) = e.expr() { | 428 | let _ty = if let Some(match_expr) = e.expr() { |
375 | self.infer_expr(match_expr) | 429 | self.infer_expr(match_expr)? |
376 | } else { | 430 | } else { |
377 | Ty::Unknown | 431 | Ty::Unknown |
378 | }; | 432 | }; |
@@ -381,7 +435,7 @@ impl InferenceContext { | |||
381 | // TODO type the bindings in pat | 435 | // TODO type the bindings in pat |
382 | // TODO type the guard | 436 | // TODO type the guard |
383 | let _ty = if let Some(e) = arm.expr() { | 437 | let _ty = if let Some(e) = arm.expr() { |
384 | self.infer_expr(e) | 438 | self.infer_expr(e)? |
385 | } else { | 439 | } else { |
386 | Ty::Unknown | 440 | Ty::Unknown |
387 | }; | 441 | }; |
@@ -394,12 +448,12 @@ impl InferenceContext { | |||
394 | } | 448 | } |
395 | ast::Expr::TupleExpr(_e) => Ty::Unknown, | 449 | ast::Expr::TupleExpr(_e) => Ty::Unknown, |
396 | ast::Expr::ArrayExpr(_e) => Ty::Unknown, | 450 | ast::Expr::ArrayExpr(_e) => Ty::Unknown, |
397 | ast::Expr::PathExpr(e) => self.infer_path_expr(e).unwrap_or(Ty::Unknown), | 451 | ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), |
398 | ast::Expr::ContinueExpr(_e) => Ty::Never, | 452 | ast::Expr::ContinueExpr(_e) => Ty::Never, |
399 | ast::Expr::BreakExpr(_e) => Ty::Never, | 453 | ast::Expr::BreakExpr(_e) => Ty::Never, |
400 | ast::Expr::ParenExpr(e) => { | 454 | ast::Expr::ParenExpr(e) => { |
401 | if let Some(e) = e.expr() { | 455 | if let Some(e) = e.expr() { |
402 | self.infer_expr(e) | 456 | self.infer_expr(e)? |
403 | } else { | 457 | } else { |
404 | Ty::Unknown | 458 | Ty::Unknown |
405 | } | 459 | } |
@@ -408,7 +462,7 @@ impl InferenceContext { | |||
408 | ast::Expr::ReturnExpr(e) => { | 462 | ast::Expr::ReturnExpr(e) => { |
409 | if let Some(e) = e.expr() { | 463 | if let Some(e) = e.expr() { |
410 | // TODO unify with return type | 464 | // TODO unify with return type |
411 | self.infer_expr(e); | 465 | self.infer_expr(e)?; |
412 | }; | 466 | }; |
413 | Ty::Never | 467 | Ty::Never |
414 | } | 468 | } |
@@ -425,7 +479,7 @@ impl InferenceContext { | |||
425 | ast::Expr::FieldExpr(_e) => Ty::Unknown, | 479 | ast::Expr::FieldExpr(_e) => Ty::Unknown, |
426 | ast::Expr::TryExpr(e) => { | 480 | ast::Expr::TryExpr(e) => { |
427 | let _inner_ty = if let Some(e) = e.expr() { | 481 | let _inner_ty = if let Some(e) = e.expr() { |
428 | self.infer_expr(e) | 482 | self.infer_expr(e)? |
429 | } else { | 483 | } else { |
430 | Ty::Unknown | 484 | Ty::Unknown |
431 | }; | 485 | }; |
@@ -433,7 +487,7 @@ impl InferenceContext { | |||
433 | } | 487 | } |
434 | ast::Expr::CastExpr(e) => { | 488 | ast::Expr::CastExpr(e) => { |
435 | let _inner_ty = if let Some(e) = e.expr() { | 489 | let _inner_ty = if let Some(e) = e.expr() { |
436 | self.infer_expr(e) | 490 | self.infer_expr(e)? |
437 | } else { | 491 | } else { |
438 | Ty::Unknown | 492 | Ty::Unknown |
439 | }; | 493 | }; |
@@ -443,7 +497,7 @@ impl InferenceContext { | |||
443 | } | 497 | } |
444 | ast::Expr::RefExpr(e) => { | 498 | ast::Expr::RefExpr(e) => { |
445 | let _inner_ty = if let Some(e) = e.expr() { | 499 | let _inner_ty = if let Some(e) = e.expr() { |
446 | self.infer_expr(e) | 500 | self.infer_expr(e)? |
447 | } else { | 501 | } else { |
448 | Ty::Unknown | 502 | Ty::Unknown |
449 | }; | 503 | }; |
@@ -451,7 +505,7 @@ impl InferenceContext { | |||
451 | } | 505 | } |
452 | ast::Expr::PrefixExpr(e) => { | 506 | ast::Expr::PrefixExpr(e) => { |
453 | let _inner_ty = if let Some(e) = e.expr() { | 507 | let _inner_ty = if let Some(e) = e.expr() { |
454 | self.infer_expr(e) | 508 | self.infer_expr(e)? |
455 | } else { | 509 | } else { |
456 | Ty::Unknown | 510 | Ty::Unknown |
457 | }; | 511 | }; |
@@ -462,10 +516,10 @@ impl InferenceContext { | |||
462 | ast::Expr::Literal(_e) => Ty::Unknown, | 516 | ast::Expr::Literal(_e) => Ty::Unknown, |
463 | }; | 517 | }; |
464 | self.write_ty(expr.syntax(), ty.clone()); | 518 | self.write_ty(expr.syntax(), ty.clone()); |
465 | ty | 519 | Ok(ty) |
466 | } | 520 | } |
467 | 521 | ||
468 | fn infer_block(&mut self, node: ast::Block) -> Ty { | 522 | fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { |
469 | for stmt in node.statements() { | 523 | for stmt in node.statements() { |
470 | match stmt { | 524 | match stmt { |
471 | ast::Stmt::LetStmt(stmt) => { | 525 | ast::Stmt::LetStmt(stmt) => { |
@@ -476,7 +530,7 @@ impl InferenceContext { | |||
476 | }; | 530 | }; |
477 | let ty = if let Some(expr) = stmt.initializer() { | 531 | let ty = if let Some(expr) = stmt.initializer() { |
478 | // TODO pass expectation | 532 | // TODO pass expectation |
479 | let expr_ty = self.infer_expr(expr); | 533 | let expr_ty = self.infer_expr(expr)?; |
480 | self.unify_with_coercion(&expr_ty, &decl_ty) | 534 | self.unify_with_coercion(&expr_ty, &decl_ty) |
481 | .unwrap_or(decl_ty) | 535 | .unwrap_or(decl_ty) |
482 | } else { | 536 | } else { |
@@ -489,23 +543,28 @@ impl InferenceContext { | |||
489 | } | 543 | } |
490 | ast::Stmt::ExprStmt(expr_stmt) => { | 544 | ast::Stmt::ExprStmt(expr_stmt) => { |
491 | if let Some(expr) = expr_stmt.expr() { | 545 | if let Some(expr) = expr_stmt.expr() { |
492 | self.infer_expr(expr); | 546 | self.infer_expr(expr)?; |
493 | } | 547 | } |
494 | } | 548 | } |
495 | } | 549 | } |
496 | } | 550 | } |
497 | let ty = if let Some(expr) = node.expr() { | 551 | let ty = if let Some(expr) = node.expr() { |
498 | self.infer_expr(expr) | 552 | self.infer_expr(expr)? |
499 | } else { | 553 | } else { |
500 | Ty::unit() | 554 | Ty::unit() |
501 | }; | 555 | }; |
502 | self.write_ty(node.syntax(), ty.clone()); | 556 | self.write_ty(node.syntax(), ty.clone()); |
503 | ty | 557 | Ok(ty) |
504 | } | 558 | } |
505 | } | 559 | } |
506 | 560 | ||
507 | pub fn infer(_db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> InferenceResult { | 561 | pub fn infer(db: &impl HirDatabase, function: Function) -> Cancelable<InferenceResult> { |
508 | let mut ctx = InferenceContext::new(scopes); | 562 | let scopes = function.scopes(db); |
563 | let module = function.module(db)?; | ||
564 | let mut ctx = InferenceContext::new(db, scopes, module); | ||
565 | |||
566 | let syntax = function.syntax(db); | ||
567 | let node = syntax.borrowed(); | ||
509 | 568 | ||
510 | if let Some(param_list) = node.param_list() { | 569 | if let Some(param_list) = node.param_list() { |
511 | for param in param_list.params() { | 570 | for param in param_list.params() { |
@@ -529,12 +588,12 @@ pub fn infer(_db: &impl HirDatabase, node: ast::FnDef, scopes: Arc<FnScopes>) -> | |||
529 | // (see Expectation in rustc_typeck) | 588 | // (see Expectation in rustc_typeck) |
530 | 589 | ||
531 | if let Some(block) = node.body() { | 590 | if let Some(block) = node.body() { |
532 | ctx.infer_block(block); | 591 | ctx.infer_block(block)?; |
533 | } | 592 | } |
534 | 593 | ||
535 | // TODO 'resolve' the types: replace inference variables by their inferred results | 594 | // TODO 'resolve' the types: replace inference variables by their inferred results |
536 | 595 | ||
537 | InferenceResult { | 596 | Ok(InferenceResult { |
538 | type_for: ctx.type_for, | 597 | type_for: ctx.type_for, |
539 | } | 598 | }) |
540 | } | 599 | } |