@@ -78,6 +78,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
78
78
trace ! ( "UninhabitedEnumBranching starting for {:?}" , body. source) ;
79
79
80
80
let mut removable_switchs = Vec :: new ( ) ;
81
+ let mut otherwise_is_last_variant_switchs = Vec :: new ( ) ;
81
82
82
83
for ( bb, bb_data) in body. basic_blocks . iter_enumerated ( ) {
83
84
trace ! ( "processing block {:?}" , bb) ;
@@ -92,8 +93,14 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
92
93
tcx. param_env_reveal_all_normalized ( body. source . def_id ( ) ) . and ( discriminant_ty) ,
93
94
) ;
94
95
95
- let allowed_variants = if let Ok ( layout) = layout {
96
+ let mut allowed_variants = if let Ok ( layout) = layout {
96
97
variant_discriminants ( & layout, discriminant_ty, tcx)
98
+ } else if let Some ( variant_range) = discriminant_ty. variant_range ( tcx) {
99
+ variant_range
100
+ . map ( |variant| {
101
+ discriminant_ty. discriminant_for_variant ( tcx, variant) . unwrap ( ) . val
102
+ } )
103
+ . collect ( )
97
104
} else {
98
105
continue ;
99
106
} ;
@@ -103,20 +110,29 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
103
110
let terminator = bb_data. terminator ( ) ;
104
111
let TerminatorKind :: SwitchInt { targets, .. } = & terminator. kind else { bug ! ( ) } ;
105
112
106
- let mut reachable_count = 0 ;
107
113
for ( index, ( val, _) ) in targets. iter ( ) . enumerate ( ) {
108
- if allowed_variants. contains ( & val) {
109
- reachable_count += 1 ;
110
- } else {
114
+ if !allowed_variants. remove ( & val) {
111
115
removable_switchs. push ( ( bb, index) ) ;
112
116
}
113
117
}
114
118
115
- if reachable_count == allowed_variants. len ( ) {
119
+ if allowed_variants. is_empty ( ) {
116
120
removable_switchs. push ( ( bb, targets. iter ( ) . count ( ) ) ) ;
121
+ } else if allowed_variants. len ( ) == 1 {
122
+ #[ allow( rustc:: potential_query_instability) ]
123
+ let last_variant = * allowed_variants. iter ( ) . next ( ) . unwrap ( ) ;
124
+ otherwise_is_last_variant_switchs. push ( ( bb, last_variant) ) ;
117
125
}
118
126
}
119
127
128
+ for ( bb, last_variant) in otherwise_is_last_variant_switchs {
129
+ let bb_data = & mut body. basic_blocks . as_mut ( ) [ bb] ;
130
+ let terminator = bb_data. terminator_mut ( ) ;
131
+ let TerminatorKind :: SwitchInt { targets, .. } = & mut terminator. kind else { bug ! ( ) } ;
132
+ targets. add_target ( last_variant, targets. otherwise ( ) ) ;
133
+ removable_switchs. push ( ( bb, targets. iter ( ) . count ( ) ) ) ;
134
+ }
135
+
120
136
if removable_switchs. is_empty ( ) {
121
137
return ;
122
138
}
0 commit comments