@@ -244,12 +244,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
244
244
ExprKind :: MethodCall ( segment, ..) => {
245
245
self . warn_if_unreachable ( expr. hir_id , segment. ident . span , "call" )
246
246
}
247
+ // allow field access when the struct and the field are both uninhabited
248
+ ExprKind :: Field ( ..)
249
+ if matches ! (
250
+ self . diverges. get( ) ,
251
+ Diverges :: Always ( DivergeReason :: Uninhabited , _)
252
+ ) && self . tcx . is_ty_uninhabited_from ( self . parent_module , ty, self . param_env ) => { }
247
253
_ => self . warn_if_unreachable ( expr. hir_id , expr. span , "expression" ) ,
248
254
}
249
255
250
256
// Any expression that produces a value of type `!` must have diverged
251
- if ty. is_never ( ) {
252
- self . diverges . set ( self . diverges . get ( ) | Diverges :: Always ( DivergeReason :: Other , expr) ) ;
257
+ if !self . diverges . get ( ) . is_always ( ) {
258
+ if ty. is_never ( ) {
259
+ self . diverges . set ( Diverges :: Always ( DivergeReason :: Other , expr) ) ;
260
+ } else if expr_may_be_uninhabited ( expr)
261
+ && self . tcx . is_ty_uninhabited_from ( self . parent_module , ty, self . param_env )
262
+ {
263
+ self . diverges . set ( Diverges :: Always ( DivergeReason :: Uninhabited , expr) ) ;
264
+ }
253
265
}
254
266
255
267
// Record the type, which applies it effects.
@@ -2886,3 +2898,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2886
2898
}
2887
2899
}
2888
2900
}
2901
+
2902
+ fn expr_may_be_uninhabited ( expr : & hir:: Expr < ' _ > ) -> bool {
2903
+ match expr. kind {
2904
+ ExprKind :: Call ( ..)
2905
+ | ExprKind :: MethodCall ( ..)
2906
+ | ExprKind :: Cast ( ..)
2907
+ | ExprKind :: Unary ( hir:: UnOp :: Deref , _)
2908
+ | ExprKind :: Field ( ..)
2909
+ | ExprKind :: Path ( ..)
2910
+ | ExprKind :: Struct ( ..) => true ,
2911
+ ExprKind :: Box ( ..)
2912
+ | ExprKind :: ConstBlock ( ..)
2913
+ | ExprKind :: Array ( ..)
2914
+ | ExprKind :: Tup ( ..)
2915
+ | ExprKind :: Binary ( ..)
2916
+ | ExprKind :: Unary ( hir:: UnOp :: Neg | hir:: UnOp :: Not , _)
2917
+ | ExprKind :: Lit ( ..)
2918
+ | ExprKind :: Type ( ..)
2919
+ | ExprKind :: DropTemps ( ..)
2920
+ | ExprKind :: Let ( ..)
2921
+ | ExprKind :: If ( ..)
2922
+ | ExprKind :: Loop ( ..)
2923
+ | ExprKind :: Match ( ..)
2924
+ | ExprKind :: Closure ( ..)
2925
+ | ExprKind :: Block ( ..)
2926
+ | ExprKind :: Assign ( ..)
2927
+ | ExprKind :: AssignOp ( ..)
2928
+ | ExprKind :: Index ( ..)
2929
+ | ExprKind :: AddrOf ( ..)
2930
+ | ExprKind :: Break ( ..)
2931
+ | ExprKind :: Continue ( ..)
2932
+ | ExprKind :: Ret ( ..)
2933
+ | ExprKind :: InlineAsm ( ..)
2934
+ | ExprKind :: Repeat ( ..)
2935
+ | ExprKind :: Yield ( ..)
2936
+ | ExprKind :: Err => false ,
2937
+ }
2938
+ }
0 commit comments