@@ -1048,15 +1048,23 @@ impl<'a> MethodDef<'a> {
1048
1048
/// discriminant values. See issue #15523.)
1049
1049
1050
1050
/// ```{.text}
1051
- /// match (this, that, ...) {
1052
- /// (Variant1, Variant1, Variant1) => ... // delegate Matching on Variant1
1053
- /// (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2
1054
- /// ...
1055
- /// _ => {
1056
- /// let __this_vi = match this { Variant1 => 0, Variant2 => 1, ... };
1057
- /// let __that_vi = match that { Variant1 => 0, Variant2 => 1, ... };
1051
+ /// let __self0_vi = unsafe {
1052
+ /// std::intrinsics::discriminant_value(&self) } as i32;
1053
+ /// let __self1_vi = unsafe {
1054
+ /// std::intrinsics::discriminant_value(&__arg1) } as i32;
1055
+ /// let __self2_vi = unsafe {
1056
+ /// std::intrinsics::discriminant_value(&__arg2) } as i32;
1057
+ ///
1058
+ /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
1059
+ /// match (...) {
1060
+ /// (Variant1, Variant1, ...) => Body1
1061
+ /// (Variant2, Variant2, ...) => Body2,
1062
+ /// ...
1063
+ /// _ => ::core::intrinsics::unreachable()
1064
+ /// }
1065
+ /// }
1066
+ /// else {
1058
1067
/// ... // catch-all remainder can inspect above variant index values.
1059
- /// }
1060
1068
/// }
1061
1069
/// ```
1062
1070
fn build_enum_match_tuple < ' b > (
@@ -1187,7 +1195,6 @@ impl<'a> MethodDef<'a> {
1187
1195
1188
1196
cx. arm ( sp, vec ! [ single_pat] , arm_expr)
1189
1197
} ) . collect ( ) ;
1190
-
1191
1198
// We will usually need the catch-all after matching the
1192
1199
// tuples `(VariantK, VariantK, ...)` for each VariantK of the
1193
1200
// enum. But:
@@ -1223,9 +1230,14 @@ impl<'a> MethodDef<'a> {
1223
1230
// ```
1224
1231
let mut index_let_stmts: Vec < P < ast:: Stmt > > = Vec :: new ( ) ;
1225
1232
1233
+ //We also build an expression which checks whether all discriminants are equal
1234
+ // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
1235
+ let mut discriminant_test = cx. expr_bool ( sp, true ) ;
1236
+
1226
1237
let target_type_name =
1227
1238
find_repr_type_name ( & cx. parse_sess . span_diagnostic , type_attrs) ;
1228
1239
1240
+ let mut first_ident = None ;
1229
1241
for ( & ident, self_arg) in vi_idents. iter ( ) . zip ( & self_args) {
1230
1242
let path = vec ! [ cx. ident_of_std( "core" ) ,
1231
1243
cx. ident_of( "intrinsics" ) ,
@@ -1243,32 +1255,64 @@ impl<'a> MethodDef<'a> {
1243
1255
let variant_disr = cx. expr_cast ( sp, variant_value, target_ty) ;
1244
1256
let let_stmt = cx. stmt_let ( sp, false , ident, variant_disr) ;
1245
1257
index_let_stmts. push ( let_stmt) ;
1258
+
1259
+ match first_ident {
1260
+ Some ( first) => {
1261
+ let first_expr = cx. expr_ident ( sp, first) ;
1262
+ let id = cx. expr_ident ( sp, ident) ;
1263
+ let test = cx. expr_binary ( sp, ast:: BiEq , first_expr, id) ;
1264
+ discriminant_test = cx. expr_binary ( sp, ast:: BiAnd , discriminant_test, test)
1265
+ }
1266
+ None => {
1267
+ first_ident = Some ( ident) ;
1268
+ }
1269
+ }
1246
1270
}
1247
1271
1248
1272
let arm_expr = self . call_substructure_method (
1249
1273
cx, trait_, type_ident, & self_args[ ..] , nonself_args,
1250
1274
& catch_all_substructure) ;
1251
1275
1252
- // Builds the expression:
1253
- // {
1254
- // let __self0_vi = ...;
1255
- // let __self1_vi = ...;
1256
- // ...
1257
- // <delegated expression referring to __self0_vi, et al.>
1258
- // }
1259
- let arm_expr = cx. expr_block (
1260
- cx. block_all ( sp, index_let_stmts, Some ( arm_expr) ) ) ;
1261
-
1262
- // Builds arm:
1263
- // _ => { let __self0_vi = ...;
1264
- // let __self1_vi = ...;
1265
- // ...
1266
- // <delegated expression as above> }
1267
- let catch_all_match_arm =
1268
- cx. arm ( sp, vec ! [ cx. pat_wild( sp) ] , arm_expr) ;
1269
-
1270
- match_arms. push ( catch_all_match_arm) ;
1271
-
1276
+ //Since we know that all the arguments will match if we reach the match expression we
1277
+ //add the unreachable intrinsics as the result of the catch all which should help llvm
1278
+ //in optimizing it
1279
+ let path = vec ! [ cx. ident_of_std( "core" ) ,
1280
+ cx. ident_of( "intrinsics" ) ,
1281
+ cx. ident_of( "unreachable" ) ] ;
1282
+ let call = cx. expr_call_global (
1283
+ sp, path, vec ! [ ] ) ;
1284
+ let unreachable = cx. expr_block ( P ( ast:: Block {
1285
+ stmts : vec ! [ ] ,
1286
+ expr : Some ( call) ,
1287
+ id : ast:: DUMMY_NODE_ID ,
1288
+ rules : ast:: UnsafeBlock ( ast:: CompilerGenerated ) ,
1289
+ span : sp } ) ) ;
1290
+ match_arms. push ( cx. arm ( sp, vec ! [ cx. pat_wild( sp) ] , unreachable) ) ;
1291
+
1292
+ // Final wrinkle: the self_args are expressions that deref
1293
+ // down to desired l-values, but we cannot actually deref
1294
+ // them when they are fed as r-values into a tuple
1295
+ // expression; here add a layer of borrowing, turning
1296
+ // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1297
+ let borrowed_self_args = self_args. move_map ( |self_arg| cx. expr_addr_of ( sp, self_arg) ) ;
1298
+ let match_arg = cx. expr ( sp, ast:: ExprTup ( borrowed_self_args) ) ;
1299
+
1300
+ //Lastly we create an expression which branches on all discriminants being equal
1301
+ // if discriminant_test {
1302
+ // match (...) {
1303
+ // (Variant1, Variant1, ...) => Body1
1304
+ // (Variant2, Variant2, ...) => Body2,
1305
+ // ...
1306
+ // _ => ::core::intrinsics::unreachable()
1307
+ // }
1308
+ // }
1309
+ // else {
1310
+ // <delegated expression referring to __self0_vi, et al.>
1311
+ // }
1312
+ let all_match = cx. expr_match ( sp, match_arg, match_arms) ;
1313
+ let arm_expr = cx. expr_if ( sp, discriminant_test, all_match, Some ( arm_expr) ) ;
1314
+ cx. expr_block (
1315
+ cx. block_all ( sp, index_let_stmts, Some ( arm_expr) ) )
1272
1316
} else if variants. is_empty ( ) {
1273
1317
// As an additional wrinkle, For a zero-variant enum A,
1274
1318
// currently the compiler
@@ -1319,17 +1363,19 @@ impl<'a> MethodDef<'a> {
1319
1363
// derive Debug on such a type could here generate code
1320
1364
// that needs the feature gate enabled.)
1321
1365
1322
- return cx. expr_unreachable ( sp) ;
1366
+ cx. expr_unreachable ( sp)
1367
+ }
1368
+ else {
1369
+
1370
+ // Final wrinkle: the self_args are expressions that deref
1371
+ // down to desired l-values, but we cannot actually deref
1372
+ // them when they are fed as r-values into a tuple
1373
+ // expression; here add a layer of borrowing, turning
1374
+ // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1375
+ let borrowed_self_args = self_args. move_map ( |self_arg| cx. expr_addr_of ( sp, self_arg) ) ;
1376
+ let match_arg = cx. expr ( sp, ast:: ExprTup ( borrowed_self_args) ) ;
1377
+ cx. expr_match ( sp, match_arg, match_arms)
1323
1378
}
1324
-
1325
- // Final wrinkle: the self_args are expressions that deref
1326
- // down to desired l-values, but we cannot actually deref
1327
- // them when they are fed as r-values into a tuple
1328
- // expression; here add a layer of borrowing, turning
1329
- // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1330
- let borrowed_self_args = self_args. move_map ( |self_arg| cx. expr_addr_of ( sp, self_arg) ) ;
1331
- let match_arg = cx. expr ( sp, ast:: ExprTup ( borrowed_self_args) ) ;
1332
- cx. expr_match ( sp, match_arg, match_arms)
1333
1379
}
1334
1380
1335
1381
fn expand_static_enum_method_body ( & self ,
0 commit comments