Use &{self.x}
for packed Copy
structs. · rust-lang/rust@6d114fb (original) (raw)
`@@ -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],
`
1538
1544
`struct_def: &'a VariantData,
`
``
1545
`+
copy: bool,
`
1539
1546
`) -> Vec {
`
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
`})
`