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

`})

`