diff options
author | Jonas Schievink <[email protected]> | 2021-02-10 13:41:54 +0000 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-02-10 13:41:54 +0000 |
commit | e837df84792d2cbf5c606788c7cab7ea4d1829d0 (patch) | |
tree | 7b9b4e4523803432d157220199a4a11c4821c471 | |
parent | 82a1b91f205ac9c3d397b2bea033639f5df9e6b6 (diff) |
infer: update resolver when descending into block
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 36 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 19 |
2 files changed, 39 insertions, 16 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 12f1591c8..d05c715e7 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -137,24 +137,28 @@ impl<'a> InferenceContext<'a> { | |||
137 | 137 | ||
138 | self.coerce_merge_branch(&then_ty, &else_ty) | 138 | self.coerce_merge_branch(&then_ty, &else_ty) |
139 | } | 139 | } |
140 | Expr::Block { statements, tail, label, id: _ } => match label { | 140 | Expr::Block { statements, tail, label, id: _ } => { |
141 | Some(_) => { | 141 | self.resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
142 | let break_ty = self.table.new_type_var(); | 142 | match label { |
143 | self.breakables.push(BreakableContext { | 143 | Some(_) => { |
144 | may_break: false, | 144 | let break_ty = self.table.new_type_var(); |
145 | break_ty: break_ty.clone(), | 145 | self.breakables.push(BreakableContext { |
146 | label: label.map(|label| self.body[label].name.clone()), | 146 | may_break: false, |
147 | }); | 147 | break_ty: break_ty.clone(), |
148 | let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); | 148 | label: label.map(|label| self.body[label].name.clone()), |
149 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | 149 | }); |
150 | if ctxt.may_break { | 150 | let ty = |
151 | ctxt.break_ty | 151 | self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); |
152 | } else { | 152 | let ctxt = self.breakables.pop().expect("breakable stack broken"); |
153 | ty | 153 | if ctxt.may_break { |
154 | ctxt.break_ty | ||
155 | } else { | ||
156 | ty | ||
157 | } | ||
154 | } | 158 | } |
159 | None => self.infer_block(statements, *tail, expected), | ||
155 | } | 160 | } |
156 | None => self.infer_block(statements, *tail, expected), | 161 | } |
157 | }, | ||
158 | Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), | 162 | Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), |
159 | Expr::TryBlock { body } => { | 163 | Expr::TryBlock { body } => { |
160 | let _inner = self.infer_expr(*body, expected); | 164 | let _inner = self.infer_expr(*body, expected); |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 16682f76f..ab21332fb 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -2415,3 +2415,22 @@ fn infer_const_params() { | |||
2415 | "#]], | 2415 | "#]], |
2416 | ); | 2416 | ); |
2417 | } | 2417 | } |
2418 | |||
2419 | #[test] | ||
2420 | fn infer_inner_type() { | ||
2421 | check_infer(r#" | ||
2422 | fn foo() { | ||
2423 | struct S { field: u32 } | ||
2424 | let s = S { field: 0 }; | ||
2425 | let f = s.field; | ||
2426 | } | ||
2427 | "#, expect![[r#" | ||
2428 | 9..89 '{ ...eld; }': () | ||
2429 | 47..48 's': S | ||
2430 | 51..65 'S { field: 0 }': S | ||
2431 | 62..63 '0': u32 | ||
2432 | 75..76 'f': u32 | ||
2433 | 79..80 's': S | ||
2434 | 79..86 's.field': u32 | ||
2435 | "#]]); | ||
2436 | } | ||