| Age | Commit message (Collapse) | Author | Lines |
|
|
|
available
|
|
|
|
The current approach to field accesses in derived code:
- Normal case: `&self.0`
- In a packed struct that derives `Copy`: `&{self.0}`
- In a packed struct that doesn't derive `Copy`: `let Self(ref x) = *self`
The `let` pattern used in the third case is equivalent to the simpler
field access in the first case. This commit changes the third case to
use a field access.
The commit also combines two boolean arguments (`is_packed` and
`always_copy`) into a single field (`copy_fields`) earlier, to save
passing both around.
|
|
Fix `TyKind::is_simple_path`
Fixes #103157.
r? `@spastorino`
|
|
PR #98758 introduced code to avoid redundant assertions in derived code
like this:
```
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u32>;
```
But the predicate `is_simple_path` introduced as part of this failed to
account for generic arguments. Therefore the deriving code erroneously
considers types like `Option<bool>` and `Option<f32>` to be the same.
This commit fixes `is_simple_path`.
Fixes #103157.
|
|
To include some `Option<>` fields of different types in a single enum.
The test output is currently buggy, but the next commit will fix that.
|
|
Mark derived StructuralEq as automatically derived.
Fixes https://github.com/rust-lang/rust/issues/69952
Drive-by: use correct spans for generic params.
|
|
|
|
|
|
danielhenrymantilla:no-bounds-for-default-annotated-derive, r=joshtriplett
Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds
That is, given something like:
```rs
// #[default] on a generic enum does not add `Default` bounds to the type params.
#[derive(Default)]
enum MyOption<T> {
#[default]
None,
Some(T),
}
```
then `MyOption<T> : Default`_as currently implemented_ only holds when `T : Default`, as reported by ```@5225225``` [over Zulip](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/.23.5Bderive.28Default.29.5D.20for.20enums.20with.20fields).
This is contrary to [what the accepted RFC proposes](https://rust-lang.github.io/rfcs/3107-derive-default-enum.html#generated-bounds) (_i.e._, that `T` be allowed not to be itself `Default`), and indeed seems to be a rather unnecessary limitation.
|
|
|
|
|
|
Don't derive `PartialEq::ne`.
Currently we skip deriving `PartialEq::ne` for C-like (fieldless) enums
and empty structs, thus reyling on the default `ne`. This behaviour is
unnecessarily conservative, because the `PartialEq` docs say this:
> Implementations must ensure that eq and ne are consistent with each other:
>
> `a != b` if and only if `!(a == b)` (ensured by the default
> implementation).
This means that the default implementation (`!(a == b)`) is always good
enough. So this commit changes things such that `ne` is never derived.
The motivation for this change is that not deriving `ne` reduces compile
times and binary sizes.
Observable behaviour may change if a user has defined a type `A` with an
inconsistent `PartialEq` and then defines a type `B` that contains an
`A` and also derives `PartialEq`. Such code is already buggy and
preserving bug-for-bug compatibility isn't necessary.
Two side-effects of the change:
- There is only one error message produced for types where `PartialEq`
cannot be derived, instead of two.
- For coverage reports, some warnings about generated `ne` methods not
being executed have disappeared.
Both side-effects seem fine, and possibly preferable.
|
|
|
|
Currently we skip deriving `PartialEq::ne` for C-like (fieldless) enums
and empty structs, thus reyling on the default `ne`. This behaviour is
unnecessarily conservative, because the `PartialEq` docs say this:
> Implementations must ensure that eq and ne are consistent with each other:
>
> `a != b` if and only if `!(a == b)` (ensured by the default
> implementation).
This means that the default implementation (`!(a == b)`) is always good
enough. So this commit changes things such that `ne` is never derived.
The motivation for this change is that not deriving `ne` reduces compile
times and binary sizes.
Observable behaviour may change if a user has defined a type `A` with an
inconsistent `PartialEq` and then defines a type `B` that contains an
`A` and also derives `PartialEq`. Such code is already buggy and
preserving bug-for-bug compatibility isn't necessary.
Two side-effects of the change:
- There is only one error message produced for types where `PartialEq`
cannot be derived, instead of two.
- For coverage reports, some warnings about generated `ne` methods not
being executed have disappeared.
Both side-effects seem fine, and possibly preferable.
|
|
|
|
Because it's more concise than the `let` form.
|
|
Currently, for the enums and comparison traits we always check the tag
for equality before doing anything else. This is a bit clumsy. This
commit changes things so that the tags are handled very much like a
zeroth field in the enum.
For `eq`/ne` this makes the code slightly cleaner.
For `partial_cmp` and `cmp` it's a more notable change: in the case
where the tags aren't equal, instead of having a tag equality check
followed by a tag comparison, it just does a single tag comparison.
The commit also improves how `Hash` works for enums: instead of having
duplicated code to hash the tag for every arm within the match, we do
it just once before the match.
All this required replacing the `EnumNonMatchingCollapsed` value with a
new `EnumTag` value.
For fieldless enums the new code is particularly improved. All the code
now produced is close to optimal, being very similar to what you'd write
by hand.
|
|
|
|
Use `tag` in names of things referring to tags, instead of the
mysterious `vi`.
Also change `arg_N` in output to `argN`, which has the same length as
`self` and so results in nicer vertical alignments.
|
|
By producing `&T` expressions for fields instead of `T`. This matches
what the existing comments (e.g. on `FieldInfo`) claim is happening, and
it's also what most of the trait-specific code needs.
The exception is `PartialEq`, which needs `T` expressions for lots of
special case error messaging to work. So we now convert the `&T` back to
a `T` for `PartialEq`.
|
|
E.g. improving code like this:
```
match &*self {
&Enum1::Single { x: ref __self_0 } => {
::core::hash::Hash::hash(&*__self_0, state)
}
}
```
to this:
```
match self {
Enum1::Single { x: __self_0 } => {
::core::hash::Hash::hash(&*__self_0, state)
}
}
```
by removing the `&*`, the `&`, and the `ref`.
I suspect the current generated code predates deref-coercion.
The commit also gets rid of `use_temporaries`, instead passing around
`always_copy`, which makes things a little clearer. And it fixes up some
comments.
|
|
Because the generated code is different to fieldless enum with multiple
variants.
|
|
Because the generatedd code is different to a `Copy` packed struct.
|
|
It's an interesting case, requiring the use of `&&` in `Debug::fmt`.
|
|
We currently do a match on the comparison of every field in a struct or
enum variant. But the last field has a degenerate match like this:
```
match ::core::cmp::Ord::cmp(&self.y, &other.y) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ordering::Equal,
cmp => cmp,
},
```
This commit changes it to this:
```
::core::cmp::Ord::cmp(&self.y, &other.y),
```
This is fairly straightforward thanks to the existing `cs_fold1`
function.
The commit also removes the `cs_fold` function which is no longer used.
(Note: there is some repetition now in `cs_cmp` and `cs_partial_cmp`. I
will remove that in a follow-up PR.)
|
|
|
|
It's common to see repeated assertions like this in derived `clone` and
`eq` methods:
```
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u32>;
```
This commit avoids them.
|
|
By not committing to either block form or expression form until
necessary, we can avoid lots of unnecessary blocks.
|
|
Because they are interesting cases with their own code generation paths.
|
|
Because `derive(Clone)` on unions triggers special behaviour.
|
|
All derive ops currently use match-destructuring to access fields. This
is reasonable for enums, but sub-optimal for structs. E.g.:
```
fn eq(&self, other: &Point) -> bool {
match *other {
Self { x: ref __self_1_0, y: ref __self_1_1 } =>
match *self {
Self { x: ref __self_0_0, y: ref __self_0_1 } =>
(*__self_0_0) == (*__self_1_0) &&
(*__self_0_1) == (*__self_1_1),
},
}
}
```
This commit changes derive ops on structs to use field access instead, e.g.:
```
fn eq(&self, other: &Point) -> bool {
self.x == other.x && self.y == other.y
}
```
This is faster to compile, results in smaller binaries, and is simpler to
generate. Unfortunately, we have to keep the old pattern generating code around
for `repr(packed)` structs because something like `&self.x` (which doesn't show
up in `PartialEq` ops, but does show up in `Debug` and `Hash` ops) isn't
allowed. But this commit at least changes those cases to use let-destructuring
instead of match-destructuring, e.g.:
```
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
{
let Self(ref __self_0_0) = *self;
{ ::core::hash::Hash::hash(&(*__self_0_0), state) }
}
}
```
There are some unnecessary blocks remaining in the generated code, but I
will fix them in a follow-up PR.
|
|
|
|
Currently the generated code for methods like `eq`, `ne`, and `partial_cmp`
includes stuff like this:
```
let __self_vi = ::core::intrinsics::discriminant_value(&*self);
let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
if true && __self_vi == __arg_1_vi {
...
}
```
This commit removes the unnecessary `true &&`, and makes the generating
code a little easier to read in the process. It also fixes some errors
in comments.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
where clause
|
|
|
|
|
|
|
|
|
|
|
|
compare mode chalk don't finish.
|
|
|