Skip to content

Commit cb93c24

Browse files
committed
Auto merge of #124157 - wutchzone:partial_eq, r=estebank
Do not add leading asterisk in the `PartialEq` I think we should address this issue, however I am not exactly sure, if this is the right way to do it. It is related to the #123056. Imagine the simplified code: ```rust trait MyTrait {} impl PartialEq for dyn MyTrait { fn eq(&self, _other: &Self) -> bool { true } } #[derive(PartialEq)] enum Bar { Foo(Box<dyn MyTrait>), } ``` On the nightly compiler, the `derive` produces invalid code with the weird error message: ``` error[E0507]: cannot move out of `*__arg1_0` which is behind a shared reference --> src/main.rs:11:9 | 9 | #[derive(PartialEq)] | --------- in this derive macro expansion 10 | enum Things { 11 | Foo(Box<dyn MyTrait>), | ^^^^^^^^^^^^^^^^ move occurs because `*__arg1_0` has type `Box<dyn MyTrait>`, which does not implement the `Copy` trait | = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) ``` It may be related to the perfect derive problem, although requiring the _type_ to be `Copy` seems unfortunate because it is not necessary. Besides, we are adding the extra dereference only for the diagnostics?
2 parents 5f8c17d + c2a0ef6 commit cb93c24

File tree

7 files changed

+54
-17
lines changed

7 files changed

+54
-17
lines changed

Diff for: compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) fn expand_deriving_partial_eq(
3131
};
3232

