diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-02-10 15:59:49 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-02-10 15:59:49 +0000 |
commit | 7ec03439a89943e46a22fa3c158eb7fffb205666 (patch) | |
tree | 2a9098516877f68242a6d8c7c8fb8bbfd615e19e | |
parent | 82a1b91f205ac9c3d397b2bea033639f5df9e6b6 (diff) | |
parent | 3c5734712a074a5bb3100dbec8b690e60b5beac0 (diff) |
Merge #7627
7627: infer: update resolver when descending into block r=jonas-schievink a=jonas-schievink
Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 29 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 43 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 47 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 51 | ||||
-rw-r--r-- | crates/ide/src/inlay_hints.rs | 1 |
5 files changed, 139 insertions, 32 deletions
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index fbe760c39..1c1423fbf 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -1495,6 +1495,20 @@ fn main(f: Foo) { | |||
1495 | ); | 1495 | ); |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | #[test] | ||
1499 | fn internal_or() { | ||
1500 | check_diagnostics( | ||
1501 | r#" | ||
1502 | fn main() { | ||
1503 | enum Either { A(bool), B } | ||
1504 | match Either::B { | ||
1505 | //^^^^^^^^^ Missing match arm | ||
1506 | Either::A(true | false) => (), | ||
1507 | } | ||
1508 | } | ||
1509 | "#, | ||
1510 | ); | ||
1511 | } | ||
1498 | mod false_negatives { | 1512 | mod false_negatives { |
1499 | //! The implementation of match checking here is a work in progress. As we roll this out, we | 1513 | //! The implementation of match checking here is a work in progress. As we roll this out, we |
1500 | //! prefer false negatives to false positives (ideally there would be no false positives). This | 1514 | //! prefer false negatives to false positives (ideally there would be no false positives). This |
@@ -1521,20 +1535,5 @@ fn main() { | |||
1521 | "#, | 1535 | "#, |
1522 | ); | 1536 | ); |
1523 | } | 1537 | } |
1524 | |||
1525 | #[test] | ||
1526 | fn internal_or() { | ||
1527 | // We do not currently handle patterns with internal `or`s. | ||
1528 | check_diagnostics( | ||
1529 | r#" | ||
1530 | fn main() { | ||
1531 | enum Either { A(bool), B } | ||
1532 | match Either::B { | ||
1533 | Either::A(true | false) => (), | ||
1534 | } | ||
1535 | } | ||
1536 | "#, | ||
1537 | ); | ||
1538 | } | ||
1539 | } | 1538 | } |
1540 | } | 1539 | } |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 12f1591c8..cb59a6937 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -137,24 +137,33 @@ 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 | let old_resolver = mem::replace( |
142 | let break_ty = self.table.new_type_var(); | 142 | &mut self.resolver, |
143 | self.breakables.push(BreakableContext { | 143 | resolver_for_expr(self.db.upcast(), self.owner, tgt_expr), |
144 | may_break: false, | 144 | ); |
145 | break_ty: break_ty.clone(), | 145 | let ty = match label { |
146 | label: label.map(|label| self.body[label].name.clone()), | 146 | Some(_) => { |
147 | }); | 147 | let break_ty = self.table.new_type_var(); |
148 | let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); | 148 | self.breakables.push(BreakableContext { |
149 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | 149 | may_break: false, |
150 | if ctxt.may_break { | 150 | break_ty: break_ty.clone(), |
151 | ctxt.break_ty | 151 | label: label.map(|label| self.body[label].name.clone()), |
152 | } else { | 152 | }); |
153 | ty | 153 | let ty = |
154 | self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); | ||
155 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | ||
156 | if ctxt.may_break { | ||
157 | ctxt.break_ty | ||
158 | } else { | ||
159 | ty | ||
160 | } | ||
154 | } | 161 | } |
155 | } | 162 | None => self.infer_block(statements, *tail, expected), |
156 | None => self.infer_block(statements, *tail, expected), | 163 | }; |
157 | }, | 164 | self.resolver = old_resolver; |
165 | ty | ||
166 | } | ||
158 | Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), | 167 | Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), |
159 | Expr::TryBlock { body } => { | 168 | Expr::TryBlock { body } => { |
160 | let _inner = self.infer_expr(*body, expected); | 169 | 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..20ceb7415 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -2415,3 +2415,50 @@ fn infer_const_params() { | |||
2415 | "#]], | 2415 | "#]], |
2416 | ); | 2416 | ); |
2417 | } | 2417 | } |
2418 | |||
2419 | #[test] | ||
2420 | fn infer_inner_type() { | ||
2421 | check_infer( | ||
2422 | r#" | ||
2423 | fn foo() { | ||
2424 | struct S { field: u32 } | ||
2425 | let s = S { field: 0 }; | ||
2426 | let f = s.field; | ||
2427 | } | ||
2428 | "#, | ||
2429 | expect![[r#" | ||
2430 | 9..89 '{ ...eld; }': () | ||
2431 | 47..48 's': S | ||
2432 | 51..65 'S { field: 0 }': S | ||
2433 | 62..63 '0': u32 | ||
2434 | 75..76 'f': u32 | ||
2435 | 79..80 's': S | ||
2436 | 79..86 's.field': u32 | ||
2437 | "#]], | ||
2438 | ); | ||
2439 | } | ||
2440 | |||
2441 | #[test] | ||
2442 | fn infer_nested_inner_type() { | ||
2443 | check_infer( | ||
2444 | r#" | ||
2445 | fn foo() { | ||
2446 | { | ||
2447 | let s = S { field: 0 }; | ||
2448 | let f = s.field; | ||
2449 | } | ||
2450 | struct S { field: u32 } | ||
2451 | } | ||
2452 | "#, | ||
2453 | expect![[r#" | ||
2454 | 9..109 '{ ...32 } }': () | ||
2455 | 15..79 '{ ... }': () | ||
2456 | 29..30 's': S | ||
2457 | 33..47 'S { field: 0 }': S | ||
2458 | 44..45 '0': u32 | ||
2459 | 61..62 'f': u32 | ||
2460 | 65..66 's': S | ||
2461 | 65..72 's.field': u32 | ||
2462 | "#]], | ||
2463 | ); | ||
2464 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index e5a3f95a6..e030f4a97 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3151,3 +3151,54 @@ fn test() { | |||
3151 | "#, | 3151 | "#, |
3152 | ); | 3152 | ); |
3153 | } | 3153 | } |
3154 | |||
3155 | #[test] | ||
3156 | fn inner_use() { | ||
3157 | check_types( | ||
3158 | r#" | ||
3159 | mod m { | ||
3160 | pub trait Tr { | ||
3161 | fn method(&self) -> u8 { 0 } | ||
3162 | } | ||
3163 | |||
3164 | impl Tr for () {} | ||
3165 | } | ||
3166 | |||
3167 | fn f() { | ||
3168 | use m::Tr; | ||
3169 | |||
3170 | ().method(); | ||
3171 | //^^^^^^^^^^^ u8 | ||
3172 | } | ||
3173 | "#, | ||
3174 | ); | ||
3175 | } | ||
3176 | |||
3177 | #[test] | ||
3178 | fn inner_use_in_block() { | ||
3179 | check_types( | ||
3180 | r#" | ||
3181 | mod m { | ||
3182 | pub trait Tr { | ||
3183 | fn method(&self) -> u8 { 0 } | ||
3184 | } | ||
3185 | |||
3186 | impl Tr for () {} | ||
3187 | } | ||
3188 | |||
3189 | fn f() { | ||
3190 | { | ||
3191 | use m::Tr; | ||
3192 | |||
3193 | ().method(); | ||
3194 | //^^^^^^^^^^^ u8 | ||
3195 | } | ||
3196 | |||
3197 | { | ||
3198 | ().method(); | ||
3199 | //^^^^^^^^^^^ {unknown} | ||
3200 | } | ||
3201 | } | ||
3202 | "#, | ||
3203 | ); | ||
3204 | } | ||
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 2f37c8040..42d0a38e8 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -654,6 +654,7 @@ fn main() { | |||
654 | let test = "test"; | 654 | let test = "test"; |
655 | //^^^^ &str | 655 | //^^^^ &str |
656 | let test = InnerStruct {}; | 656 | let test = InnerStruct {}; |
657 | //^^^^ InnerStruct | ||
657 | 658 | ||
658 | let test = unresolved(); | 659 | let test = unresolved(); |
659 | 660 | ||