Skip to content

Commit 6d114fb

Browse files
committed
Use &{self.x} for packed Copy structs.
Because it's more concise than the `let` form.
1 parent 10144e2 commit 6d114fb

File tree

3 files changed

+40
-37
lines changed

3 files changed

+40
-37
lines changed

compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ pub fn expand_deriving_partial_eq(
3838
// stripping `&` or adding `*`. This isn't necessary for
3939
// type checking, but it results in much better error
4040
// messages if something goes wrong.
41+
//
42+
// For `packed` structs that impl `Copy`, we'll end up with
43+
// an expr like `{ self.0 } != { other.0 }`. It would be
44+
// nice to strip those blocks, giving `self.0 != other.0`,
45+
// but then the "`#[derive]` can't be used on a
46+
// `#[repr(packed)]` struct that does not derive Copy"
47+
// error is issued erroneously by the MIR builder.
4148
let convert = |expr: &P<Expr>| {
4249
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
4350
&expr.kind

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

+27-17
Original file line numberDiff line numberDiff line change
@@ -1014,19 +1014,20 @@ impl<'a> MethodDef<'a> {
10141014
/// ```
10151015
/// But if the struct is `repr(packed)`, we can't use something like
10161016
/// `&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:
10191019
/// ```
10201020
/// # struct A { x: u8, y: u8 }
10211021
/// impl PartialEq for A {
10221022
/// 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 }
10261024
/// }
10271025
/// }
10281026
/// ```
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`:
10301031
/// ```
10311032
/// # struct A { x: u8, y: u8 }
10321033
/// impl PartialEq for A {
@@ -1065,9 +1066,14 @@ impl<'a> MethodDef<'a> {
10651066

10661067
if !is_packed {
10671068
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);
10691074
mk_body(cx, selflike_fields)
10701075
} else {
1076+
// Neither packed nor copy. Need to use ref patterns.
10711077
let prefixes: Vec<_> =
10721078
(0..selflike_args.len()).map(|i| format!("__self_{}", i)).collect();
10731079
let addr_of = always_copy;
@@ -1536,6 +1542,7 @@ impl<'a> TraitDef<'a> {
15361542
cx: &mut ExtCtxt<'_>,
15371543
selflike_args: &[P<Expr>],
15381544
struct_def: &'a VariantData,
1545+
copy: bool,
15391546
) -> Vec<FieldInfo> {
15401547
self.create_fields(struct_def, |i, struct_field, sp| {
15411548
selflike_args
@@ -1545,18 +1552,21 @@ impl<'a> TraitDef<'a> {
15451552
// `unwrap_or_else` case otherwise the hygiene is wrong and we get
15461553
// "field `0` of struct `Point` is private" errors on tuple
15471554
// structs.
1548-
cx.expr_addr_of(
1555+
let mut field_expr = cx.expr(
15491556
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+
}),
15581562
),
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)
15601570
})
15611571
.collect()
15621572
})

src/test/ui/deriving/deriving-all-codegen.stdout

+6-20
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,8 @@ impl ::core::marker::Copy for PackedCopy { }
441441
#[allow(unused_qualifications)]
442442
impl ::core::fmt::Debug for PackedCopy {
443443
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
444-
let Self(__self_0_0) = *self;
445444
::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedCopy",
446-
&&__self_0_0)
445+
&&{ self.0 })
447446
}
448447
}
449448
#[automatically_derived]
@@ -458,26 +457,17 @@ impl ::core::default::Default for PackedCopy {
458457
#[allow(unused_qualifications)]
459458
impl ::core::hash::Hash for PackedCopy {
460459
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
461-
let Self(__self_0_0) = *self;
462-
::core::hash::Hash::hash(&__self_0_0, state)
460+
::core::hash::Hash::hash(&{ self.0 }, state)
463461
}
464462
}
465463
impl ::core::marker::StructuralPartialEq for PackedCopy {}
466464
#[automatically_derived]
467465
#[allow(unused_qualifications)]
468466
impl ::core::cmp::PartialEq for PackedCopy {
469467
#[inline]
470-
fn eq(&self, other: &PackedCopy) -> bool {
471-
let Self(__self_0_0) = *self;
472-
let Self(__self_1_0) = *other;
473-
__self_0_0 == __self_1_0
474-
}
468+
fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } }
475469
#[inline]
476-
fn ne(&self, other: &PackedCopy) -> bool {
477-
let Self(__self_0_0) = *self;
478-
let Self(__self_1_0) = *other;
479-
__self_0_0 != __self_1_0
480-
}
470+
fn ne(&self, other: &PackedCopy) -> bool { { self.0 } != { other.0 } }
481471
}
482472
impl ::core::marker::StructuralEq for PackedCopy {}
483473
#[automatically_derived]
@@ -496,19 +486,15 @@ impl ::core::cmp::PartialOrd for PackedCopy {
496486
#[inline]
497487
fn partial_cmp(&self, other: &PackedCopy)
498488
-> ::core::option::Option<::core::cmp::Ordering> {
499-
let Self(__self_0_0) = *self;
500-
let Self(__self_1_0) = *other;
501-
::core::cmp::PartialOrd::partial_cmp(&__self_0_0, &__self_1_0)
489+
::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
502490
}
503491
}
504492
#[automatically_derived]
505493
#[allow(unused_qualifications)]
506494
impl ::core::cmp::Ord for PackedCopy {
507495
#[inline]
508496
fn cmp(&self, other: &PackedCopy) -> ::core::cmp::Ordering {
509-
let Self(__self_0_0) = *self;
510-
let Self(__self_1_0) = *other;
511-
::core::cmp::Ord::cmp(&__self_0_0, &__self_1_0)
497+
::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 })
512498
}
513499
}
514500

0 commit comments

Comments
 (0)