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

`})

`