Skip to content

Commit 1addbed

Browse files
Document things a bit more carefully, also account for coercion in check_expr_has_type_or_error
1 parent 0264089 commit 1addbed

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
186186
if self.coerce_never {
187187
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
188188
} else {
189+
// Otherwise the only coercion we can do is unification.
189190
return self.unify_and(a, b, identity);
190191
}
191192
}

compiler/rustc_hir_typeck/src/expr.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6262

6363
// While we don't allow *arbitrary* coercions here, we *do* allow
6464
// coercions from ! to `expected`.
65-
if ty.is_never() {
65+
if ty.is_never() && self.expr_constitutes_read(expr) {
6666
if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
6767
let reported = self.dcx().span_delayed_bug(
6868
expr.span,
@@ -260,6 +260,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
260260
ty
261261
}
262262

263+
/// Whether this expression constitutes a read of value of the type that
264+
/// it evaluates to.
265+
///
266+
/// This is used to determine if we should consider the block to diverge
267+
/// if the expression evaluates to `!`, and if we should insert a `NeverToAny`
268+
/// coercion for values of type `!`.
269+
///
270+
/// This function generally returns `false` if the expression is a place
271+
/// expression and the *parent* expression is the scrutinee of a match or
272+
/// the pointee of an `&` addr-of expression, since both of those parent
273+
/// expressions take a *place* and not a value.
274+
///
275+
/// This function is unfortunately a bit heuristical, though it is certainly
276+
/// far sounder than the prior status quo: <https://github.com/rust-lang/rust/issues/117288>.
263277
pub(super) fn expr_constitutes_read(&self, expr: &'tcx hir::Expr<'tcx>) -> bool {
264278
// We only care about place exprs. Anything else returns an immediate
265279
// which would constitute a read. We don't care about distinguishing

tests/mir-opt/uninhabited_not_read.rs

-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,3 @@ fn main() {
2424
let _ = *x;
2525
}
2626
}
27-

tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@ LL | let c1 = || match x { };
77
| ^ `x` used here but it isn't initialized
88

99
error[E0381]: used binding `x` isn't initialized
10-
--> $DIR/pattern-matching-should-fail.rs:15:14
10+
--> $DIR/pattern-matching-should-fail.rs:15:23
1111
|
1212
LL | let x: !;
1313
| - binding declared here but left uninitialized
1414
LL | let c2 = || match x { _ => () };
15-
| ^^ - borrow occurs due to use in closure
16-
| |
17-
| `x` used here but it isn't initialized
15+
| ^ `x` used here but it isn't initialized
1816

1917
error[E0381]: used binding `variant` isn't initialized
2018
--> $DIR/pattern-matching-should-fail.rs:27:13

0 commit comments

Comments
 (0)