diff options
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 59 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 79 |
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)] |
682 | struct Expectation { | 678 | enum 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 | ||
688 | impl Expectation { | 685 | impl 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 | }; |