mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
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
This commit is contained in:
commit
ea8897c9be
@ -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 {
|
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
||||||
match ty.kind(Interner) {
|
match ty.kind(Interner) {
|
||||||
TyKind::Error => self.table.new_type_var(),
|
TyKind::Error => self.table.new_type_var(),
|
||||||
|
@ -152,11 +152,20 @@ impl<'a> InferenceContext<'a> {
|
|||||||
.1
|
.1
|
||||||
}
|
}
|
||||||
Expr::TryBlock { body } => {
|
Expr::TryBlock { body } => {
|
||||||
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
|
// The type that is returned from the try block
|
||||||
let _inner = this.infer_expr(*body, expected);
|
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 } => {
|
Expr::Async { body } => {
|
||||||
let ret_ty = self.table.new_type_var();
|
let ret_ty = self.table.new_type_var();
|
||||||
|
@ -2064,17 +2064,17 @@ fn fn_pointer_return() {
|
|||||||
fn block_modifiers_smoke_test() {
|
fn block_modifiers_smoke_test() {
|
||||||
check_infer(
|
check_infer(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: future
|
//- minicore: future, try
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let x = unsafe { 92 };
|
let x = unsafe { 92 };
|
||||||
let y = async { async { () }.await };
|
let y = async { async { () }.await };
|
||||||
let z = try { () };
|
let z: core::ops::ControlFlow<(), _> = try { () };
|
||||||
let w = const { 92 };
|
let w = const { 92 };
|
||||||
let t = 'a: { 92 };
|
let t = 'a: { 92 };
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
16..162 '{ ...2 }; }': ()
|
16..193 '{ ...2 }; }': ()
|
||||||
26..27 'x': i32
|
26..27 'x': i32
|
||||||
30..43 'unsafe { 92 }': i32
|
30..43 'unsafe { 92 }': 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..77 'async { () }': impl Future<Output = ()>
|
||||||
65..83 'async ....await': ()
|
65..83 'async ....await': ()
|
||||||
73..75 '()': ()
|
73..75 '()': ()
|
||||||
95..96 'z': {unknown}
|
95..96 'z': ControlFlow<(), ()>
|
||||||
99..109 'try { () }': ()
|
130..140 'try { () }': ()
|
||||||
99..109 'try { () }': {unknown}
|
130..140 'try { () }': ControlFlow<(), ()>
|
||||||
105..107 '()': ()
|
136..138 '()': ()
|
||||||
119..120 'w': i32
|
150..151 'w': i32
|
||||||
123..135 'const { 92 }': i32
|
154..166 'const { 92 }': i32
|
||||||
123..135 'const { 92 }': i32
|
154..166 'const { 92 }': i32
|
||||||
131..133 '92': i32
|
162..164 '92': i32
|
||||||
145..146 't': i32
|
176..177 't': i32
|
||||||
149..159 ''a: { 92 }': i32
|
180..190 ''a: { 92 }': i32
|
||||||
155..157 '92': i32
|
186..188 '92': i32
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -37,35 +37,13 @@ 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]
|
#[test]
|
||||||
fn async_blocks_are_borders() {
|
fn async_blocks_are_borders() {
|
||||||
check_diagnostics(
|
check_diagnostics(
|
||||||
r#"
|
r#"
|
||||||
fn foo() {
|
fn foo() {
|
||||||
'a: loop {
|
'a: loop {
|
||||||
try {
|
async {
|
||||||
break;
|
break;
|
||||||
//^^^^^ error: break outside of loop
|
//^^^^^ error: break outside of loop
|
||||||
break 'a;
|
break 'a;
|
||||||
@ -87,7 +65,7 @@ fn foo() {
|
|||||||
r#"
|
r#"
|
||||||
fn foo() {
|
fn foo() {
|
||||||
'a: loop {
|
'a: loop {
|
||||||
try {
|
|| {
|
||||||
break;
|
break;
|
||||||
//^^^^^ error: break outside of loop
|
//^^^^^ error: break outside of loop
|
||||||
break 'a;
|
break 'a;
|
||||||
@ -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]
|
#[test]
|
||||||
fn label_blocks() {
|
fn label_blocks() {
|
||||||
check_diagnostics(
|
check_diagnostics(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user