diff options
| author | bors <bors@rust-lang.org> | 2022-12-30 21:35:46 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-12-30 21:35:46 +0000 |
| commit | ea8897c9be9e63e5d67ccac47287e5dd7bb0d934 (patch) | |
| tree | 42220009364319fb98ecfbc1c1105a37c61552b0 | |
| parent | 6892b16336222c98239ead51158741f82a8a1c32 (diff) | |
| parent | aaa682c534f488b51063e015a23597b344a335ff (diff) | |
| download | rust-ea8897c9be9e63e5d67ccac47287e5dd7bb0d934.tar.gz rust-ea8897c9be9e63e5d67ccac47287e5dd7bb0d934.zip | |
Auto merge of #13856 - WaffleLapkin:typeck_try{}, r=Veykril
fix: Type check unstable `try{}` blocks

Fixes https://github.com/rust-lang/rust-analyzer/issues/11843
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 2 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 17 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/simple.rs | 28 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs | 40 |
4 files changed, 46 insertions, 41 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 7cf4fb10506..18e45511a4b 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -688,7 +688,7 @@ impl<'a> InferenceContext<'a> { } } - /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. + /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it. fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty.kind(Interner) { TyKind::Error => self.table.new_type_var(), diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index b1f4de82607..d4050f9af49 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -152,11 +152,20 @@ impl<'a> InferenceContext<'a> { .1 } Expr::TryBlock { body } => { - self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { - let _inner = this.infer_expr(*body, expected); + // The type that is returned from the try block + let try_ty = self.table.new_type_var(); + if let Some(ty) = expected.only_has_type(&mut self.table) { + self.unify(&try_ty, &ty); + } + + // The ok-ish type that is expected from the last expression + let ok_ty = self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_ok()); + + self.with_breakable_ctx(BreakableKind::Block, ok_ty.clone(), None, |this| { + this.infer_expr(*body, &Expectation::has_type(ok_ty)); }); - // FIXME should be std::result::Result<{inner}, _> - self.err_ty() + + try_ty } Expr::Async { body } => { let ret_ty = self.table.new_type_var(); diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index d7431443b83..146145523b2 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -2064,17 +2064,17 @@ fn fn_pointer_return() { fn block_modifiers_smoke_test() { check_infer( r#" -//- minicore: future +//- minicore: future, try async fn main() { let x = unsafe { 92 }; let y = async { async { () }.await }; - let z = try { () }; + let z: core::ops::ControlFlow<(), _> = try { () }; let w = const { 92 }; let t = 'a: { 92 }; } "#, expect![[r#" - 16..162 '{ ...2 }; }': () + 16..193 '{ ...2 }; }': () 26..27 'x': i32 30..43 'unsafe { 92 }': i32 30..43 'unsafe { 92 }': i32 @@ -2086,17 +2086,17 @@ async fn main() { 65..77 'async { () }': impl Future<Output = ()> 65..83 'async ....await': () 73..75 '()': () - 95..96 'z': {unknown} - 99..109 'try { () }': () - 99..109 'try { () }': {unknown} - 105..107 '()': () - 119..120 'w': i32 - 123..135 'const { 92 }': i32 - 123..135 'const { 92 }': i32 - 131..133 '92': i32 - 145..146 't': i32 - 149..159 ''a: { 92 }': i32 - 155..157 '92': i32 + 95..96 'z': ControlFlow<(), ()> + 130..140 'try { () }': () + 130..140 'try { () }': ControlFlow<(), ()> + 136..138 '()': () + 150..151 'w': i32 + 154..166 'const { 92 }': i32 + 154..166 'const { 92 }': i32 + 162..164 '92': i32 + 176..177 't': i32 + 180..190 ''a: { 92 }': i32 + 186..188 '92': i32 "#]], ) } diff --git a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs index 0c92e706b39..10e637979f2 100644 --- a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs +++ b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs @@ -38,12 +38,12 @@ fn foo() { } #[test] - fn try_blocks_are_borders() { + fn async_blocks_are_borders() { check_diagnostics( r#" fn foo() { 'a: loop { - try { + async { break; //^^^^^ error: break outside of loop break 'a; @@ -60,12 +60,12 @@ fn foo() { } #[test] - fn async_blocks_are_borders() { + fn closures_are_borders() { check_diagnostics( r#" fn foo() { 'a: loop { - try { + || { break; //^^^^^ error: break outside of loop break 'a; @@ -82,21 +82,17 @@ fn foo() { } #[test] - fn closures_are_borders() { + fn blocks_pass_through() { check_diagnostics( r#" fn foo() { 'a: loop { - try { - break; - //^^^^^ error: break outside of loop - break 'a; - //^^^^^^^^ error: break outside of loop - continue; - //^^^^^^^^ error: continue outside of loop - continue 'a; - //^^^^^^^^^^^ error: continue outside of loop - }; + { + break; + break 'a; + continue; + continue 'a; + } } } "#, @@ -104,17 +100,17 @@ fn foo() { } #[test] - fn blocks_pass_through() { + fn try_blocks_pass_through() { check_diagnostics( r#" fn foo() { 'a: loop { - { - break; - break 'a; - continue; - continue 'a; - } + try { + break; + break 'a; + continue; + continue 'a; + }; } } "#, |
