1
Fork 0
Commit graph

87 commits

Author SHA1 Message Date
Matthias Krüger
aea4c0c1b8
Rollup merge of #104391 - nnethercote:deriving-cleanups, r=jackh726
Deriving cleanups

Fixing some minor problems `@RalfJung` found in #99046.

r? `@RalfJung`
2022-11-15 01:40:44 +01:00
Nicholas Nethercote
111db7d3a8 Remove TraitDef::generics.
Because it's always empty.
2022-11-14 15:59:41 +11:00
Nicholas Nethercote
96280b6a1d Remove addr_of argument from create_struct_pattern_fields.
Because it's always false.
2022-11-14 13:59:54 +11:00
Nicholas Nethercote
9985f4611b Clarify expand_struct_method_body.
Spotted by @RalfJung. This causes no behavioural changes.
2022-11-14 13:49:08 +11:00
Dylan DPC
4b0b89827d
Rollup merge of #102049 - fee1-dead-contrib:derive_const, r=oli-obk
Add the `#[derive_const]` attribute

Closes #102371. This is a minimal patchset for the attribute to work. There are no restrictions on what traits this attribute applies to.

r? `````@oli-obk`````
2022-11-12 12:02:50 +05:30
Michael Goulet
d3bd6beb97 Rename AssocItemKind::TyAlias to AssocItemKind::Type 2022-10-10 02:31:37 +00:00
bors
0152393048 Auto merge of #99324 - reez12g:issue-99144, r=jyn514
Enable doctests in compiler/ crates

Helps with https://github.com/rust-lang/rust/issues/99144
2022-10-06 03:01:57 +00:00
Matthias Krüger
df11395a55
Rollup merge of #101040 - 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.
2022-10-03 20:58:55 +02:00
reez12g
73775a96dc Fix docs in compiler/rustc_builtin_macros/src/deriving/generic/mod.rs 2022-09-29 16:49:21 +09:00
Deadbeef
a052f2cce1 Add the #[derive_const] attribute 2022-09-20 11:57:58 +00:00
Daniel Henry-Mantilla
cb86c38cdb Fix #[derive(Default)] on a generic #[default] enum adding unnecessary Default bounds 2022-09-05 13:49:37 +02:00
Cameron Steffen
02ba216e3c Refactor and re-use BindingAnnotation 2022-09-02 12:55:05 -05:00
bors
eac6c33bc6 Auto merge of #100869 - nnethercote:replace-ThinVec, r=spastorino
Replace `rustc_data_structures::thin_vec::ThinVec` with `thin_vec::ThinVec`

`rustc_data_structures::thin_vec::ThinVec` looks like this:
```
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
```
It's just a zero word if the vector is empty, but requires two
allocations if it is non-empty. So it's only usable in cases where the
vector is empty most of the time.

This commit removes it in favour of `thin_vec::ThinVec`, which is also
word-sized, but stores the length and capacity in the same allocation as
the elements. It's good in a wider variety of situation, e.g. in enum
variants where the vector is usually/always non-empty.

The commit also:
- Sorts some `Cargo.toml` dependency lists, to make additions easier.
- Sorts some `use` item lists, to make additions easier.
- Changes `clean_trait_ref_with_bindings` to take a
  `ThinVec<TypeBinding>` rather than a `&[TypeBinding]`, because this
  avoid some unnecessary allocations.

r? `@spastorino`
2022-09-01 08:01:06 +00:00
Nicholas Nethercote
b38106b6d8 Replace rustc_data_structures::thin_vec::ThinVec with thin_vec::ThinVec.
`rustc_data_structures::thin_vec::ThinVec` looks like this:
```
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
```
It's just a zero word if the vector is empty, but requires two
allocations if it is non-empty. So it's only usable in cases where the
vector is empty most of the time.

This commit removes it in favour of `thin_vec::ThinVec`, which is also
word-sized, but stores the length and capacity in the same allocation as
the elements. It's good in a wider variety of situation, e.g. in enum
variants where the vector is usually/always non-empty.

The commit also:
- Sorts some `Cargo.toml` dependency lists, to make additions easier.
- Sorts some `use` item lists, to make additions easier.
- Changes `clean_trait_ref_with_bindings` to take a
  `ThinVec<TypeBinding>` rather than a `&[TypeBinding]`, because this
  avoid some unnecessary allocations.
2022-08-29 15:42:13 +10:00
bors
ce36e88256 Auto merge of #100497 - kadiwa4:remove_clone_into_iter, r=cjgillot
Avoid cloning a collection only to iterate over it

`@rustbot` label: +C-cleanup
2022-08-28 18:31:08 +00:00
Nicholas Nethercote
619b8abaa6 Use AttrVec in more places.
In some places we use `Vec<Attribute>` and some places we use
`ThinVec<Attribute>` (a.k.a. `AttrVec`). This results in various points
where we have to convert between `Vec` and `ThinVec`.

