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.rs68
1 files changed, 65 insertions, 3 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index bd4ef69a0..fb7c6cd8c 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -22,7 +22,7 @@ use rustc_hash::FxHashMap;
22 22
23use hir_def::{ 23use hir_def::{
24 body::Body, 24 body::Body,
25 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData, StaticData},
26 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
27 lang_item::LangItemTarget, 27 lang_item::LangItemTarget,
28 path::{path, Path}, 28 path::{path, Path},
@@ -71,7 +71,7 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
71 match def { 71 match def {
72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)), 72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)), 73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)),
74 DefWithBodyId::StaticId(s) => ctx.collect_const(&db.static_data(s)), 74 DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
75 } 75 }
76 76
77 ctx.infer_body(); 77 ctx.infer_body();
@@ -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
@@ -476,6 +485,10 @@ impl<'a> InferenceContext<'a> {
476 self.return_ty = self.make_ty(&data.type_ref); 485 self.return_ty = self.make_ty(&data.type_ref);
477 } 486 }
478 487
488 fn collect_static(&mut self, data: &StaticData) {
489 self.return_ty = self.make_ty(&data.type_ref);
490 }
491
479 fn collect_fn(&mut self, data: &FunctionData) { 492 fn collect_fn(&mut self, data: &FunctionData) {
480 let body = Arc::clone(&self.body); // avoid borrow checker problem 493 let body = Arc::clone(&self.body); // avoid borrow checker problem
481 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) 494 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
@@ -666,15 +679,57 @@ impl Expectation {
666 } 679 }
667} 680}
668 681
682#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
683enum Diverges {
684 Maybe,
685 Always,
686}
687
688impl Diverges {
689 fn is_always(self) -> bool {
690 self == Diverges::Always
691 }
692}
693
694impl std::ops::BitAnd for Diverges {
695 type Output = Self;
696 fn bitand(self, other: Self) -> Self {
697 std::cmp::min(self, other)
698 }
699}
700
701impl std::ops::BitOr for Diverges {
702 type Output = Self;
703 fn bitor(self, other: Self) -> Self {
704 std::cmp::max(self, other)
705 }
706}
707
708impl std::ops::BitAndAssign for Diverges {
709 fn bitand_assign(&mut self, other: Self) {
710 *self = *self & other;
711 }
712}
713
714impl std::ops::BitOrAssign for Diverges {
715 fn bitor_assign(&mut self, other: Self) {
716 *self = *self | other;
717 }
718}
719
669mod diagnostics { 720mod diagnostics {
670 use hir_def::{expr::ExprId, FunctionId}; 721 use hir_def::{expr::ExprId, FunctionId};
671 use hir_expand::diagnostics::DiagnosticSink; 722 use hir_expand::diagnostics::DiagnosticSink;
672 723
673 use crate::{db::HirDatabase, diagnostics::NoSuchField}; 724 use crate::{
725 db::HirDatabase,
726 diagnostics::{BreakOutsideOfLoop, NoSuchField},
727 };
674 728
675 #[derive(Debug, PartialEq, Eq, Clone)] 729 #[derive(Debug, PartialEq, Eq, Clone)]
676 pub(super) enum InferenceDiagnostic { 730 pub(super) enum InferenceDiagnostic {
677 NoSuchField { expr: ExprId, field: usize }, 731 NoSuchField { expr: ExprId, field: usize },
732 BreakOutsideOfLoop { expr: ExprId },
678 } 733 }
679 734
680 impl InferenceDiagnostic { 735 impl InferenceDiagnostic {
@@ -690,6 +745,13 @@ mod diagnostics {
690 let field = source_map.field_syntax(*expr, *field); 745 let field = source_map.field_syntax(*expr, *field);
691 sink.push(NoSuchField { file: field.file_id, field: field.value }) 746 sink.push(NoSuchField { file: field.file_id, field: field.value })
692 } 747 }
748 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
749 let (_, source_map) = db.body_with_source_map(owner.into());
750 let ptr = source_map
751 .expr_syntax(*expr)
752 .expect("break outside of loop in synthetic syntax");
753 sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
754 }
693 } 755 }
694 } 756 }
695 } 757 }