@@ -1014,19 +1014,20 @@ impl<'a> MethodDef<'a> {
1014
1014
/// ```
1015
1015
/// But if the struct is `repr(packed)`, we can't use something like
1016
1016
/// `&self.x` on a packed type (as required for e.g. `Debug` and `Hash`)
1017
- /// because that might cause an unaligned ref. So we use let-destructuring
1018
- /// instead. If the struct impls `Copy` :
1017
+ /// because that might cause an unaligned ref. If the struct impls `Copy`,
1018
+ /// we use a local block to force a copy :
1019
1019
/// ```
1020
1020
/// # struct A { x: u8, y: u8 }
1021
1021
/// impl PartialEq for A {
1022
1022
/// fn eq(&self, other: &A) -> bool {
1023
- /// let Self { x: __self_0_0, y: __self_0_1 } = *self;
1024
- /// let Self { x: __self_1_0, y: __self_1_1 } = *other;
1025
- /// __self_0_0 == __self_1_0 && __self_0_1 == __self_1_1
1023
+ /// { self.x } == { other.y } && { self.y } == { other.y }
1026
1024
/// }
1027
1025
/// }
1028
1026
/// ```
1029
- /// If it doesn't impl `Copy`:
1027
+ /// (The copy isn't necessary for `eq`, but it makes more sense for other
1028
+ /// functions that use e.g. `&{ self.x }`.)
1029
+ ///
1030
+ /// If it doesn't impl `Copy`, we use let-destructuring with `ref`:
1030
1031
/// ```
1031
1032
/// # struct A { x: u8, y: u8 }
1032
1033
/// impl PartialEq for A {
@@ -1065,9 +1066,14 @@ impl<'a> MethodDef<'a> {
1065
1066
1066
1067
if !is_packed {
1067
1068
let selflike_fields =
1068
- trait_. create_struct_field_access_fields ( cx, selflike_args, struct_def) ;
1069
+ trait_. create_struct_field_access_fields ( cx, selflike_args, struct_def, false ) ;
1070
+ mk_body ( cx, selflike_fields)
1071
+ } else if always_copy {
1072
+ let selflike_fields =
1073
+ trait_. create_struct_field_access_fields ( cx, selflike_args, struct_def, true ) ;
1069
1074
mk_body ( cx, selflike_fields)
1070
1075
} else {
1076
+ // Neither packed nor copy. Need to use ref patterns.
1071
1077
let prefixes: Vec < _ > =
1072
1078
( 0 ..selflike_args. len ( ) ) . map ( |i| format ! ( "__self_{}" , i) ) . collect ( ) ;
1073
1079
let addr_of = always_copy;
@@ -1536,6 +1542,7 @@ impl<'a> TraitDef<'a> {
1536
1542
cx : & mut ExtCtxt < ' _ > ,
1537
1543
selflike_args : & [ P < Expr > ] ,
1538
1544
struct_def : & ' a VariantData ,
1545
+ copy : bool ,
1539
1546
) -> Vec < FieldInfo > {
1540
1547
self . create_fields ( struct_def, |i, struct_field, sp| {
1541
1548
selflike_args
@@ -1545,18 +1552,21 @@ impl<'a> TraitDef<'a> {
1545
1552
// `unwrap_or_else` case otherwise the hygiene is wrong and we get
1546
1553
// "field `0` of struct `Point` is private" errors on tuple
1547
1554
// structs.
1548
- cx. expr_addr_of (
1555
+ let mut field_expr = cx. expr (
1549
1556
sp,
1550
- cx. expr (
1551
- sp,
1552
- ast:: ExprKind :: Field (
1553
- selflike_arg. clone ( ) ,
1554
- struct_field. ident . unwrap_or_else ( || {
1555
- Ident :: from_str_and_span ( & i. to_string ( ) , struct_field. span )
1556
- } ) ,
1557
- ) ,
1557
+ ast:: ExprKind :: Field (
1558
+ selflike_arg. clone ( ) ,
1559
+ struct_field. ident . unwrap_or_else ( || {
1560
+ Ident :: from_str_and_span ( & i. to_string ( ) , struct_field. span )
1561
+ } ) ,
1558
1562
) ,
1559
- )
1563
+ ) ;
1564
+ if copy {
1565
+ field_expr = cx. expr_block (
1566
+ cx. block ( struct_field. span , vec ! [ cx. stmt_expr( field_expr) ] ) ,
1567
+ ) ;
1568
+ }
1569
+ cx. expr_addr_of ( sp, field_expr)
1560
1570
} )
1561
1571
. collect ( )
1562
1572
} )
0 commit comments