提交 2f4e86b9 编写于 作者: C Cameron Steffen

Enforce diverging let...else

上级 cb4439a3
......@@ -781,6 +781,10 @@ fn note_error_origin(
);
}
}
ObligationCauseCode::LetElse => {
err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
err.help("...or use `match` instead of `let...else`");
}
_ => (),
}
}
......@@ -2592,6 +2596,7 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
}
IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
LetElse => Error0308("`else` clause of `let...else` does not diverge"),
MainFunctionType => Error0580("`main` function has wrong type"),
StartFunctionType => Error0308("`#[start]` function has wrong type"),
IntrinsicType => Error0308("intrinsic has wrong type"),
......
......@@ -305,6 +305,9 @@ pub enum ObligationCauseCode<'tcx> {
/// Intrinsic has wrong type
IntrinsicType,
/// A let else block does not diverge
LetElse,
/// Method receiver
MethodReceiver,
......
......@@ -1928,7 +1928,11 @@ fn note_obligation_cause_code<T>(
| ObligationCauseCode::OpaqueType
| ObligationCauseCode::MiscObligation
| ObligationCauseCode::WellFormed(..)
| ObligationCauseCode::MatchImpl(..) => {}
| ObligationCauseCode::MatchImpl(..)
| ObligationCauseCode::ReturnType
| ObligationCauseCode::ReturnValue(_)
| ObligationCauseCode::BlockTailExpression(_)
| ObligationCauseCode::LetElse => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
}
......@@ -2338,9 +2342,6 @@ fn note_obligation_cause_code<T>(
predicate
));
}
ObligationCauseCode::ReturnType
| ObligationCauseCode::ReturnValue(_)
| ObligationCauseCode::BlockTailExpression(_) => (),
ObligationCauseCode::TrivialBound => {
err.help("see issue #48214");
if tcx.sess.opts.unstable_features.is_nightly_build() {
......
......@@ -849,7 +849,26 @@ fn check_then_else(
coerce.coerce(self, &self.misc(sp), then_expr, then_ty);
if let Some(else_expr) = opt_else_expr {
let else_ty = self.check_expr_with_expectation(else_expr, expected);
let else_ty = if sp.desugaring_kind() == Some(DesugaringKind::LetElse) {
// todo introduce `check_expr_with_expectation(.., Expectation::LetElse)`
// for errors that point to the offending expression rather than the entire block.
// We could use `check_expr_eq_type(.., tcx.types.never)`, but then there is no
// way to detect that the expected type originated from let-else and provide
// a customized error.
let else_ty = self.check_expr(else_expr);
let cause = self.cause(else_expr.span, ObligationCauseCode::LetElse);
if let Some(mut err) =
self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
{
err.emit();
self.tcx.ty_error()
} else {
else_ty
}
} else {
self.check_expr_with_expectation(else_expr, expected)
};
let else_diverges = self.diverges.get();
let opt_suggest_box_span =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册