Skip to content

Commit

Permalink
Document things a bit more carefully, also account for coercion in ch…
Browse files Browse the repository at this point in the history
…eck_expr_has_type_or_error
  • Loading branch information
compiler-errors committed Oct 5, 2024
1 parent 73d49f8 commit 515b932
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 6 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ impl<'f, 'tcx> Coerce<'f, '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);
}
}
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// 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,
Expand Down Expand Up @@ -260,6 +260,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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
Expand Down
1 change: 0 additions & 1 deletion tests/mir-opt/uninhabited_not_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ fn main() {
let _ = *x;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 515b932

Please sign in to comment.