aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-05-21 16:41:20 +0100
committerFlorian Diebold <[email protected]>2021-05-21 17:23:03 +0100
commit556c9cebdb91278702263df4ac8c99ec24ab331a (patch)
treed1895aa19a6ec1b7532871e171f1c37870298f58 /crates/hir_ty/src
parent99c73537faba59c881805573442562418e0b650a (diff)
Refactor expectation handling
So as to not use `TyKind::Error` as "no expectation".
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/infer.rs59
-rw-r--r--crates/hir_ty/src/infer/coerce.rs4
-rw-r--r--crates/hir_ty/src/infer/expr.rs79
3 files changed, 88 insertions, 54 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index db2234018..a137c0f92 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -370,10 +370,6 @@ impl<'a> InferenceContext<'a> {
370 } 370 }
371 371
372 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 372 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
373 // TODO handle expectations properly
374 if ty2.is_unknown() {
375 return true;
376 }
377 self.table.unify(ty1, ty2) 373 self.table.unify(ty1, ty2)
378 } 374 }
379 375
@@ -679,17 +675,23 @@ impl<'a> InferenceContext<'a> {
679/// When inferring an expression, we propagate downward whatever type hint we 675/// When inferring an expression, we propagate downward whatever type hint we
680/// are able in the form of an `Expectation`. 676/// are able in the form of an `Expectation`.
681#[derive(Clone, PartialEq, Eq, Debug)] 677#[derive(Clone, PartialEq, Eq, Debug)]
682struct Expectation { 678enum Expectation {
683 ty: Ty, 679 None,
684 /// See the `rvalue_hint` method. 680 HasType(Ty),
685 rvalue_hint: bool, 681 // Castable(Ty), // rustc has this, we currently just don't propagate an expectation for casts
682 RValueLikeUnsized(Ty),
686} 683}
687 684
688impl Expectation { 685impl Expectation {
689 /// The expectation that the type of the expression needs to equal the given 686 /// The expectation that the type of the expression needs to equal the given
690 /// type. 687 /// type.
691 fn has_type(ty: Ty) -> Self { 688 fn has_type(ty: Ty) -> Self {
692 Expectation { ty, rvalue_hint: false } 689 if ty.is_unknown() {
690 // FIXME: get rid of this?
691 Expectation::None
692 } else {
693 Expectation::HasType(ty)
694 }
693 } 695 }
694 696
695 /// The following explanation is copied straight from rustc: 697 /// The following explanation is copied straight from rustc:
@@ -713,24 +715,41 @@ impl Expectation {
713 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 715 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
714 /// for examples of where this comes up,. 716 /// for examples of where this comes up,.
715 fn rvalue_hint(ty: Ty) -> Self { 717 fn rvalue_hint(ty: Ty) -> Self {
716 Expectation { ty, rvalue_hint: true } 718 match ty.strip_references().kind(&Interner) {
719 TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty),
720 _ => Expectation::has_type(ty),
721 }
717 } 722 }
718 723
719 /// This expresses no expectation on the type. 724 /// This expresses no expectation on the type.
720 fn none() -> Self { 725 fn none() -> Self {
721 Expectation { 726 Expectation::None
722 // FIXME 727 }
723 ty: TyKind::Error.intern(&Interner), 728
724 rvalue_hint: false, 729 fn resolve(&self, table: &mut unify::InferenceTable) -> Expectation {
730 match self {
731 Expectation::None => Expectation::None,
732 Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
733 Expectation::RValueLikeUnsized(t) => {
734 Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
735 }
725 } 736 }
726 } 737 }
727 738
728 fn coercion_target(&self) -> Ty { 739 fn to_option(&self, table: &mut unify::InferenceTable) -> Option<Ty> {
729 if self.rvalue_hint { 740 match self.resolve(table) {
730 // FIXME 741 Expectation::None => None,
731 TyKind::Error.intern(&Interner) 742 Expectation::HasType(t) |
732 } else { 743 // Expectation::Castable(t) |
733 self.ty.clone() 744 Expectation::RValueLikeUnsized(t) => Some(t),
745 }
746 }
747
748 fn only_has_type(&self, table: &mut unify::InferenceTable) -> Option<Ty> {
749 match self {
750 Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
751 // Expectation::Castable(_) |
752 Expectation::RValueLikeUnsized(_) | Expectation::None => None,
734 } 753 }
735 } 754 }
736} 755}
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 20c512517..03dd6ae76 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -21,10 +21,6 @@ impl<'a> InferenceContext<'a> {
21 pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { 21 pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
22 let from_ty = self.resolve_ty_shallow(from_ty); 22 let from_ty = self.resolve_ty_shallow(from_ty);
23 let to_ty = self.resolve_ty_shallow(to_ty); 23 let to_ty = self.resolve_ty_shallow(to_ty);
24 // TODO handle expectations properly
25 if to_ty.is_unknown() {
26 return true;
27 }
28 match self.coerce_inner(from_ty, &to_ty) { 24 match self.coerce_inner(from_ty, &to_ty) {
29 Ok(result) => { 25 Ok(result) => {
30 self.table.register_infer_ok(result); 26 self.table.register_infer_ok(result);
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index f5782ab24..4ef847d3a 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -39,12 +39,14 @@ impl<'a> InferenceContext<'a> {
39 // Any expression that produces a value of type `!` must have diverged 39 // Any expression that produces a value of type `!` must have diverged
40 self.diverges = Diverges::Always; 40 self.diverges = Diverges::Always;
41 } 41 }
42 let could_unify = self.unify(&ty, &expected.ty); 42 if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
43 if !could_unify { 43 let could_unify = self.unify(&ty, &expected_ty);
44 self.result.type_mismatches.insert( 44 if !could_unify {
45 tgt_expr.into(), 45 self.result.type_mismatches.insert(
46 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 46 tgt_expr.into(),
47 ); 47 TypeMismatch { expected: expected_ty.clone(), actual: ty.clone() },
48 );
49 }
48 } 50 }
49 ty 51 ty
50 } 52 }
@@ -53,18 +55,20 @@ impl<'a> InferenceContext<'a> {
53 /// Return the type after possible coercion. 55 /// Return the type after possible coercion.
54 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 56 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
55 let ty = self.infer_expr_inner(expr, &expected); 57 let ty = self.infer_expr_inner(expr, &expected);
56 let ty = if !self.coerce(&ty, &expected.coercion_target()) { 58 let ty = if let Some(target) = expected.only_has_type(&mut self.table) {
57 self.result.type_mismatches.insert( 59 if !self.coerce(&ty, &target) {
58 expr.into(), 60 self.result.type_mismatches.insert(
59 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 61 expr.into(),
60 ); 62 TypeMismatch { expected: target.clone(), actual: ty.clone() },
61 // Return actual type when type mismatch. 63 );
62 // This is needed for diagnostic when return type mismatch. 64 // Return actual type when type mismatch.
63 ty 65 // This is needed for diagnostic when return type mismatch.
64 } else if expected.coercion_target().is_unknown() { 66 ty
65 ty 67 } else {
68 target.clone()
69 }
66 } else { 70 } else {
67 expected.ty.clone() 71 ty
68 }; 72 };
69 73
70 ty 74 ty
@@ -280,7 +284,9 @@ impl<'a> InferenceContext<'a> {
280 // Eagerly try to relate the closure type with the expected 284 // Eagerly try to relate the closure type with the expected
281 // type, otherwise we often won't have enough information to 285 // type, otherwise we often won't have enough information to
282 // infer the body. 286 // infer the body.
283 self.coerce(&closure_ty, &expected.ty); 287 if let Some(t) = expected.only_has_type(&mut self.table) {
288 self.coerce(&closure_ty, &t);
289 }
284 290
285 // Now go through the argument patterns 291 // Now go through the argument patterns
286 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { 292 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
@@ -413,7 +419,9 @@ impl<'a> InferenceContext<'a> {
413 self.write_variant_resolution(tgt_expr.into(), variant); 419 self.write_variant_resolution(tgt_expr.into(), variant);
414 } 420 }
415 421
416 self.unify(&ty, &expected.ty); 422 if let Some(t) = expected.only_has_type(&mut self.table) {
423 self.unify(&ty, &t);
424 }
417 425
418 let substs = ty 426 let substs = ty
419 .as_adt() 427 .as_adt()
@@ -516,6 +524,7 @@ impl<'a> InferenceContext<'a> {
516 self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok()) 524 self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
517 } 525 }
518 Expr::Cast { expr, type_ref } => { 526 Expr::Cast { expr, type_ref } => {
527 // FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary)
519 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 528 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
520 let cast_ty = self.make_ty(type_ref); 529 let cast_ty = self.make_ty(type_ref);
521 // FIXME check the cast... 530 // FIXME check the cast...
@@ -523,14 +532,16 @@ impl<'a> InferenceContext<'a> {
523 } 532 }
524 Expr::Ref { expr, rawness, mutability } => { 533 Expr::Ref { expr, rawness, mutability } => {
525 let mutability = lower_to_chalk_mutability(*mutability); 534 let mutability = lower_to_chalk_mutability(*mutability);
526 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = 535 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = expected
527 &self.resolve_ty_shallow(&expected.ty).as_reference_or_ptr() 536 .only_has_type(&mut self.table)
537 .as_ref()
538 .and_then(|t| t.as_reference_or_ptr())
528 { 539 {
529 if *exp_mutability == Mutability::Mut && mutability == Mutability::Not { 540 if exp_mutability == Mutability::Mut && mutability == Mutability::Not {
530 // FIXME: record type error - expected mut reference but found shared ref, 541 // FIXME: record type error - expected mut reference but found shared ref,
531 // which cannot be coerced 542 // which cannot be coerced
532 } 543 }
533 if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr { 544 if exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
534 // FIXME: record type error - expected reference but found ptr, 545 // FIXME: record type error - expected reference but found ptr,
535 // which cannot be coerced 546 // which cannot be coerced
536 } 547 }
@@ -701,8 +712,12 @@ impl<'a> InferenceContext<'a> {
701 } 712 }
702 } 713 }
703 Expr::Tuple { exprs } => { 714 Expr::Tuple { exprs } => {
704 let mut tys = match self.resolve_ty_shallow(&expected.ty).kind(&Interner) { 715 let mut tys = match expected
705 TyKind::Tuple(_, substs) => substs 716 .only_has_type(&mut self.table)
717 .as_ref()
718 .map(|t| t.kind(&Interner))
719 {
720 Some(TyKind::Tuple(_, substs)) => substs
706 .iter(&Interner) 721 .iter(&Interner)
707 .map(|a| a.assert_ty_ref(&Interner).clone()) 722 .map(|a| a.assert_ty_ref(&Interner).clone())
708 .chain(repeat_with(|| self.table.new_type_var())) 723 .chain(repeat_with(|| self.table.new_type_var()))
@@ -718,14 +733,16 @@ impl<'a> InferenceContext<'a> {
718 TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner) 733 TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner)
719 } 734 }
720 Expr::Array(array) => { 735 Expr::Array(array) => {
721 let elem_ty = match self.resolve_ty_shallow(&expected.ty).kind(&Interner) { 736 let elem_ty =
722 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), 737 match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) {
723 _ => self.table.new_type_var(), 738 Some(TyKind::Array(st, _)) | Some(TyKind::Slice(st)) => st.clone(),
724 }; 739 _ => self.table.new_type_var(),
740 };
725 741
726 let len = match array { 742 let len = match array {
727 Array::ElementList(items) => { 743 Array::ElementList(items) => {
728 for expr in items.iter() { 744 for expr in items.iter() {
745 // FIXME: use CoerceMany (coerce_merge_branch)
729 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); 746 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
730 } 747 }
731 Some(items.len() as u64) 748 Some(items.len() as u64)
@@ -839,7 +856,9 @@ impl<'a> InferenceContext<'a> {
839 // we don't even make an attempt at coercion 856 // we don't even make an attempt at coercion
840 self.table.new_maybe_never_var() 857 self.table.new_maybe_never_var()
841 } else { 858 } else {
842 self.coerce(&TyBuilder::unit(), &expected.coercion_target()); 859 if let Some(t) = expected.only_has_type(&mut self.table) {
860 self.coerce(&TyBuilder::unit(), &t);
861 }
843 TyBuilder::unit() 862 TyBuilder::unit()
844 } 863 }
845 }; 864 };