]> git.lizzy.rs Git - rust.git/commitdiff
Fix syntax in `-Zunpretty-expanded` output for derived `PartialEq`.
authorNicholas Nethercote <n.nethercote@gmail.com>
Mon, 30 Jan 2023 05:29:52 +0000 (16:29 +1100)
committerNicholas Nethercote <n.nethercote@gmail.com>
Wed, 1 Feb 2023 04:14:05 +0000 (15:14 +1100)
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 })
```

compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
compiler/rustc_expand/src/build.rs
tests/ui/deriving/deriving-all-codegen.stdout

index 88d454fbc11230f5ad04f55269112bd8789dc1d9..bad47db0de1d4e16103d6724d786eb479d480ab7 100644 (file)
@@ -29,16 +29,30 @@ fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOr
                         cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
                     };
 
-                    // We received `&T` arguments. Convert them to `T` by
-                    // stripping `&` or adding `*`. This isn't necessary for
-                    // type checking, but it results in much better error
-                    // messages if something goes wrong.
+                    // We received arguments of type `&T`. Convert them to type `T` by stripping
+                    // any leading `&` or adding `*`. This isn't necessary for type checking, but
+                    // it results in better error messages if something goes wrong.
+                    //
+                    // Note: for arguments that look like `&{ x }`, which occur with packed
+                    // structs, this would cause expressions like `{ self.x } == { other.x }`,
+                    // which isn't valid Rust syntax. This wouldn't break compilation because these
+                    // AST nodes are constructed within the compiler. But it would mean that code
+                    // printed by `-Zunpretty=expanded` (or `cargo expand`) would have invalid
+                    // syntax, which would be suboptimal. So we wrap these in parens, giving
+                    // `({ self.x }) == ({ other.x })`, which is valid syntax.
                     let convert = |expr: &P<Expr>| {
                         if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
                             &expr.kind
                         {
-                            inner.clone()
+                            if let ExprKind::Block(..) = &inner.kind {
+                                // `&{ x }` form: remove the `&`, add parens.
+                                cx.expr_paren(field.span, inner.clone())
+                            } else {
+                                // `&x` form: remove the `&`.
+                                inner.clone()
+                            }
                         } else {
+                            // No leading `&`: add a leading `*`.
                             cx.expr_deref(field.span, expr.clone())
                         }
                     };
index 9b16e79d49a9e951042e6978f33e92d712195430..6cd56852f9d686942633ce3b258358c310d56469 100644 (file)
@@ -272,6 +272,10 @@ pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
     }
 
+    pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+        self.expr(sp, ast::ExprKind::Paren(e))
+    }
+
     pub fn expr_call(
         &self,
         span: Span,
index b4874cef134f77df98fd94427bf3a878021c54bf..8e238a509d2fd5193ac460241b91a1a763e4688c 100644 (file)
@@ -209,7 +209,7 @@ impl ::core::marker::StructuralPartialEq for PackedPoint { }
 impl ::core::cmp::PartialEq for PackedPoint {
     #[inline]
     fn eq(&self, other: &PackedPoint) -> bool {
-        { self.x } == { other.x } && { self.y } == { other.y }
+        ({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
     }
 }
 #[automatically_derived]
@@ -718,8 +718,8 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
     ::core::marker::Copy {
     #[inline]
     fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
-        { self.0 } == { other.0 } && { self.1 } == { other.1 } &&
-            { self.2 } == { other.2 }
+        ({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
+            ({ self.2 }) == ({ other.2 })
     }
 }
 #[automatically_derived]