Skip to content

Commit ea8897c

Browse files
committed
Auto merge of #13856 - WaffleLapkin:typeck_try{}, r=Veykril
fix: Type check unstable `try{}` blocks ![Peek 2022-12-29 01-40](https://user-images.githubusercontent.com/38225716/209875594-8bf9c9e2-9998-40b0-8820-28c7f2d9bae4.gif) Fixes #11843
2 parents 6892b16 + aaa682c commit ea8897c

File tree

4 files changed

+46
-41
lines changed

4 files changed

+46
-41
lines changed

crates/hir-ty/src/infer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ impl<'a> InferenceContext<'a> {
688688
}
689689
}
690690

691-
/// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
691+
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
692692
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
693693
match ty.kind(Interner) {
694694
TyKind::Error => self.table.new_type_var(),

crates/hir-ty/src/infer/expr.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,20 @@ impl<'a> InferenceContext<'a> {
152152
.1
153153
}
154154
Expr::TryBlock { body } => {
155-
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
156-
let _inner = this.infer_expr(*body, expected);
155+
// The type that is returned from the try block
156+
let try_ty = self.table.new_type_var();
157+
if let Some(ty) = expected.only_has_type(&mut self.table) {
158+
self.unify(&try_ty, &ty);
159+
}
160+
161+
// The ok-ish type that is expected from the last expression
162+
let ok_ty = self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_ok());
163+
164+
self.with_breakable_ctx(BreakableKind::Block, ok_ty.clone(), None, |this| {
165+
this.infer_expr(*body, &Expectation::has_type(ok_ty));
157166
});
158-
// FIXME should be std::result::Result<{inner}, _>
159-
self.err_ty()
167+
168+
try_ty
160169
}
161170
Expr::Async { body } => {
162171
let ret_ty = self.table.new_type_var();

crates/hir-ty/src/tests/simple.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -2064,17 +2064,17 @@ fn fn_pointer_return() {
20642064
fn block_modifiers_smoke_test() {
20652065
check_infer(
20662066
r#"
2067-
//- minicore: future
2067+
//- minicore: future, try
20682068
async fn main() {
20692069
let x = unsafe { 92 };
20702070
let y = async { async { () }.await };
2071-
let z = try { () };
2071+
let z: core::ops::ControlFlow<(), _> = try { () };
20722072
let w = const { 92 };
20732073
let t = 'a: { 92 };
20742074
}
20752075
"#,
20762076
expect![[r#"
2077-
16..162 '{ ...2 }; }': ()
2077+
16..193 '{ ...2 }; }': ()
20782078
26..27 'x': i32
20792079
30..43 'unsafe { 92 }': i32
20802080
30..43 'unsafe { 92 }': i32
@@ -2086,17 +2086,17 @@ async fn main() {
20862086
65..77 'async { () }': impl Future<Output = ()>
20872087
65..83 'async ....await': ()
20882088
73..75 '()': ()
2089-
95..96 'z': {unknown}
2090-
99..109 'try { () }': ()
2091-
99..109 'try { () }': {unknown}
2092-
105..107 '()': ()
2093-
119..120 'w': i32
2094-
123..135 'const { 92 }': i32
2095-
123..135 'const { 92 }': i32
2096-
131..133 '92': i32
2097-
145..146 't': i32
2098-
149..159 ''a: { 92 }': i32
2099-
155..157 '92': i32
2089+
95..96 'z': ControlFlow<(), ()>
2090+
130..140 'try { () }': ()
2091+
130..140 'try { () }': ControlFlow<(), ()>
2092+
136..138 '()': ()
2093+
150..151 'w': i32
2094+
154..166 'const { 92 }': i32
2095+
154..166 'const { 92 }': i32
2096+
162..164 '92': i32
2097+
176..177 't': i32
2098+
180..190 ''a: { 92 }': i32
2099+
186..188 '92': i32
21002100
"#]],
21012101
)
21022102
}

crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs

+18-22
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ fn foo() {
3838
}
3939

4040
#[test]
41-
fn try_blocks_are_borders() {
41+
fn async_blocks_are_borders() {
4242
check_diagnostics(
4343
r#"
4444
fn foo() {
4545
'a: loop {
46-
try {
46+
async {
4747
break;
4848
//^^^^^ error: break outside of loop
4949
break 'a;
@@ -60,12 +60,12 @@ fn foo() {
6060
}
6161

6262
#[test]
63-
fn async_blocks_are_borders() {
63+
fn closures_are_borders() {
6464
check_diagnostics(
6565
r#"
6666
fn foo() {
6767
'a: loop {
68-
try {
68+
|| {
6969
break;
7070
//^^^^^ error: break outside of loop
7171
break 'a;
@@ -82,39 +82,35 @@ fn foo() {
8282
}
8383

8484
#[test]
85-
fn closures_are_borders() {
85+
fn blocks_pass_through() {
8686
check_diagnostics(
8787
r#"
8888
fn foo() {
8989
'a: loop {
90-
try {
91-
break;
92-
//^^^^^ error: break outside of loop
93-
break 'a;
94-
//^^^^^^^^ error: break outside of loop
95-
continue;
96-
//^^^^^^^^ error: continue outside of loop
97-
continue 'a;
98-
//^^^^^^^^^^^ error: continue outside of loop
99-
};
90+
{
91+
break;
92+
break 'a;
93+
continue;
94+
continue 'a;
95+
}
10096
}
10197
}
10298
"#,
10399
);
104100
}
105101

106102
#[test]
107-
fn blocks_pass_through() {
103+
fn try_blocks_pass_through() {
108104
check_diagnostics(
109105
r#"
110106
fn foo() {
111107
'a: loop {
112-
{
113-
break;
114-
break 'a;
115-
continue;
116-
continue 'a;
117-
}
108+
try {
109+
break;
110+
break 'a;
111+
continue;
112+
continue 'a;
113+
};
118114
}
119115
}
120116
"#,

0 commit comments

Comments
 (0)