aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/infer.rs')
-rw-r--r--crates/ra_hir_ty/src/infer.rs60
1 files changed, 59 insertions, 1 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index bd4ef69a0..a21ad8d86 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -210,6 +210,13 @@ 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,
214 breakables: Vec<BreakableContext>,
215}
216
217#[derive(Clone, Debug)]
218struct BreakableContext {
219 pub may_break: bool,
213} 220}
214 221
215impl<'a> InferenceContext<'a> { 222impl<'a> InferenceContext<'a> {
@@ -224,6 +231,8 @@ impl<'a> InferenceContext<'a> {
224 owner, 231 owner,
225 body: db.body(owner), 232 body: db.body(owner),
226 resolver, 233 resolver,
234 diverges: Diverges::Maybe,
235 breakables: Vec::new(),
227 } 236 }
228 } 237 }
229 238
@@ -666,15 +675,57 @@ impl Expectation {
666 } 675 }
667} 676}
668 677
678#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
679enum Diverges {
680 Maybe,
681 Always,
682}
683
684impl Diverges {
685 fn is_always(self) -> bool {
686 self == Diverges::Always
687 }
688}
689
690impl std::ops::BitAnd for Diverges {
691 type Output = Self;
692 fn bitand(self, other: Self) -> Self {
693 std::cmp::min(self, other)
694 }
695}
696
697impl std::ops::BitOr for Diverges {
698 type Output = Self;
699 fn bitor(self, other: Self) -> Self {
700 std::cmp::max(self, other)
701 }
702}
703
704impl std::ops::BitAndAssign for Diverges {
705 fn bitand_assign(&mut self, other: Self) {
706 *self = *self & other;
707 }
708}
709
710impl std::ops::BitOrAssign for Diverges {
711 fn bitor_assign(&mut self, other: Self) {
712 *self = *self | other;
713 }
714}
715
669mod diagnostics { 716mod diagnostics {
670 use hir_def::{expr::ExprId, FunctionId}; 717 use hir_def::{expr::ExprId, FunctionId};
671 use hir_expand::diagnostics::DiagnosticSink; 718 use hir_expand::diagnostics::DiagnosticSink;
672 719
673 use crate::{db::HirDatabase, diagnostics::NoSuchField}; 720 use crate::{
721 db::HirDatabase,
722 diagnostics::{BreakOutsideOfLoop, NoSuchField},
723 };
674 724
675 #[derive(Debug, PartialEq, Eq, Clone)] 725 #[derive(Debug, PartialEq, Eq, Clone)]
676 pub(super) enum InferenceDiagnostic { 726 pub(super) enum InferenceDiagnostic {
677 NoSuchField { expr: ExprId, field: usize }, 727 NoSuchField { expr: ExprId, field: usize },
728 BreakOutsideOfLoop { expr: ExprId },
678 } 729 }
679 730
680 impl InferenceDiagnostic { 731 impl InferenceDiagnostic {
@@ -690,6 +741,13 @@ mod diagnostics {
690 let field = source_map.field_syntax(*expr, *field); 741 let field = source_map.field_syntax(*expr, *field);
691 sink.push(NoSuchField { file: field.file_id, field: field.value }) 742 sink.push(NoSuchField { file: field.file_id, field: field.value })
692 } 743 }
744 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
745 let (_, source_map) = db.body_with_source_map(owner.into());
746 let ptr = source_map
747 .expr_syntax(*expr)
748 .expect("break outside of loop in synthetic syntax");
749 sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
750 }
693 } 751 }
694 } 752 }
695 } 753 }