Skip to content

Commit 150b9d7

Browse files
authored
Rollup merge of #107488 - nnethercote:fix-PartialEq-syntax, r=RalfJung
Fix syntax in `-Zunpretty-expanded` output for derived `PartialEq`. If you do `derive(PartialEq)` on a packed struct, the output shown by `-Zunpretty=expanded` includes expressions like this: ``` { self.x } == { other.x } ``` This is invalid syntax. This doesn't break compilation, because the AST nodes are constructed within the compiler. But it does mean anyone using `-Zunpretty=expanded` output as a guide for hand-written impls could get a nasty surprise. This commit fixes things by instead using this form: ``` ({ self.x }) == ({ other.x }) ``` r? ``@RalfJung``
2 parents f838fa8 + 75e87d1 commit 150b9d7

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

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

+19-5
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,30 @@ pub fn expand_deriving_partial_eq(
2929
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
3030
};
3131

32-
// We received `&T` arguments. Convert them to `T` by
33-
// stripping `&` or adding `*`. This isn't necessary for
34-
// type checking, but it results in much better error
35-
// messages if something goes wrong.
32+
// We received arguments of type `&T`. Convert them to type `T` by stripping
33+
// any leading `&` or adding `*`. This isn't necessary for type checking, but
34+
// it results in better error messages if something goes wrong.
35+
//
36+
// Note: for arguments that look like `&{ x }`, which occur with packed
37+
// structs, this would cause expressions like `{ self.x } == { other.x }`,
38+
// which isn't valid Rust syntax. This wouldn't break compilation because these
39+
// AST nodes are constructed within the compiler. But it would mean that code
40+
// printed by `-Zunpretty=expanded` (or `cargo expand`) would have invalid
41+
// syntax, which would be suboptimal. So we wrap these in parens, giving
42+
// `({ self.x }) == ({ other.x })`, which is valid syntax.
3643
let convert = |expr: &P<Expr>| {
3744
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
3845
&expr.kind
3946
{
40-
inner.clone()
47+
if let ExprKind::Block(..) = &inner.kind {
48+
// `&{ x }` form: remove the `&`, add parens.
49+
cx.expr_paren(field.span, inner.clone())
50+
} else {
51+
// `&x` form: remove the `&`.
52+
inner.clone()
53+
}
4154
} else {
55+
// No leading `&`: add a leading `*`.
4256
cx.expr_deref(field.span, expr.clone())
4357
}
4458
};

compiler/rustc_expand/src/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ impl<'a> ExtCtxt<'a> {
272272
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
273273
}
274274

275+
pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
276+
self.expr(sp, ast::ExprKind::Paren(e))
277+
}
278+
275279
pub fn expr_call(
276280
&self,
277281
span: Span,

tests/ui/deriving/deriving-all-codegen.stdout

+3-3
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ impl ::core::marker::StructuralPartialEq for PackedPoint { }
209209
impl ::core::cmp::PartialEq for PackedPoint {
210210
#[inline]
211211
fn eq(&self, other: &PackedPoint) -> bool {
212-
{ self.x } == { other.x } && { self.y } == { other.y }
212+
({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
213213
}
214214
}
215215
#[automatically_derived]
@@ -718,8 +718,8 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
718718
::core::marker::Copy {
719719
#[inline]
720720
fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
721-
{ self.0 } == { other.0 } && { self.1 } == { other.1 } &&
722-
{ self.2 } == { other.2 }
721+
({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
722+
({ self.2 }) == ({ other.2 })
723723
}
724724
}
725725
#[automatically_derived]

0 commit comments

Comments
 (0)