Use &{self.x}
for packed Copy
structs. · rust-lang/rust@1cb1d63 (original) (raw)
`@@ -1013,20 +1013,25 @@ impl<'a> MethodDef<'a> {
`
1013
1013
`/// }
`
1014
1014
```` /// ```
`1015`
`1015`
`` /// But if the struct is `repr(packed)`, we can't use something like
``
`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`:
``
``
`1016`
`` +
/// `&self.x` because that might cause an unaligned ref. So for any trait
``
``
`1017`
`` +
/// method that takes a reference, if the struct impls `Copy` then we use a
``
``
`1018`
`+
/// 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
`` +
/// // Desugars to { self.x }.eq(&{ other.y }) && ...
``
``
1024
`+
/// { self.x } == { other.y } && { self.y } == { other.y }
`
``
1025
`+
/// }
`
``
1026
`+
/// }
`
``
1027
`+
/// impl Hash for A {
`
``
1028
`+
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
`
``
1029
`+
/// ::core::hash::Hash::hash(&{ self.x }, state);
`
``
1030
`+
/// ::core::hash::Hash::hash(&{ self.y }, state)
`
1026
1031
`/// }
`
1027
1032
`/// }
`
1028
1033
```` /// ```
`1029`
``
`` -
/// If it doesn't impl `Copy`:
``
``
`1034`
`` +
/// If the struct doesn't impl `Copy`, we use let-destructuring with `ref`:
``
`1030`
`1035`
```` /// ```
1031
1036
`/// # struct A { x: u8, y: u8 }
`
1032
1037
`/// impl PartialEq for A {
`
`@@ -1038,7 +1043,7 @@ impl<'a> MethodDef<'a> {
`
1038
1043
`/// }
`
1039
1044
```` /// ```
````
1040
1045
`/// This latter case only works if the fields match the alignment required
`
1041
``
`` -
/// by the packed(N)
attribute.
``
``
1046
`` +
/// by the packed(N)
attribute. (We'll get errors later on if not.)
``
1042
1047
`fn expand_struct_method_body<'b>(
`
1043
1048
`&self,
`
1044
1049
`cx: &mut ExtCtxt<'_>,
`
`@@ -1065,9 +1070,14 @@ impl<'a> MethodDef<'a> {
`
1065
1070
``
1066
1071
`if !is_packed {
`
1067
1072
`let selflike_fields =
`
1068
``
`-
trait_.create_struct_field_access_fields(cx, selflike_args, struct_def);
`
``
1073
`+
trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, false);
`
``
1074
`+
mk_body(cx, selflike_fields)
`
``
1075
`+
} else if always_copy {
`
``
1076
`+
let selflike_fields =
`
``
1077
`+
trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, true);
`
1069
1078
`mk_body(cx, selflike_fields)
`
1070
1079
`} else {
`
``
1080
`+
// Neither packed nor copy. Need to use ref patterns.
`
1071
1081
`let prefixes: Vec<_> =
`
1072
1082
`(0..selflike_args.len()).map(|i| format!("_self{}", i)).collect();
`
1073
1083
`let addr_of = always_copy;
`
`@@ -1536,6 +1546,7 @@ impl<'a> TraitDef<'a> {
`
1536
1546
`cx: &mut ExtCtxt<'_>,
`
1537
1547
`selflike_args: &[P],
`
1538
1548
`struct_def: &'a VariantData,
`
``
1549
`+
copy: bool,
`
1539
1550
`) -> Vec {
`
1540
1551
`self.create_fields(struct_def, |i, struct_field, sp| {
`
1541
1552
` selflike_args
`
`@@ -1545,18 +1556,21 @@ impl<'a> TraitDef<'a> {
`
1545
1556
`` // unwrap_or_else
case otherwise the hygiene is wrong and we get
``
1546
1557
`` // "field 0
of struct Point
is private" errors on tuple
``
1547
1558
`// structs.
`
1548
``
`-
cx.expr_addr_of(
`
``
1559
`+
let mut field_expr = cx.expr(
`
1549
1560
` 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
``
`-
),
`
``
1561
`+
ast::ExprKind::Field(
`
``
1562
`+
selflike_arg.clone(),
`
``
1563
`+
struct_field.ident.unwrap_or_else(|| {
`
``
1564
`+
Ident::from_str_and_span(&i.to_string(), struct_field.span)
`
``
1565
`+
}),
`
1558
1566
`),
`
1559
``
`-
)
`
``
1567
`+
);
`
``
1568
`+
if copy {
`
``
1569
`+
field_expr = cx.expr_block(
`
``
1570
`+
cx.block(struct_field.span, vec![cx.stmt_expr(field_expr)]),
`
``
1571
`+
);
`
``
1572
`+
}
`
``
1573
`+
cx.expr_addr_of(sp, field_expr)
`
1560
1574
`})
`
1561
1575
`.collect()
`
1562
1576
`})
`