diff options
-rw-r--r-- | crates/ra_hir/src/ty.rs | 162 |
1 files changed, 37 insertions, 125 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 83da13f1a..7b8dbe6b7 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -239,19 +239,11 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | |||
239 | .param_list() | 239 | .param_list() |
240 | .map(|pl| { | 240 | .map(|pl| { |
241 | pl.params() | 241 | pl.params() |
242 | .map(|p| { | 242 | .map(|p| Ty::new_opt(db, &module, p.type_ref())) |
243 | p.type_ref() | ||
244 | .map(|t| Ty::new(db, &module, t)) | ||
245 | .unwrap_or(Ok(Ty::Unknown)) | ||
246 | }) | ||
247 | .collect() | 243 | .collect() |
248 | }) | 244 | }) |
249 | .unwrap_or_else(|| Ok(Vec::new()))?; | 245 | .unwrap_or_else(|| Ok(Vec::new()))?; |
250 | let output = node | 246 | let output = Ty::new_opt(db, &module, node.ret_type().and_then(|rt| rt.type_ref()))?; |
251 | .ret_type() | ||
252 | .and_then(|rt| rt.type_ref()) | ||
253 | .map(|t| Ty::new(db, &module, t)) | ||
254 | .unwrap_or(Ok(Ty::Unknown))?; | ||
255 | let sig = FnSig { input, output }; | 247 | let sig = FnSig { input, output }; |
256 | Ok(Ty::FnPtr(Arc::new(sig))) | 248 | Ok(Ty::FnPtr(Arc::new(sig))) |
257 | } | 249 | } |
@@ -263,11 +255,6 @@ pub fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> { | |||
263 | }) | 255 | }) |
264 | } | 256 | } |
265 | 257 | ||
266 | // TODO this should probably be per namespace (i.e. types vs. values), since for | ||
267 | // a tuple struct `struct Foo(Bar)`, Foo has function type as a value, but | ||
268 | // defines the struct type Foo when used in the type namespace. rustc has a | ||
269 | // separate DefId for the constructor, but with the current DefId approach, that | ||
270 | // seems complicated. | ||
271 | pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | 258 | pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { |
272 | let def = def_id.resolve(db)?; | 259 | let def = def_id.resolve(db)?; |
273 | match def { | 260 | match def { |
@@ -396,22 +383,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
396 | let ty = match expr { | 383 | let ty = match expr { |
397 | ast::Expr::IfExpr(e) => { | 384 | ast::Expr::IfExpr(e) => { |
398 | if let Some(condition) = e.condition() { | 385 | if let Some(condition) = e.condition() { |
399 | if let Some(e) = condition.expr() { | 386 | // TODO if no pat, this should be bool |
400 | // TODO if no pat, this should be bool | 387 | self.infer_expr_opt(condition.expr())?; |
401 | self.infer_expr(e)?; | ||
402 | } | ||
403 | // TODO write type for pat | 388 | // TODO write type for pat |
404 | }; | 389 | }; |
405 | let if_ty = if let Some(block) = e.then_branch() { | 390 | let if_ty = self.infer_block_opt(e.then_branch())?; |
406 | self.infer_block(block)? | 391 | let else_ty = self.infer_block_opt(e.else_branch())?; |
407 | } else { | ||
408 | Ty::Unknown | ||
409 | }; | ||
410 | let else_ty = if let Some(block) = e.else_branch() { | ||
411 | self.infer_block(block)? | ||
412 | } else { | ||
413 | Ty::Unknown | ||
414 | }; | ||
415 | if let Some(ty) = self.unify(&if_ty, &else_ty) { | 392 | if let Some(ty) = self.unify(&if_ty, &else_ty) { |
416 | ty | 393 | ty |
417 | } else { | 394 | } else { |
@@ -419,62 +396,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
419 | Ty::Unknown | 396 | Ty::Unknown |
420 | } | 397 | } |
421 | } | 398 | } |
422 | ast::Expr::BlockExpr(e) => { | 399 | ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block())?, |
423 | if let Some(block) = e.block() { | ||
424 | self.infer_block(block)? | ||
425 | } else { | ||
426 | Ty::Unknown | ||
427 | } | ||
428 | } | ||
429 | ast::Expr::LoopExpr(e) => { | 400 | ast::Expr::LoopExpr(e) => { |
430 | if let Some(block) = e.loop_body() { | 401 | self.infer_block_opt(e.loop_body())?; |
431 | self.infer_block(block)?; | ||
432 | }; | ||
433 | // TODO never, or the type of the break param | 402 | // TODO never, or the type of the break param |
434 | Ty::Unknown | 403 | Ty::Unknown |
435 | } | 404 | } |
436 | ast::Expr::WhileExpr(e) => { | 405 | ast::Expr::WhileExpr(e) => { |
437 | if let Some(condition) = e.condition() { | 406 | if let Some(condition) = e.condition() { |
438 | if let Some(e) = condition.expr() { | 407 | // TODO if no pat, this should be bool |
439 | // TODO if no pat, this should be bool | 408 | self.infer_expr_opt(condition.expr())?; |
440 | self.infer_expr(e)?; | ||
441 | } | ||
442 | // TODO write type for pat | 409 | // TODO write type for pat |
443 | }; | 410 | }; |
444 | if let Some(block) = e.loop_body() { | 411 | self.infer_block_opt(e.loop_body())?; |
445 | // TODO | ||
446 | self.infer_block(block)?; | ||
447 | }; | ||
448 | // TODO always unit? | 412 | // TODO always unit? |
449 | Ty::Unknown | 413 | Ty::Unknown |
450 | } | 414 | } |
451 | ast::Expr::ForExpr(e) => { | 415 | ast::Expr::ForExpr(e) => { |
452 | if let Some(expr) = e.iterable() { | 416 | let _iterable_ty = self.infer_expr_opt(e.iterable()); |
453 | self.infer_expr(expr)?; | ||
454 | } | ||
455 | if let Some(_pat) = e.pat() { | 417 | if let Some(_pat) = e.pat() { |
456 | // TODO write type for pat | 418 | // TODO write type for pat |
457 | } | 419 | } |
458 | if let Some(block) = e.loop_body() { | 420 | self.infer_block_opt(e.loop_body())?; |
459 | self.infer_block(block)?; | ||
460 | } | ||
461 | // TODO always unit? | 421 | // TODO always unit? |
462 | Ty::Unknown | 422 | Ty::Unknown |
463 | } | 423 | } |
464 | ast::Expr::LambdaExpr(e) => { | 424 | ast::Expr::LambdaExpr(e) => { |
465 | let _body_ty = if let Some(body) = e.body() { | 425 | let _body_ty = self.infer_expr_opt(e.body())?; |
466 | self.infer_expr(body)? | ||
467 | } else { | ||
468 | Ty::Unknown | ||
469 | }; | ||
470 | Ty::Unknown | 426 | Ty::Unknown |
471 | } | 427 | } |
472 | ast::Expr::CallExpr(e) => { | 428 | ast::Expr::CallExpr(e) => { |
473 | let callee_ty = if let Some(e) = e.expr() { | 429 | let callee_ty = self.infer_expr_opt(e.expr())?; |
474 | self.infer_expr(e)? | ||
475 | } else { | ||
476 | Ty::Unknown | ||
477 | }; | ||
478 | if let Some(arg_list) = e.arg_list() { | 430 | if let Some(arg_list) = e.arg_list() { |
479 | for arg in arg_list.args() { | 431 | for arg in arg_list.args() { |
480 | // TODO unify / expect argument type | 432 | // TODO unify / expect argument type |
@@ -491,11 +443,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
491 | } | 443 | } |
492 | } | 444 | } |
493 | ast::Expr::MethodCallExpr(e) => { | 445 | ast::Expr::MethodCallExpr(e) => { |
494 | let _receiver_ty = if let Some(e) = e.expr() { | 446 | let _receiver_ty = self.infer_expr_opt(e.expr())?; |
495 | self.infer_expr(e)? | ||
496 | } else { | ||
497 | Ty::Unknown | ||
498 | }; | ||
499 | if let Some(arg_list) = e.arg_list() { | 447 | if let Some(arg_list) = e.arg_list() { |
500 | for arg in arg_list.args() { | 448 | for arg in arg_list.args() { |
501 | // TODO unify / expect argument type | 449 | // TODO unify / expect argument type |
@@ -505,20 +453,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
505 | Ty::Unknown | 453 | Ty::Unknown |
506 | } | 454 | } |
507 | ast::Expr::MatchExpr(e) => { | 455 | ast::Expr::MatchExpr(e) => { |
508 | let _ty = if let Some(match_expr) = e.expr() { | 456 | let _ty = self.infer_expr_opt(e.expr())?; |
509 | self.infer_expr(match_expr)? | ||
510 | } else { | ||
511 | Ty::Unknown | ||
512 | }; | ||
513 | if let Some(match_arm_list) = e.match_arm_list() { | 457 | if let Some(match_arm_list) = e.match_arm_list() { |
514 | for arm in match_arm_list.arms() { | 458 | for arm in match_arm_list.arms() { |
515 | // TODO type the bindings in pat | 459 | // TODO type the bindings in pat |
516 | // TODO type the guard | 460 | // TODO type the guard |
517 | let _ty = if let Some(e) = arm.expr() { | 461 | let _ty = self.infer_expr_opt(arm.expr())?; |
518 | self.infer_expr(e)? | ||
519 | } else { | ||
520 | Ty::Unknown | ||
521 | }; | ||
522 | } | 462 | } |
523 | // TODO unify all the match arm types | 463 | // TODO unify all the match arm types |
524 | Ty::Unknown | 464 | Ty::Unknown |
@@ -531,19 +471,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
531 | ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), | 471 | ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), |
532 | ast::Expr::ContinueExpr(_e) => Ty::Never, | 472 | ast::Expr::ContinueExpr(_e) => Ty::Never, |
533 | ast::Expr::BreakExpr(_e) => Ty::Never, | 473 | ast::Expr::BreakExpr(_e) => Ty::Never, |
534 | ast::Expr::ParenExpr(e) => { | 474 | ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr())?, |
535 | if let Some(e) = e.expr() { | ||
536 | self.infer_expr(e)? | ||
537 | } else { | ||
538 | Ty::Unknown | ||
539 | } | ||
540 | } | ||
541 | ast::Expr::Label(_e) => Ty::Unknown, | 475 | ast::Expr::Label(_e) => Ty::Unknown, |
542 | ast::Expr::ReturnExpr(e) => { | 476 | ast::Expr::ReturnExpr(e) => { |
543 | if let Some(e) = e.expr() { | 477 | self.infer_expr_opt(e.expr())?; |
544 | // TODO unify with / expect return type | ||
545 | self.infer_expr(e)?; | ||
546 | }; | ||
547 | Ty::Never | 478 | Ty::Never |
548 | } | 479 | } |
549 | ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { | 480 | ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { |
@@ -554,10 +485,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
554 | let (ty, _variant_data) = self.resolve_variant(e.path())?; | 485 | let (ty, _variant_data) = self.resolve_variant(e.path())?; |
555 | if let Some(nfl) = e.named_field_list() { | 486 | if let Some(nfl) = e.named_field_list() { |
556 | for field in nfl.fields() { | 487 | for field in nfl.fields() { |
557 | if let Some(e) = field.expr() { | 488 | // TODO unify with / expect field type |
558 | // TODO unify with / expect field type | 489 | self.infer_expr_opt(field.expr())?; |
559 | self.infer_expr(e)?; | ||
560 | } | ||
561 | } | 490 | } |
562 | } | 491 | } |
563 | ty | 492 | ty |
@@ -592,40 +521,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
592 | } | 521 | } |
593 | } | 522 | } |
594 | ast::Expr::TryExpr(e) => { | 523 | ast::Expr::TryExpr(e) => { |
595 | let _inner_ty = if let Some(e) = e.expr() { | 524 | let _inner_ty = self.infer_expr_opt(e.expr())?; |
596 | self.infer_expr(e)? | ||
597 | } else { | ||
598 | Ty::Unknown | ||
599 | }; | ||
600 | Ty::Unknown | 525 | Ty::Unknown |
601 | } | 526 | } |
602 | ast::Expr::CastExpr(e) => { | 527 | ast::Expr::CastExpr(e) => { |
603 | let _inner_ty = if let Some(e) = e.expr() { | 528 | let _inner_ty = self.infer_expr_opt(e.expr())?; |
604 | self.infer_expr(e)? | 529 | let cast_ty = Ty::new_opt(self.db, &self.module, e.type_ref())?; |
605 | } else { | ||
606 | Ty::Unknown | ||
607 | }; | ||
608 | let cast_ty = e | ||
609 | .type_ref() | ||
610 | .map(|t| Ty::new(self.db, &self.module, t)) | ||
611 | .unwrap_or(Ok(Ty::Unknown))?; | ||
612 | // TODO do the coercion... | 530 | // TODO do the coercion... |
613 | cast_ty | 531 | cast_ty |
614 | } | 532 | } |
615 | ast::Expr::RefExpr(e) => { | 533 | ast::Expr::RefExpr(e) => { |
616 | let _inner_ty = if let Some(e) = e.expr() { | 534 | let _inner_ty = self.infer_expr_opt(e.expr())?; |
617 | self.infer_expr(e)? | ||
618 | } else { | ||
619 | Ty::Unknown | ||
620 | }; | ||
621 | Ty::Unknown | 535 | Ty::Unknown |
622 | } | 536 | } |
623 | ast::Expr::PrefixExpr(e) => { | 537 | ast::Expr::PrefixExpr(e) => { |
624 | let _inner_ty = if let Some(e) = e.expr() { | 538 | let _inner_ty = self.infer_expr_opt(e.expr())?; |
625 | self.infer_expr(e)? | ||
626 | } else { | ||
627 | Ty::Unknown | ||
628 | }; | ||
629 | Ty::Unknown | 539 | Ty::Unknown |
630 | } | 540 | } |
631 | ast::Expr::RangeExpr(_e) => Ty::Unknown, | 541 | ast::Expr::RangeExpr(_e) => Ty::Unknown, |
@@ -636,15 +546,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
636 | Ok(ty) | 546 | Ok(ty) |
637 | } | 547 | } |
638 | 548 | ||
549 | fn infer_block_opt(&mut self, node: Option<ast::Block>) -> Cancelable<Ty> { | ||
550 | if let Some(b) = node { | ||
551 | self.infer_block(b) | ||
552 | } else { | ||
553 | Ok(Ty::Unknown) | ||
554 | } | ||
555 | } | ||
556 | |||
639 | fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { | 557 | fn infer_block(&mut self, node: ast::Block) -> Cancelable<Ty> { |
640 | for stmt in node.statements() { | 558 | for stmt in node.statements() { |
641 | match stmt { | 559 | match stmt { |
642 | ast::Stmt::LetStmt(stmt) => { | 560 | ast::Stmt::LetStmt(stmt) => { |
643 | let decl_ty = if let Some(type_ref) = stmt.type_ref() { | 561 | let decl_ty = Ty::new_opt(self.db, &self.module, stmt.type_ref())?; |
644 | Ty::new(self.db, &self.module, type_ref)? | ||
645 | } else { | ||
646 | Ty::Unknown | ||
647 | }; | ||
648 | let ty = if let Some(expr) = stmt.initializer() { | 562 | let ty = if let Some(expr) = stmt.initializer() { |
649 | // TODO pass expectation | 563 | // TODO pass expectation |
650 | let expr_ty = self.infer_expr(expr)?; | 564 | let expr_ty = self.infer_expr(expr)?; |
@@ -659,9 +573,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
659 | }; | 573 | }; |
660 | } | 574 | } |
661 | ast::Stmt::ExprStmt(expr_stmt) => { | 575 | ast::Stmt::ExprStmt(expr_stmt) => { |
662 | if let Some(expr) = expr_stmt.expr() { | 576 | self.infer_expr_opt(expr_stmt.expr())?; |
663 | self.infer_expr(expr)?; | ||
664 | } | ||
665 | } | 577 | } |
666 | } | 578 | } |
667 | } | 579 | } |