@@ -183,7 +183,6 @@ use rustc_ast::ptr::P;
183
183
use rustc_ast:: { self as ast, BinOpKind , EnumDef , Expr , Generics , PatKind } ;
184
184
use rustc_ast:: { GenericArg , GenericParamKind , VariantData } ;
185
185
use rustc_attr as attr;
186
- use rustc_data_structures:: map_in_place:: MapInPlace ;
187
186
use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
188
187
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
189
188
use rustc_span:: Span ;
@@ -455,7 +454,6 @@ impl<'a> TraitDef<'a> {
455
454
} ;
456
455
let container_id = cx. current_expansion . id . expn_data ( ) . parent . expect_local ( ) ;
457
456
let always_copy = has_no_type_params && cx. resolver . has_derive_copy ( container_id) ;
458
- let use_temporaries = is_packed && always_copy;
459
457
460
458
let newitem = match item. kind {
461
459
ast:: ItemKind :: Struct ( ref struct_def, ref generics) => self . expand_struct_def (
@@ -464,11 +462,11 @@ impl<'a> TraitDef<'a> {
464
462
item. ident ,
465
463
generics,
466
464
from_scratch,
467
- use_temporaries,
468
465
is_packed,
466
+ always_copy,
469
467
) ,
470
468
ast:: ItemKind :: Enum ( ref enum_def, ref generics) => {
471
- // We ignore `use_temporaries ` here, because
469
+ // We ignore `is_packed`/`always_copy ` here, because
472
470
// `repr(packed)` enums cause an error later on.
473
471
//
474
472
// This can only cause further compilation errors
@@ -484,8 +482,8 @@ impl<'a> TraitDef<'a> {
484
482
item. ident ,
485
483
generics,
486
484
from_scratch,
487
- use_temporaries,
488
485
is_packed,
486
+ always_copy,
489
487
)
490
488
} else {
491
489
cx. span_err ( mitem. span , "this trait cannot be derived for unions" ) ;
@@ -766,8 +764,8 @@ impl<'a> TraitDef<'a> {
766
764
type_ident : Ident ,
767
765
generics : & Generics ,
768
766
from_scratch : bool ,
769
- use_temporaries : bool ,
770
767
is_packed : bool ,
768
+ always_copy : bool ,
771
769
) -> P < ast:: Item > {
772
770
let field_tys: Vec < P < ast:: Ty > > =
773
771
struct_def. fields ( ) . iter ( ) . map ( |field| field. ty . clone ( ) ) . collect ( ) ;
@@ -795,8 +793,8 @@ impl<'a> TraitDef<'a> {
795
793
type_ident,
796
794
& selflike_args,
797
795
& nonselflike_args,
798
- use_temporaries,
799
796
is_packed,
797
+ always_copy,
800
798
)
801
799
} ;
802
800
@@ -937,9 +935,7 @@ impl<'a> MethodDef<'a> {
937
935
938
936
match ty {
939
937
// Selflike (`&Self`) arguments only occur in non-static methods.
940
- Ref ( box Self_ , _) if !self . is_static ( ) => {
941
- selflike_args. push ( cx. expr_deref ( span, arg_expr) )
942
- }
938
+ Ref ( box Self_ , _) if !self . is_static ( ) => selflike_args. push ( arg_expr) ,
943
939
Self_ => cx. span_bug ( span, "`Self` in non-return position" ) ,
944
940
_ => nonselflike_args. push ( arg_expr) ,
945
941
}
@@ -1025,9 +1021,9 @@ impl<'a> MethodDef<'a> {
1025
1021
/// # struct A { x: i32, y: i32 }
1026
1022
/// impl PartialEq for A {
1027
1023
/// fn eq(&self, other: &A) -> bool {
1028
- /// let Self { x: ref __self_0_0, y: ref __self_0_1 } = *self;
1029
- /// let Self { x: ref __self_1_0, y: ref __self_1_1 } = *other;
1030
- /// * __self_0_0 == * __self_1_0 && * __self_0_1 == * __self_1_1
1024
+ /// let Self { x: __self_0_0, y: __self_0_1 } = *self;
1025
+ /// let Self { x: __self_1_0, y: __self_1_1 } = *other;
1026
+ /// __self_0_0 == __self_1_0 && __self_0_1 == __self_1_1
1031
1027
/// }
1032
1028
/// }
1033
1029
/// ```
@@ -1039,8 +1035,8 @@ impl<'a> MethodDef<'a> {
1039
1035
type_ident : Ident ,
1040
1036
selflike_args : & [ P < Expr > ] ,
1041
1037
nonselflike_args : & [ P < Expr > ] ,
1042
- use_temporaries : bool ,
1043
1038
is_packed : bool ,
1039
+ always_copy : bool ,
1044
1040
) -> BlockOrExpr {
1045
1041
let span = trait_. span ;
1046
1042
assert ! ( selflike_args. len( ) == 1 || selflike_args. len( ) == 2 ) ;
@@ -1062,23 +1058,21 @@ impl<'a> MethodDef<'a> {
1062
1058
} else {
1063
1059
let prefixes: Vec < _ > =
1064
1060
( 0 ..selflike_args. len ( ) ) . map ( |i| format ! ( "__self_{}" , i) ) . collect ( ) ;
1061
+ let no_deref = always_copy;
1065
1062
let selflike_fields =
1066
- trait_. create_struct_pattern_fields ( cx, struct_def, & prefixes, use_temporaries ) ;
1063
+ trait_. create_struct_pattern_fields ( cx, struct_def, & prefixes, no_deref ) ;
1067
1064
let mut body = mk_body ( cx, selflike_fields) ;
1068
1065
1069
1066
let struct_path = cx. path ( span, vec ! [ Ident :: new( kw:: SelfUpper , type_ident. span) ] ) ;
1070
- let patterns = trait_. create_struct_patterns (
1071
- cx,
1072
- struct_path,
1073
- struct_def,
1074
- & prefixes,
1075
- use_temporaries,
1076
- ) ;
1067
+ let use_ref_pat = is_packed && !always_copy;
1068
+ let patterns =
1069
+ trait_. create_struct_patterns ( cx, struct_path, struct_def, & prefixes, use_ref_pat) ;
1077
1070
1078
1071
// Do the let-destructuring.
1079
1072
let mut stmts: Vec < _ > = iter:: zip ( selflike_args, patterns)
1080
1073
. map ( |( selflike_arg_expr, pat) | {
1081
- cx. stmt_let_pat ( span, pat, selflike_arg_expr. clone ( ) )
1074
+ let selflike_arg_expr = cx. expr_deref ( span, selflike_arg_expr. clone ( ) ) ;
1075
+ cx. stmt_let_pat ( span, pat, selflike_arg_expr)
1082
1076
} )
1083
1077
. collect ( ) ;
1084
1078
stmts. extend ( std:: mem:: take ( & mut body. 0 ) ) ;
@@ -1118,18 +1112,16 @@ impl<'a> MethodDef<'a> {
1118
1112
/// impl ::core::cmp::PartialEq for A {
1119
1113
/// #[inline]
1120
1114
/// fn eq(&self, other: &A) -> bool {
1121
- /// {
1122
- /// let __self_vi = ::core::intrinsics::discriminant_value(&*self);
1123
- /// let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
1124
- /// if true && __self_vi == __arg_1_vi {
1125
- /// match (&*self, &*other) {
1126
- /// (&A::A2(ref __self_0), &A::A2(ref __arg_1_0)) =>
1127
- /// (*__self_0) == (*__arg_1_0),
1128
- /// _ => true,
1129
- /// }
1130
- /// } else {
1131
- /// false // catch-all handler
1115
+ /// let __self_vi = ::core::intrinsics::discriminant_value(self);
1116
+ /// let __arg_1_vi = ::core::intrinsics::discriminant_value(other);
1117
+ /// if __self_vi == __arg_1_vi {
1118
+ /// match (self, other) {
1119
+ /// (A::A2(__self_0), A::A2(__arg_1_0)) =>
1120
+ /// *__self_0 == *__arg_1_0,
1121
+ /// _ => true,
1132
1122
/// }
1123
+ /// } else {
1124
+ /// false // catch-all handler
1133
1125
/// }
1134
1126
/// }
1135
1127
/// }
@@ -1202,28 +1194,21 @@ impl<'a> MethodDef<'a> {
1202
1194
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
1203
1195
// (see "Final wrinkle" note below for why.)
1204
1196
1205
- let use_temporaries = false ; // enums can't be repr(packed)
1206
- let fields = trait_. create_struct_pattern_fields (
1197
+ let no_deref = false ; // because enums can't be repr(packed)
1198
+ let fields =
1199
+ trait_. create_struct_pattern_fields ( cx, & variant. data , & prefixes, no_deref) ;
1200
+
1201
+ let sp = variant. span . with_ctxt ( trait_. span . ctxt ( ) ) ;
1202
+ let variant_path = cx. path ( sp, vec ! [ type_ident, variant. ident] ) ;
1203
+ let use_ref_pat = false ; // because enums can't be repr(packed)
1204
+ let mut subpats: Vec < _ > = trait_. create_struct_patterns (
1207
1205
cx,
1206
+ variant_path,
1208
1207
& variant. data ,
1209
1208
& prefixes,
1210
- use_temporaries ,
1209
+ use_ref_pat ,
1211
1210
) ;
1212
1211
1213
- let sp = variant. span . with_ctxt ( trait_. span . ctxt ( ) ) ;
1214
- let variant_path = cx. path ( sp, vec ! [ type_ident, variant. ident] ) ;
1215
- let mut subpats: Vec < _ > = trait_
1216
- . create_struct_patterns (
1217
- cx,
1218
- variant_path,
1219
- & variant. data ,
1220
- & prefixes,
1221
- use_temporaries,
1222
- )
1223
- . into_iter ( )
1224
- . map ( |p| cx. pat ( span, PatKind :: Ref ( p, ast:: Mutability :: Not ) ) )
1225
- . collect ( ) ;
1226
-
1227
1212
// Here is the pat = `(&VariantK, &VariantK, ...)`
1228
1213
let single_pat = if subpats. len ( ) == 1 {
1229
1214
subpats. pop ( ) . unwrap ( )
@@ -1302,25 +1287,23 @@ impl<'a> MethodDef<'a> {
1302
1287
// Build a series of let statements mapping each selflike_arg
1303
1288
// to its discriminant value.
1304
1289
//
1305
- // i.e., for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
1306
- // with three Self args, builds three statements:
1290
+ // i.e., for `enum E<T> { A, B(1), C(T, T) }` for `PartialEq::eq`,
1291
+ // builds two statements:
1307
1292
// ```
1308
- // let __self_vi = std::intrinsics::discriminant_value(&self);
1309
- // let __arg_1_vi = std::intrinsics::discriminant_value(&arg1);
1310
- // let __arg_2_vi = std::intrinsics::discriminant_value(&arg2);
1293
+ // let __self_vi = ::core::intrinsics::discriminant_value(self);
1294
+ // let __arg_1_vi = ::core::intrinsics::discriminant_value(other);
1311
1295
// ```
1312
1296
let mut index_let_stmts: Vec < ast:: Stmt > = Vec :: with_capacity ( vi_idents. len ( ) + 1 ) ;
1313
1297
1314
- // We also build an expression which checks whether all discriminants are equal:
1315
- // `__self_vi == __arg_1_vi && __self_vi == __arg_2_vi && ...`
1298
+ // We also build an expression which checks whether all discriminants are equal, e.g.
1299
+ // `__self_vi == __arg_1_vi`.
1316
1300
let mut discriminant_test = cx. expr_bool ( span, true ) ;
1317
1301
for ( i, ( & ident, selflike_arg) ) in iter:: zip ( & vi_idents, & selflike_args) . enumerate ( ) {
1318
- let selflike_addr = cx. expr_addr_of ( span, selflike_arg. clone ( ) ) ;
1319
1302
let variant_value = deriving:: call_intrinsic (
1320
1303
cx,
1321
1304
span,
1322
1305
sym:: discriminant_value,
1323
- vec ! [ selflike_addr ] ,
1306
+ vec ! [ selflike_arg . clone ( ) ] ,
1324
1307
) ;
1325
1308
let let_stmt = cx. stmt_let ( span, false , ident, variant_value) ;
1326
1309
index_let_stmts. push ( let_stmt) ;
@@ -1347,17 +1330,11 @@ impl<'a> MethodDef<'a> {
1347
1330
)
1348
1331
. into_expr ( cx, span) ;
1349
1332
1350
- // Final wrinkle: the selflike_args are expressions that deref
1351
- // down to desired places, but we cannot actually deref
1352
- // them when they are fed as r-values into a tuple
1353
- // expression; here add a layer of borrowing, turning
1354
- // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1355
- selflike_args. map_in_place ( |selflike_arg| cx. expr_addr_of ( span, selflike_arg) ) ;
1356
1333
let match_arg = cx. expr ( span, ast:: ExprKind :: Tup ( selflike_args) ) ;
1357
1334
1358
- // Lastly we create an expression which branches on all discriminants being equal
1359
- // if discriminant_test {
1360
- // match (... ) {
1335
+ // Lastly we create an expression which branches on all discriminants being equal, e.g.
1336
+ // if __self_vi == _arg_1_vi {
1337
+ // match (self, other ) {
1361
1338
// (Variant1, Variant1, ...) => Body1
1362
1339
// (Variant2, Variant2, ...) => Body2,
1363
1340
// ...
@@ -1376,12 +1353,6 @@ impl<'a> MethodDef<'a> {
1376
1353
// for the zero variant case.
1377
1354
BlockOrExpr ( vec ! [ ] , Some ( deriving:: call_unreachable ( cx, span) ) )
1378
1355
} else {
1379
- // Final wrinkle: the selflike_args are expressions that deref
1380
- // down to desired places, but we cannot actually deref
1381
- // them when they are fed as r-values into a tuple
1382
- // expression; here add a layer of borrowing, turning
1383
- // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1384
- selflike_args. map_in_place ( |selflike_arg| cx. expr_addr_of ( span, selflike_arg) ) ;
1385
1356
let match_arg = if selflike_args. len ( ) == 1 {
1386
1357
selflike_args. pop ( ) . unwrap ( )
1387
1358
} else {
@@ -1451,18 +1422,18 @@ impl<'a> TraitDef<'a> {
1451
1422
struct_path : ast:: Path ,
1452
1423
struct_def : & ' a VariantData ,
1453
1424
prefixes : & [ String ] ,
1454
- use_temporaries : bool ,
1425
+ use_ref_pat : bool ,
1455
1426
) -> Vec < P < ast:: Pat > > {
1456
1427
prefixes
1457
1428
. iter ( )
1458
1429
. map ( |prefix| {
1459
1430
let pieces_iter =
1460
1431
struct_def. fields ( ) . iter ( ) . enumerate ( ) . map ( |( i, struct_field) | {
1461
1432
let sp = struct_field. span . with_ctxt ( self . span . ctxt ( ) ) ;
1462
- let binding_mode = if use_temporaries {
1463
- ast:: BindingMode :: ByValue ( ast:: Mutability :: Not )
1464
- } else {
1433
+ let binding_mode = if use_ref_pat {
1465
1434
ast:: BindingMode :: ByRef ( ast:: Mutability :: Not )
1435
+ } else {
1436
+ ast:: BindingMode :: ByValue ( ast:: Mutability :: Not )
1466
1437
} ;
1467
1438
let ident = self . mk_pattern_ident ( prefix, i) ;
1468
1439
let path = ident. with_span_pos ( sp) ;
@@ -1541,15 +1512,15 @@ impl<'a> TraitDef<'a> {
1541
1512
cx : & mut ExtCtxt < ' _ > ,
1542
1513
struct_def : & ' a VariantData ,
1543
1514
prefixes : & [ String ] ,
1544
- use_temporaries : bool ,
1515
+ no_deref : bool ,
1545
1516
) -> Vec < FieldInfo > {
1546
1517
self . create_fields ( struct_def, |i, _struct_field, sp| {
1547
1518
prefixes
1548
1519
. iter ( )
1549
1520
. map ( |prefix| {
1550
1521
let ident = self . mk_pattern_ident ( prefix, i) ;
1551
1522
let expr = cx. expr_path ( cx. path_ident ( sp, ident) ) ;
1552
- if use_temporaries { expr } else { cx. expr_deref ( sp, expr) }
1523
+ if no_deref { expr } else { cx. expr_deref ( sp, expr) }
1553
1524
} )
1554
1525
. collect ( )
1555
1526
} )
@@ -1564,11 +1535,7 @@ impl<'a> TraitDef<'a> {
1564
1535
self . create_fields ( struct_def, |i, struct_field, sp| {
1565
1536
selflike_args
1566
1537
. iter ( )
1567
- . map ( |mut selflike_arg| {
1568
- // We don't the need the deref, if there is one.
1569
- if let ast:: ExprKind :: Unary ( ast:: UnOp :: Deref , inner) = & selflike_arg. kind {
1570
- selflike_arg = inner;
1571
- }
1538
+ . map ( |selflike_arg| {
1572
1539
// Note: we must use `struct_field.span` rather than `span` in the
1573
1540
// `unwrap_or_else` case otherwise the hygiene is wrong and we get
1574
1541
// "field `0` of struct `Point` is private" errors on tuple
0 commit comments