mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Correctly handle non-semi statement expressions for never coercions
This commit is contained in:
parent
95c4cb991f
commit
b85e2af898
3 changed files with 37 additions and 14 deletions
|
@ -84,6 +84,30 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn infer_expr_coerce_never(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
||||||
|
let ty = self.infer_expr_inner(expr, expected);
|
||||||
|
// While we don't allow *arbitrary* coercions here, we *do* allow
|
||||||
|
// coercions from ! to `expected`.
|
||||||
|
if ty.is_never() {
|
||||||
|
if let Some(adjustments) = self.result.expr_adjustments.get(&expr) {
|
||||||
|
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &**adjustments {
|
||||||
|
target.clone()
|
||||||
|
} else {
|
||||||
|
self.err_ty()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let adj_ty = self.table.new_type_var();
|
||||||
|
self.write_expr_adj(
|
||||||
|
expr,
|
||||||
|
vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty.clone() }],
|
||||||
|
);
|
||||||
|
adj_ty
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||||
self.db.unwind_if_cancelled();
|
self.db.unwind_if_cancelled();
|
||||||
|
|
||||||
|
@ -91,7 +115,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
Expr::Missing => self.err_ty(),
|
Expr::Missing => self.err_ty(),
|
||||||
&Expr::If { condition, then_branch, else_branch } => {
|
&Expr::If { condition, then_branch, else_branch } => {
|
||||||
let expected = &expected.adjust_for_branches(&mut self.table);
|
let expected = &expected.adjust_for_branches(&mut self.table);
|
||||||
self.infer_expr(
|
self.infer_expr_coerce_never(
|
||||||
condition,
|
condition,
|
||||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||||
);
|
);
|
||||||
|
@ -415,7 +439,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
for arm in arms.iter() {
|
for arm in arms.iter() {
|
||||||
if let Some(guard_expr) = arm.guard {
|
if let Some(guard_expr) = arm.guard {
|
||||||
self.diverges = Diverges::Maybe;
|
self.diverges = Diverges::Maybe;
|
||||||
self.infer_expr(
|
self.infer_expr_coerce_never(
|
||||||
guard_expr,
|
guard_expr,
|
||||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||||
);
|
);
|
||||||
|
@ -1146,7 +1170,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
let coerce_ty = expected.coercion_target_type(&mut self.table);
|
let coerce_ty = expected.coercion_target_type(&mut self.table);
|
||||||
let old_resolver =
|
let old_resolver =
|
||||||
mem::replace(&mut self.resolver, resolver_for_expr(self.db.upcast(), self.owner, expr));
|
mem::replace(&mut self.resolver, resolver_for_expr(self.db.upcast(), self.owner, expr));
|
||||||
|
|
||||||
let (break_ty, ty) =
|
let (break_ty, ty) =
|
||||||
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| {
|
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| {
|
||||||
for stmt in statements {
|
for stmt in statements {
|
||||||
|
@ -1188,14 +1211,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Statement::Expr { expr, has_semi } => {
|
&Statement::Expr { expr, has_semi } => {
|
||||||
this.infer_expr(
|
if has_semi {
|
||||||
expr,
|
this.infer_expr(expr, &Expectation::none());
|
||||||
&if has_semi {
|
} else {
|
||||||
Expectation::none()
|
this.infer_expr_coerce(
|
||||||
} else {
|
expr,
|
||||||
Expectation::HasType(this.result.standard_types.unit.clone())
|
&Expectation::HasType(this.result.standard_types.unit.clone()),
|
||||||
},
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,7 +476,7 @@ fn infer_adt_pattern() {
|
||||||
183..184 'x': usize
|
183..184 'x': usize
|
||||||
190..191 'x': usize
|
190..191 'x': usize
|
||||||
201..205 'E::B': E
|
201..205 'E::B': E
|
||||||
209..212 'foo': bool
|
209..212 'foo': {unknown}
|
||||||
216..217 '1': usize
|
216..217 '1': usize
|
||||||
227..231 'E::B': E
|
227..231 'E::B': E
|
||||||
235..237 '10': usize
|
235..237 '10': usize
|
||||||
|
|
|
@ -270,7 +270,7 @@ fn infer_std_crash_5() {
|
||||||
61..320 '{ ... }': ()
|
61..320 '{ ... }': ()
|
||||||
75..79 'name': &{unknown}
|
75..79 'name': &{unknown}
|
||||||
82..166 'if doe... }': &{unknown}
|
82..166 'if doe... }': &{unknown}
|
||||||
85..98 'doesnt_matter': bool
|
85..98 'doesnt_matter': {unknown}
|
||||||
99..128 '{ ... }': &{unknown}
|
99..128 '{ ... }': &{unknown}
|
||||||
113..118 'first': &{unknown}
|
113..118 'first': &{unknown}
|
||||||
134..166 '{ ... }': &{unknown}
|
134..166 '{ ... }': &{unknown}
|
||||||
|
@ -279,7 +279,7 @@ fn infer_std_crash_5() {
|
||||||
181..188 'content': &{unknown}
|
181..188 'content': &{unknown}
|
||||||
191..313 'if ICE... }': &{unknown}
|
191..313 'if ICE... }': &{unknown}
|
||||||
194..231 'ICE_RE..._VALUE': {unknown}
|
194..231 'ICE_RE..._VALUE': {unknown}
|
||||||
194..247 'ICE_RE...&name)': bool
|
194..247 'ICE_RE...&name)': {unknown}
|
||||||
241..246 '&name': &&{unknown}
|
241..246 '&name': &&{unknown}
|
||||||
242..246 'name': &{unknown}
|
242..246 'name': &{unknown}
|
||||||
248..276 '{ ... }': &{unknown}
|
248..276 '{ ... }': &{unknown}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue