@@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
62
62
63
63
// While we don't allow *arbitrary* coercions here, we *do* allow
64
64
// coercions from ! to `expected`.
65
- if ty. is_never ( ) {
65
+ if ty. is_never ( ) && self . expr_constitutes_read ( expr ) {
66
66
if let Some ( _) = self . typeck_results . borrow ( ) . adjustments ( ) . get ( expr. hir_id ) {
67
67
let reported = self . dcx ( ) . span_delayed_bug (
68
68
expr. span ,
@@ -260,6 +260,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
260
260
ty
261
261
}
262
262
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>.
263
277
pub ( super ) fn expr_constitutes_read ( & self , expr : & ' tcx hir:: Expr < ' tcx > ) -> bool {
264
278
// We only care about place exprs. Anything else returns an immediate
265
279
// which would constitute a read. We don't care about distinguishing
0 commit comments