From 16264a3a53765d692e55ba73c74bb3abc653cb4b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 20:43:12 +0000 Subject: [PATCH 1/5] fixup a doc comment --- crates/hir-ty/src/infer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 7cf4fb1050..18e45511a4 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(), From eecab99dec7a812199d2c403013d393dd1dec680 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 20:46:45 +0000 Subject: [PATCH 2/5] Allow `break` and co to go through `try{}` blocks --- crates/hir-ty/src/infer/expr.rs | 2 +- .../src/handlers/break_outside_of_loop.rs | 40 +++++++++---------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index b1f4de8260..0d3f15c3d5 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -152,7 +152,7 @@ impl<'a> InferenceContext<'a> { .1 } Expr::TryBlock { body } => { - self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| { + self.with_breakable_ctx(BreakableKind::Block, self.err_ty(), None, |this| { let _inner = this.infer_expr(*body, expected); }); // FIXME should be std::result::Result<{inner}, _> 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 0c92e706b3..7a957e1c50 100644 --- a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs +++ b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs @@ -37,28 +37,6 @@ fn foo() { ); } - #[test] - fn try_blocks_are_borders() { - 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 - }; - } -} -"#, - ); - } - #[test] fn async_blocks_are_borders() { check_diagnostics( @@ -121,6 +99,24 @@ fn foo() { ); } + #[test] + fn try_blocks_pass_through() { + check_diagnostics( + r#" +fn foo() { + 'a: loop { + try { + break; + break 'a; + continue; + continue 'a; + }; + } +} +"#, + ); + } + #[test] fn label_blocks() { check_diagnostics( From 797da9e8da3a464ba9b0ce6420e4323ed8e53dc1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 20:53:55 +0000 Subject: [PATCH 3/5] Actually test `async{}` blocks in `async_blocks_are_borders` --- crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7a957e1c50..a27996593a 100644 --- a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs +++ b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs @@ -43,7 +43,7 @@ fn foo() { r#" fn foo() { 'a: loop { - try { + async { break; //^^^^^ error: break outside of loop break 'a; From ef303f224fb67fa09fe007894242828fa17d24f8 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 20:54:38 +0000 Subject: [PATCH 4/5] Actually test closures in `closures_are_borders` --- crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a27996593a..10e637979f 100644 --- a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs +++ b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs @@ -65,7 +65,7 @@ fn foo() { r#" fn foo() { 'a: loop { - try { + || { break; //^^^^^ error: break outside of loop break 'a; From aaa682c534f488b51063e015a23597b344a335ff Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 21:25:47 +0000 Subject: [PATCH 5/5] Implement `try{}` block type inference --- crates/hir-ty/src/infer/expr.rs | 17 +++++++++++++---- crates/hir-ty/src/tests/simple.rs | 28 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 0d3f15c3d5..d4050f9af4 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::Block, 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 d7431443b8..146145523b 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 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 "#]], ) }