aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-02-29 14:31:07 +0000
committerFlorian Diebold <[email protected]>2020-02-29 14:31:07 +0000
commit5fe220b9873d587188adae63fa205481a9aae9ce (patch)
tree51599b3664e16cd5f0ef288dac924330c5cd0af0 /crates/ra_hir_ty/src/infer.rs
parent0ec7f760fcd8bb9c2273e004468faa2a8cbeb29d (diff)
Fix a common false-positive type mismatch
E.g. for `&{ some_string() }` in a context where a `&str` is expected, we reported a mismatch inside the block. The problem is that we're passing an expectation of `str` down, but the expectation is more of a hint in this case. There's a long comment in rustc about this, which I just copied. Also, fix reported location for type mismatches in macros.
Diffstat (limited to 'crates/ra_hir_ty/src/infer.rs')
-rw-r--r--crates/ra_hir_ty/src/infer.rs41
1 files changed, 36 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 6e1d268de..569d46cc3 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -583,21 +583,52 @@ impl InferTy {
583#[derive(Clone, PartialEq, Eq, Debug)] 583#[derive(Clone, PartialEq, Eq, Debug)]
584struct Expectation { 584struct Expectation {
585 ty: Ty, 585 ty: Ty,
586 // FIXME: In some cases, we need to be aware whether the expectation is that 586 /// See the `rvalue_hint` method.
587 // the type match exactly what we passed, or whether it just needs to be 587 rvalue_hint: bool,
588 // coercible to the expected type. See Expectation::rvalue_hint in rustc.
589} 588}
590 589
591impl Expectation { 590impl Expectation {
592 /// The expectation that the type of the expression needs to equal the given 591 /// The expectation that the type of the expression needs to equal the given
593 /// type. 592 /// type.
594 fn has_type(ty: Ty) -> Self { 593 fn has_type(ty: Ty) -> Self {
595 Expectation { ty } 594 Expectation { ty, rvalue_hint: false }
595 }
596
597 /// The following explanation is copied straight from rustc:
598 /// Provides an expectation for an rvalue expression given an *optional*
599 /// hint, which is not required for type safety (the resulting type might
600 /// be checked higher up, as is the case with `&expr` and `box expr`), but
601 /// is useful in determining the concrete type.
602 ///
603 /// The primary use case is where the expected type is a fat pointer,
604 /// like `&[isize]`. For example, consider the following statement:
605 ///
606 /// let x: &[isize] = &[1, 2, 3];
607 ///
608 /// In this case, the expected type for the `&[1, 2, 3]` expression is
609 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
610 /// expectation `ExpectHasType([isize])`, that would be too strong --
611 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
612 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
613 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
614 /// which still is useful, because it informs integer literals and the like.
615 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
616 /// for examples of where this comes up,.
617 fn rvalue_hint(ty: Ty) -> Self {
618 Expectation { ty, rvalue_hint: true }
596 } 619 }
597 620
598 /// This expresses no expectation on the type. 621 /// This expresses no expectation on the type.
599 fn none() -> Self { 622 fn none() -> Self {
600 Expectation { ty: Ty::Unknown } 623 Expectation { ty: Ty::Unknown, rvalue_hint: false }
624 }
625
626 fn coercion_target(&self) -> &Ty {
627 if self.rvalue_hint {
628 &Ty::Unknown
629 } else {
630 &self.ty
631 }
601 } 632 }
602} 633}
603 634