Document things a bit more carefully, also account for coercion in check_expr_has_type_or_error
This commit is contained in:
parent
73d49f8c69
commit
515b93297f
@ -186,6 +186,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||
if self.coerce_never {
|
||||
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
|
||||
} else {
|
||||
// Otherwise the only coercion we can do is unification.
|
||||
return self.unify_and(a, b, identity);
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ pub(crate) fn check_expr_has_type_or_error(
|
||||
|
||||
// While we don't allow *arbitrary* coercions here, we *do* allow
|
||||
// coercions from ! to `expected`.
|
||||
if ty.is_never() {
|
||||
if ty.is_never() && self.expr_constitutes_read(expr) {
|
||||
if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
|
||||
let reported = self.dcx().span_delayed_bug(
|
||||
expr.span,
|
||||
@ -260,6 +260,20 @@ pub(super) fn check_expr_with_expectation_and_args(
|
||||
ty
|
||||
}
|
||||
|
||||
/// Whether this expression constitutes a read of value of the type that
|
||||
/// it evaluates to.
|
||||
///
|
||||
/// This is used to determine if we should consider the block to diverge
|
||||
/// if the expression evaluates to `!`, and if we should insert a `NeverToAny`
|
||||
/// coercion for values of type `!`.
|
||||
///
|
||||
/// This function generally returns `false` if the expression is a place
|
||||
/// expression and the *parent* expression is the scrutinee of a match or
|
||||
/// the pointee of an `&` addr-of expression, since both of those parent
|
||||
/// expressions take a *place* and not a value.
|
||||
///
|
||||
/// This function is unfortunately a bit heuristical, though it is certainly
|
||||
/// far sounder than the prior status quo: <https://github.com/rust-lang/rust/issues/117288>.
|
||||
pub(super) fn expr_constitutes_read(&self, expr: &'tcx hir::Expr<'tcx>) -> bool {
|
||||
// We only care about place exprs. Anything else returns an immediate
|
||||
// which would constitute a read. We don't care about distinguishing
|
||||
|
@ -24,4 +24,3 @@ fn main() {
|
||||
let _ = *x;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@ LL | let c1 = || match x { };
|
||||
| ^ `x` used here but it isn't initialized
|
||||
|
||||
error[E0381]: used binding `x` isn't initialized
|
||||
--> $DIR/pattern-matching-should-fail.rs:15:14
|
||||
--> $DIR/pattern-matching-should-fail.rs:15:23
|
||||
|
|
||||
LL | let x: !;
|
||||
| - binding declared here but left uninitialized
|
||||
LL | let c2 = || match x { _ => () };
|
||||
| ^^ - borrow occurs due to use in closure
|
||||
| |
|
||||
| `x` used here but it isn't initialized
|
||||
| ^ `x` used here but it isn't initialized
|
||||
|
||||
error[E0381]: used binding `variant` isn't initialized
|
||||
--> $DIR/pattern-matching-should-fail.rs:27:13
|
||||
|
Loading…
Reference in New Issue
Block a user