This commit changes the places that use `Vec<Attribute>` to use
`AttrVec`. A lot of this is mechanical and boring, but there are
some interesting parts:
- It adds a few new methods to `ThinVec`.
- It implements `MapInPlace` for `ThinVec`, and introduces a macro to
  avoid the repetition of this trait for `Vec`, `SmallVec`, and
  `ThinVec`.

Overall, it makes the code a little nicer, and has little effect on
performance. But it is a precursor to removing
`rustc_data_structures::thin_vec::ThinVec` and replacing it with
`thin_vec::ThinVec`, which is implemented more efficiently.
2022-08-22 07:35:33 +10:00
bors
361c599fee Auto merge of #98655 - nnethercote:dont-derive-PartialEq-ne, r=dtolnay
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.
2022-08-18 10:11:11 +00:00
Nicholas Nethercote
6cd40d0e51 Remove attrs arg from typaram and mk_ty_param.
Because it's always empty.
2022-08-17 12:33:42 +10:00
Nicholas Nethercote
2c24958cfd Remove TraitDef::attributes.
Because it's always empty.
2022-08-17 12:29:02 +10:00
Nicholas Nethercote
3e04fed6fa Remove {ast,hir}::WhereEqPredicate::id.
These fields are unused.
2022-08-16 12:13:23 +10:00
KaDiWa
4eebcb9910
avoid cloning and then iterating 2022-08-13 16:16:52 +02:00
Nicholas Nethercote
232bd80130 Simplify rustc_ast::visit::Visitor::visit_poly_trait_ref.
It is passed an argument that is never used.
2022-08-11 11:10:01 +10:00
Nicholas Nethercote
d4a5b034b7 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.
2022-08-01 08:01:58 +10:00
Samrat Man Singh
8374ab6d65 Don't add attribute to allow unused-qualifications to derive impl's
Currently `#![forbid(unused_qualifications)]` is incompatible with all
derive's because we add `#[allow(unused_qualifications)]` in all
generated impl's.
2022-07-18 22:28:17 -04:00
Nicholas Nethercote
1cb1d63bd2 Use &{self.x} for packed Copy structs.
Because it's more concise than the `let` form.
2022-07-13 10:54:02 +10:00
Nicholas Nethercote
10144e29af Handle tags better.
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.
2022-07-11 16:58:32 +10:00
Nicholas Nethercote
4bcbd76bc9 Move the no-variants handling code earlier in expand_enum_method_body.
To avoid computing a bunch of stuff that it doesn't need.
2022-07-11 14:09:53 +10:00
Nicholas Nethercote
f1d9e2b50c Avoid some unnecessary blocks in derive output. 2022-07-11 14:09:37 +10:00
Nicholas Nethercote
56178d4259 Rename tag-related things.
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.
2022-07-11 14:09:17 +10:00
Nicholas Nethercote
96f09d73cd Remove unnecessary &* sigil pairs in derived code.
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`.
2022-07-11 14:07:33 +10:00
Nicholas Nethercote
277bc9641d Remove unnecessary sigils and refs in derived code.
E.g. improving code like this:
```
match &*self {
    &Enum1::Single { x: ref __self_0 } => {
        ::core:#️⃣:Hash::hash(&*__self_0, state)
    }
}
```
to this:
```
match self {
    Enum1::Single { x: __self_0 } => {
        ::core:#️⃣: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.
2022-07-11 14:04:42 +10:00
Nicholas Nethercote
f314ece275 Remove mutbl argument from create_struct_patterns.
It's always `ast::Mutability::Not`.
2022-07-11 07:30:27 +10:00
Nicholas Nethercote
0578697a63 Minor updates based on review comments. 2022-07-09 10:04:09 +10:00
Nicholas Nethercote
16a286b003 Simplify cs_fold.
`cs_fold` has four distinct cases, covered by three different function
arguments:

- first field
- combine current field with previous results
- no fields
- non-matching enum variants

This commit clarifies things by replacing the three function arguments
with one that takes a new `CsFold` type with four slightly different)
cases

- single field
- combine result for current field with results for previous fields
- no fields
- non-matching enum variants

This makes the code shorter and clearer.
2022-07-09 09:02:50 +10:00
Nicholas Nethercote
65d0bfbca5 Cut down large comment about zero-variant enums.
When deriving functions for zero-variant enums, we just generated a
function body that calls `std::instrincs::unreachable`. There is a large
comment with some not-very-useful historical discussion about
alternatives, including some discussion of feature-gating zero-variant
enums, which is clearly irrelevant today.

This commit cuts the comment down greatly.
2022-07-09 09:02:50 +10:00
Nicholas Nethercote
7f1dfcab67 Avoid transposes in deriving code.
The deriving code has some complex parts involving iterations over
selflike args and also fields within structs and enum variants.

The return types for a few functions demonstrate this:

- `TraitDef::create_{struct_pattern,enum_variant_pattern}` returns a
  `(P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>)>)`
- `TraitDef::create_struct_field_accesses` returns a `Vec<(Span,
  Option<Ident>, P<Expr>)>`.

This results in per-field data stored within per-selflike-arg data, with
lots of repetition within the per-field data elements. This then has to
be "transposed" in two places (`expand_struct_method_body` and
`expand_enum_method_body`) into per-self-like-arg data stored within
per-field data. It's all quite clumsy and confusing.

This commit rearranges things greatly. Data is obtained in the needed
form up-front, avoiding the need for transposition. Also, various
functions are split, removed, and added, to make things clearer and
avoid tuple return values.

The diff is hard to read, which reflects the messiness of the original
code -- there wasn't an easy way to break these changes into small
pieces. (Sorry!) It's a net reduction of 35 lines and a readability
improvement. The generated code is unchanged.
2022-07-09 09:02:50 +10:00
Nicholas Nethercote
27571da5fa Remove FieldInfo::attrs.
It's unused. This also removes the need for the lifetime on `FieldInfo`,
which is nice.
2022-07-09 09:02:50 +10:00
Nicholas Nethercote
d3057b5ca7 Rename FieldInfo fields.
Use `self_exprs` and `other_selflike_exprs` in a manner similar to the
previous commit.
2022-07-09 09:02:50 +10:00
Nicholas Nethercote
32c9ffb9cc Clarify args terminology.
The deriving code has inconsistent terminology to describe args.

In some places it distinguishes between:
- the `&self` arg (if present), versus
- all other args.

In other places it distinguishes between:
- the `&self` arg (if present) and any other arguments with the same
  type (in practice there is at most one, e.g. in `PartialEq::eq`),
  versus
- all other args.

The terms "self_args" and "nonself_args" are sometimes used for the
former distinction, and sometimes for the latter. "args" is also
sometimes used for "all other args".

This commit makes the code consistently uses "self_args"/"nonself_args"
for the former and "selflike_args"/"nonselflike_args" for the latter.
This change makes the code easier to read.

The commit also adds a panic on an impossible path (the `Self_` case) in
`extract_arg_details`.
2022-07-09 09:02:49 +10:00
Nicholas Nethercote
0da063c991 Inline and remove the cs_fold_* functions.
Because they now have a single call site each.

Also rename `cs_fold1` as `cs_fold`, now that it's the only folding
function left.
2022-07-05 09:34:56 +10:00
Nicholas Nethercote
0ee79f2c5a Avoid the unnecessary innermost match in partial_cmp/cmp.
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.)
2022-07-05 09:34:54 +10:00
Nicholas Nethercote
2c911dc16f Avoid unnecessary 1-tuples in derived code. 2022-07-04 18:37:29 +10:00
Nicholas Nethercote
5762d2385e Avoid unnecessary blocks in derive output.
By not committing to either block form or expression form until
necessary, we can avoid lots of unnecessary blocks.
2022-07-04 18:34:20 +10:00
Nicholas Nethercote
ecc6e95ed4 Don't use match-destructuring for derived ops on structs.
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:#️⃣:Hasher>(&self, state: &mut __H) -> () {
    {
	let Self(ref __self_0_0) = *self;
	{ ::core:#️⃣: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.
2022-07-04 10:48:15 +10:00
Nicholas Nethercote
528343f93b Comment fixes.
Remove an out-of-date sentence, and fix a typo.
2022-07-04 10:48:15 +10:00
Nicholas Nethercote
b94246693a Simplify pointer handling.
The existing derive code allows for various possibilities that aren't
needed in practice, which complicates the code. There are only a few
auto-derived traits and new ones are unlikely, so this commit simplifies
things.

- `PtrTy` has been eliminated. The `Raw` variant was never used, and the
  lifetime for the `Borrowed` variant was always `None`. That left just
  the mutability field, which has been inlined as necessary.
- `MethodDef::explicit_self` was a confusing `Option<Option<PtrTy>>`.
  Indicating either `&self` or nothing. It's now a `bool`.
- `borrowed_self` is renamed as `self_ref`.
- `Ty::Ptr` is renamed to `Ty::Ref`.
2022-07-01 15:16:17 +10:00
Nicholas Nethercote
57d56891d2 Remove some unnecessary pubs. 2022-07-01 06:35:14 +10:00
Nicholas Nethercote
89f6917a49 Remove Substructure::self_args.
It's unused.
2022-07-01 06:35:14 +10:00
Nicholas Nethercote
1254fe974d Remove {Method,Trait}Def::is_unsafe.
They are always `false`.
2022-07-01 06:35:01 +10:00
Nicholas Nethercote
d13fa0d21b Remove Substructure::method_ident.
It's unused.
2022-07-01 06:04:36 +10:00