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``
This commit is contained in:
commit
150b9d753b
@ -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)`");
|
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
|
||||||
};
|
};
|
||||||
|
|
||||||
// We received `&T` arguments. Convert them to `T` by
|
// We received arguments of type `&T`. Convert them to type `T` by stripping
|
||||||
// stripping `&` or adding `*`. This isn't necessary for
|
// any leading `&` or adding `*`. This isn't necessary for type checking, but
|
||||||
// type checking, but it results in much better error
|
// it results in better error messages if something goes wrong.
|
||||||
// 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>| {
|
let convert = |expr: &P<Expr>| {
|
||||||
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
|
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
|
||||||
&expr.kind
|
&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 {
|
} else {
|
||||||
|
// No leading `&`: add a leading `*`.
|
||||||
cx.expr_deref(field.span, expr.clone())
|
cx.expr_deref(field.span, expr.clone())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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))
|
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(
|
pub fn expr_call(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -209,7 +209,7 @@ impl ::core::marker::StructuralPartialEq for PackedPoint { }
|
|||||||
impl ::core::cmp::PartialEq for PackedPoint {
|
impl ::core::cmp::PartialEq for PackedPoint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &PackedPoint) -> bool {
|
fn eq(&self, other: &PackedPoint) -> bool {
|
||||||
{ self.x } == { other.x } && { self.y } == { other.y }
|
({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
@ -718,8 +718,8 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
|
|||||||
::core::marker::Copy {
|
::core::marker::Copy {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
|
fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
|
||||||
{ self.0 } == { other.0 } && { self.1 } == { other.1 } &&
|
({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
|
||||||
{ self.2 } == { other.2 }
|
({ self.2 }) == ({ other.2 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
Loading…
Reference in New Issue
Block a user