Skip to content

Commit b85e2af

Browse files
committed
Correctly handle non-semi statement expressions for never coercions
1 parent 95c4cb9 commit b85e2af

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

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

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,38 @@ impl<'a> InferenceContext<'a> {
8484
}
8585
}
8686

87+
pub(super) fn infer_expr_coerce_never(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
88+
let ty = self.infer_expr_inner(expr, expected);
89+
// While we don't allow *arbitrary* coercions here, we *do* allow
90+
// coercions from ! to `expected`.
91+
if ty.is_never() {
92+
if let Some(adjustments) = self.result.expr_adjustments.get(&expr) {
93+
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &**adjustments {
94+
target.clone()
95+
} else {
96+
self.err_ty()
97+
};
98+
}
99+
100+
let adj_ty = self.table.new_type_var();
101+
self.write_expr_adj(
102+
expr,
103+
vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty.clone() }],
104+
);
105+
adj_ty
106+
} else {
107+
ty
108+
}
109+
}
110+
87111
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
88112
self.db.unwind_if_cancelled();
89113

90114
let ty = match &self.body[tgt_expr] {
91115
Expr::Missing => self.err_ty(),
92116
&Expr::If { condition, then_branch, else_branch } => {
93117
let expected = &expected.adjust_for_branches(&mut self.table);
94-
self.infer_expr(
118+
self.infer_expr_coerce_never(
95119
condition,
96120
&Expectation::HasType(self.result.standard_types.bool_.clone()),
97121
);
@@ -415,7 +439,7 @@ impl<'a> InferenceContext<'a> {
415439
for arm in arms.iter() {
416440
if let Some(guard_expr) = arm.guard {
417441
self.diverges = Diverges::Maybe;
418-
self.infer_expr(
442+
self.infer_expr_coerce_never(
419443
guard_expr,
420444
&Expectation::HasType(self.result.standard_types.bool_.clone()),
421445
);
@@ -1146,7 +1170,6 @@ impl<'a> InferenceContext<'a> {
11461170
let coerce_ty = expected.coercion_target_type(&mut self.table);
11471171
let old_resolver =
11481172
mem::replace(&mut self.resolver, resolver_for_expr(self.db.upcast(), self.owner, expr));
1149-
11501173
let (break_ty, ty) =
11511174
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| {
11521175
for stmt in statements {
@@ -1188,14 +1211,14 @@ impl<'a> InferenceContext<'a> {
11881211
}
11891212
}
11901213
&Statement::Expr { expr, has_semi } => {
1191-
this.infer_expr(
1192-
expr,
1193-
&if has_semi {
1194-
Expectation::none()
1195-
} else {
1196-
Expectation::HasType(this.result.standard_types.unit.clone())
1197-
},
1198-
);
1214+
if has_semi {
1215+
this.infer_expr(expr, &Expectation::none());
1216+
} else {
1217+
this.infer_expr_coerce(
1218+
expr,
1219+
&Expectation::HasType(this.result.standard_types.unit.clone()),
1220+
);
1221+
}
11991222
}
12001223
}
12011224
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ fn infer_adt_pattern() {
476476
183..184 'x': usize
477477
190..191 'x': usize
478478
201..205 'E::B': E
479-
209..212 'foo': bool
479+
209..212 'foo': {unknown}
480480
216..217 '1': usize
481481
227..231 'E::B': E
482482
235..237 '10': usize

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ fn infer_std_crash_5() {
270270
61..320 '{ ... }': ()
271271
75..79 'name': &{unknown}
272272
82..166 'if doe... }': &{unknown}
273-
85..98 'doesnt_matter': bool
273+
85..98 'doesnt_matter': {unknown}
274274
99..128 '{ ... }': &{unknown}
275275
113..118 'first': &{unknown}
276276
134..166 '{ ... }': &{unknown}
@@ -279,7 +279,7 @@ fn infer_std_crash_5() {
279279
181..188 'content': &{unknown}
280280
191..313 'if ICE... }': &{unknown}
281281
194..231 'ICE_RE..._VALUE': {unknown}
282-
194..247 'ICE_RE...&name)': bool
282+
194..247 'ICE_RE...&name)': {unknown}
283283
241..246 '&name': &&{unknown}
284284
242..246 'name': &{unknown}
285285
248..276 '{ ... }': &{unknown}

0 commit comments

Comments
 (0)