3333
// We received arguments of type `&T`. Convert them to type `T` by stripping
34-
// any leading `&` or adding `*`. This isn't necessary for type checking, but
34+
// any leading `&`. This isn't necessary for type checking, but
3535
// it results in better error messages if something goes wrong.
3636
//
3737
// Note: for arguments that look like `&{ x }`, which occur with packed
@@ -53,8 +53,7 @@ pub(crate) fn expand_deriving_partial_eq(
5353
inner.clone()
5454
}
5555
} else {
56-
// No leading `&`: add a leading `*`.
57-
cx.expr_deref(field.span, expr.clone())
56+
expr.clone()
5857
}
5958
};
6059
cx.expr_binary(

Diff for: compiler/rustc_builtin_macros/src/deriving/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fn assert_ty_bounds(
123123
span: Span,
124124
assert_path: &[Symbol],
125125
) {
126-
// Deny anonymous structs or unions to avoid wierd errors.
126+
// Deny anonymous structs or unions to avoid weird errors.
127127
assert!(!ty.kind.is_anon_adt(), "Anonymous structs or unions cannot be type parameters");
128128
// Generate statement `let _: assert_path<ty>;`.
129129
let span = cx.with_def_site_ctxt(span);

Diff for: compiler/rustc_builtin_macros/src/format.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ fn make_format_args(
315315

316316
let mut used = vec![false; args.explicit_args().len()];
317317
let mut invalid_refs = Vec::new();
318-
let mut numeric_refences_to_named_arg = Vec::new();
318+
let mut numeric_references_to_named_arg = Vec::new();
319319

320320
enum ArgRef<'a> {
321321
Index(usize),
@@ -336,7 +336,7 @@ fn make_format_args(
336336
used[index] = true;
337337
if arg.kind.ident().is_some() {
338338
// This was a named argument, but it was used as a positional argument.
339-
numeric_refences_to_named_arg.push((index, span, used_as));
339+
numeric_references_to_named_arg.push((index, span, used_as));
340340
}
341341
Ok(index)
342342
} else {
@@ -544,7 +544,7 @@ fn make_format_args(
544544
// Only check for unused named argument names if there are no other errors to avoid causing
545545
// too much noise in output errors, such as when a named argument is entirely unused.
546546
if invalid_refs.is_empty() && !has_unused && !unnamed_arg_after_named_arg {
547-
for &(index, span, used_as) in &numeric_refences_to_named_arg {
547+
for &(index, span, used_as) in &numeric_references_to_named_arg {
548548
let (position_sp_to_replace, position_sp_for_msg) = match used_as {
549549
Placeholder(pspan) => (span, pspan),
550550
Precision => {

Diff for: tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0369]: binary operation `==` cannot be applied to type `Error`
1+
error[E0369]: binary operation `==` cannot be applied to type `&Error`
22
--> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
33
|
44
LL | #[derive(PartialEq)]

Diff for: tests/ui/derives/derives-span-PartialEq-enum.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0369]: binary operation `==` cannot be applied to type `Error`
1+
error[E0369]: binary operation `==` cannot be applied to type `&Error`
22
--> $DIR/derives-span-PartialEq-enum.rs:9:6
33
|
44
LL | #[derive(PartialEq)]

Diff for: tests/ui/deriving/deriving-all-codegen.rs

+14
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,20 @@ enum EnumGeneric<T, U> {
156156
Two(U),
157157
}
158158

159+
// An enum that has variant, which does't implement `Copy`.
160+
#[derive(PartialEq)]
161+
enum NonCopyEnum {
162+
// The `dyn NonCopyTrait` implements `PartialEq`, but it doesn't require `Copy`.
163+
// So we cannot generate `PartialEq` with dereference.
164+
NonCopyField(Box<dyn NonCopyTrait>),
165+
}
166+
trait NonCopyTrait {}
167+
impl PartialEq for dyn NonCopyTrait {
168+
fn eq(&self, _other: &Self) -> bool {
169+
true
170+
}
171+
}
172+
159173
// A union. Most builtin traits are not derivable for unions.
160174
#[derive(Clone, Copy)]
161175
pub union Union {

Diff for: tests/ui/deriving/deriving-all-codegen.stdout

+32-8
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ impl ::core::cmp::PartialEq for Enum1 {
876876
fn eq(&self, other: &Enum1) -> bool {
877877
match (self, other) {
878878
(Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) =>
879-
*__self_0 == *__arg1_0,
879+
__self_0 == __arg1_0,
880880
}
881881
}
882882
}
@@ -1119,10 +1119,10 @@ impl ::core::cmp::PartialEq for Mixed {
11191119
__self_discr == __arg1_discr &&
11201120
match (self, other) {
11211121
(Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
1122-
*__self_0 == *__arg1_0,
1122+
__self_0 == __arg1_0,
11231123
(Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
11241124
d1: __arg1_0, d2: __arg1_1 }) =>
1125-
*__self_0 == *__arg1_0 && *__self_1 == *__arg1_1,
1125+
__self_0 == __arg1_0 && __self_1 == __arg1_1,
11261126
_ => true,
11271127
}
11281128
}
@@ -1245,11 +1245,11 @@ impl ::core::cmp::PartialEq for Fielded {
12451245
__self_discr == __arg1_discr &&
12461246
match (self, other) {
12471247
(Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
1248-
*__self_0 == *__arg1_0,
1248+
__self_0 == __arg1_0,
12491249
(Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
1250-
*__self_0 == *__arg1_0,
1250+
__self_0 == __arg1_0,
12511251
(Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
1252-
*__self_0 == *__arg1_0,
1252+
__self_0 == __arg1_0,
12531253
_ => unsafe { ::core::intrinsics::unreachable() }
12541254
}
12551255
}
@@ -1368,9 +1368,9 @@ impl<T: ::core::cmp::PartialEq, U: ::core::cmp::PartialEq>
13681368
__self_discr == __arg1_discr &&
13691369
match (self, other) {
13701370
(EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) =>
1371-
*__self_0 == *__arg1_0,
1371+
__self_0 == __arg1_0,
13721372
(EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) =>
1373-
*__self_0 == *__arg1_0,
1373+
__self_0 == __arg1_0,
13741374
_ => unsafe { ::core::intrinsics::unreachable() }
13751375
}
13761376
}
@@ -1426,6 +1426,30 @@ impl<T: ::core::cmp::Ord, U: ::core::cmp::Ord> ::core::cmp::Ord for
14261426
}
14271427
}
14281428

1429+
// An enum that has variant, which does't implement `Copy`.
1430+
enum NonCopyEnum {
1431+
1432+
// The `dyn NonCopyTrait` implements `PartialEq`, but it doesn't require `Copy`.
1433+
// So we cannot generate `PartialEq` with dereference.
1434+
NonCopyField(Box<dyn NonCopyTrait>),
1435+
}
1436+
#[automatically_derived]
1437+
impl ::core::marker::StructuralPartialEq for NonCopyEnum { }
1438+
#[automatically_derived]
1439+
impl ::core::cmp::PartialEq for NonCopyEnum {
1440+
#[inline]
1441+
fn eq(&self, other: &NonCopyEnum) -> bool {
1442+
match (self, other) {
1443+
(NonCopyEnum::NonCopyField(__self_0),
1444+
NonCopyEnum::NonCopyField(__arg1_0)) => __self_0 == __arg1_0,
1445+
}
1446+
}
1447+
}
1448+
trait NonCopyTrait {}
1449+
impl PartialEq for dyn NonCopyTrait {
1450+
fn eq(&self, _other: &Self) -> bool { true }
1451+
}
1452+
14291453
// A union. Most builtin traits are not derivable for unions.
14301454
pub union Union {
14311455
pub b: bool,

0 commit comments

Comments
 (0)