aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-05-08 16:36:11 +0100
committerFlorian Diebold <[email protected]>2020-05-08 17:15:24 +0100
commitfe7bf993aa8d64668707e348f2ea69918cfda9a4 (patch)
tree9d3fc4f969dbd06d982dda6dadc6325a668e7eb1 /crates/ra_hir_ty/src/infer.rs
parentd3eb9d8eafbebca7da95fa8a4813b92eb5080500 (diff)
Implement better handling of divergence
Divergence here means that for some reason, the end of a block will not be reached. We tried to model this just using the never type, but that doesn't work fully (e.g. in `let x = { loop {}; "foo" };` x should still have type `&str`); so this introduces a `diverges` flag that the type checker keeps track of, like rustc does.
Diffstat (limited to 'crates/ra_hir_ty/src/infer.rs')
-rw-r--r--crates/ra_hir_ty/src/infer.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index bd4ef69a0..d3a066268 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -210,6 +210,7 @@ struct InferenceContext<'a> {
210 /// closures, but currently this is the only field that will change there, 210 /// closures, but currently this is the only field that will change there,
211 /// so it doesn't make sense. 211 /// so it doesn't make sense.
212 return_ty: Ty, 212 return_ty: Ty,
213 diverges: Diverges,
213} 214}
214 215
215impl<'a> InferenceContext<'a> { 216impl<'a> InferenceContext<'a> {
@@ -224,6 +225,7 @@ impl<'a> InferenceContext<'a> {
224 owner, 225 owner,
225 body: db.body(owner), 226 body: db.body(owner),
226 resolver, 227 resolver,
228 diverges: Diverges::Maybe,
227 } 229 }
228 } 230 }
229 231
@@ -666,6 +668,44 @@ impl Expectation {
666 } 668 }
667} 669}
668 670
671#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
672enum Diverges {
673 Maybe,
674 Always,
675}
676
677impl Diverges {
678 fn is_always(self) -> bool {
679 self == Diverges::Always
680 }
681}
682
683impl std::ops::BitAnd for Diverges {
684 type Output = Self;
685 fn bitand(self, other: Self) -> Self {
686 std::cmp::min(self, other)
687 }
688}
689
690impl std::ops::BitOr for Diverges {
691 type Output = Self;
692 fn bitor(self, other: Self) -> Self {
693 std::cmp::max(self, other)
694 }
695}
696
697impl std::ops::BitAndAssign for Diverges {
698 fn bitand_assign(&mut self, other: Self) {
699 *self = *self & other;
700 }
701}
702
703impl std::ops::BitOrAssign for Diverges {
704 fn bitor_assign(&mut self, other: Self) {
705 *self = *self | other;
706 }
707}
708
669mod diagnostics { 709mod diagnostics {
670 use hir_def::{expr::ExprId, FunctionId}; 710 use hir_def::{expr::ExprId, FunctionId};
671 use hir_expand::diagnostics::DiagnosticSink; 711 use hir_expand::diagnostics::DiagnosticSink;