2014-06-09 20:12:30 +00:00
|
|
|
//! Some code that abstracts away much of the boilerplate of writing
|
2014-12-31 04:25:18 +00:00
|
|
|
//! `derive` instances for traits. Among other things it manages getting
|
2014-06-09 20:12:30 +00:00
|
|
|
//! access to the fields of the 4 different sorts of structs and enum
|
|
|
|
//! variants, as well as creating the method and impl ast instances.
|
|
|
|
//!
|
|
|
|
//! Supported features (fairly exhaustive):
|
|
|
|
//!
|
|
|
|
//! - Methods taking any number of parameters of any type, and returning
|
|
|
|
//! any type, other than vectors, bottom and closures.
|
|
|
|
//! - Generating `impl`s for types with type parameters and lifetimes
|
2018-11-27 02:59:49 +00:00
|
|
|
//! (e.g., `Option<T>`), the parameters are automatically given the
|
2014-06-09 20:12:30 +00:00
|
|
|
//! current trait as a bound. (This includes separate type parameters
|
|
|
|
//! and lifetimes for methods.)
|
2015-01-12 13:00:19 +00:00
|
|
|
//! - Additional bounds on the type parameters (`TraitDef.additional_bounds`)
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2017-08-15 19:45:21 +00:00
|
|
|
//! The most important thing for implementors is the `Substructure` and
|
2014-06-09 20:12:30 +00:00
|
|
|
//! `SubstructureFields` objects. The latter groups 5 possibilities of the
|
|
|
|
//! arguments:
|
|
|
|
//!
|
|
|
|
//! - `Struct`, when `Self` is a struct (including tuple structs, e.g
|
2015-01-17 23:55:21 +00:00
|
|
|
//! `struct T(i32, char)`).
|
2014-06-09 20:12:30 +00:00
|
|
|
//! - `EnumMatching`, when `Self` is an enum and all the arguments are the
|
2018-11-27 02:59:49 +00:00
|
|
|
//! same variant of the enum (e.g., `Some(1)`, `Some(3)` and `Some(4)`)
|
2024-04-14 09:31:51 +00:00
|
|
|
//! - `EnumDiscr` when `Self` is an enum, for comparing the enum discriminants.
|
2014-06-09 20:12:30 +00:00
|
|
|
//! - `StaticEnum` and `StaticStruct` for static methods, where the type
|
|
|
|
//! being derived upon is either an enum or struct respectively. (Any
|
|
|
|
//! argument with type Self is just grouped among the non-self
|
|
|
|
//! arguments.)
|
|
|
|
//!
|
|
|
|
//! In the first two cases, the values from the corresponding fields in
|
2022-07-08 05:32:27 +00:00
|
|
|
//! all the arguments are grouped together.
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
|
|
|
//! The non-static cases have `Option<ident>` in several places associated
|
|
|
|
//! with field `expr`s. This represents the name of the field it is
|
|
|
|
//! associated with. It is only not `None` when the associated field has
|
|
|
|
//! an identifier in the source code. For example, the `x`s in the
|
|
|
|
//! following snippet
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2023-10-22 19:04:50 +00:00
|
|
|
//! struct A {
|
|
|
|
//! x: i32,
|
|
|
|
//! }
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2015-01-17 23:55:21 +00:00
|
|
|
//! struct B(i32);
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
|
|
|
//! enum C {
|
2015-01-17 23:55:21 +00:00
|
|
|
//! C0(i32),
|
|
|
|
//! C1 { x: i32 }
|
2014-06-09 20:12:30 +00:00
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
2015-01-17 23:55:21 +00:00
|
|
|
//! The `i32`s in `B` and `C0` don't have an identifier, so the
|
2014-06-09 20:12:30 +00:00
|
|
|
//! `Option<ident>`s would be `None` for them.
|
|
|
|
//!
|
2018-11-12 18:05:20 +00:00
|
|
|
//! In the static cases, the structure is summarized, either into the just
|
2014-06-09 20:12:30 +00:00
|
|
|
//! spans of the fields or a list of spans and the field idents (for tuple
|
|
|
|
//! structs and record structs, respectively), or a list of these, for
|
|
|
|
//! enums (one for each variant). For empty struct and empty enum
|
|
|
|
//! variants, it is represented as a count of 0.
|
|
|
|
//!
|
2015-01-12 13:00:19 +00:00
|
|
|
//! # "`cs`" functions
|
|
|
|
//!
|
2022-06-23 22:31:00 +00:00
|
|
|
//! The `cs_...` functions ("combine substructure") are designed to
|
2015-01-12 13:00:19 +00:00
|
|
|
//! make life easier by providing some pre-made recipes for common
|
2015-05-08 15:12:29 +00:00
|
|
|
//! threads; mostly calling the function being derived on all the
|
2015-01-12 13:00:19 +00:00
|
|
|
//! arguments and then combining them back together in some way (or
|
|
|
|
//! letting the user chose that). They are not meant to be the only
|
|
|
|
//! way to handle the structures that this code creates.
|
|
|
|
//!
|
2014-06-09 20:12:30 +00:00
|
|
|
//! # Examples
|
|
|
|
//!
|
|
|
|
//! The following simplified `PartialEq` is used for in-code examples:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! trait PartialEq {
|
2015-11-03 16:34:11 +00:00
|
|
|
//! fn eq(&self, other: &Self) -> bool;
|
2014-06-09 20:12:30 +00:00
|
|
|
//! }
|
2023-10-22 19:04:50 +00:00
|
|
|
//!
|
2015-01-17 23:55:21 +00:00
|
|
|
//! impl PartialEq for i32 {
|
|
|
|
//! fn eq(&self, other: &i32) -> bool {
|
2014-06-09 20:12:30 +00:00
|
|
|
//! *self == *other
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! Some examples of the values of `SubstructureFields` follow, using the
|
|
|
|
//! above `PartialEq`, `A`, `B` and `C`.
|
|
|
|
//!
|
|
|
|
//! ## Structs
|
|
|
|
//!
|
|
|
|
//! When generating the `expr` for the `A` impl, the `SubstructureFields` is
|
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2015-01-12 13:00:19 +00:00
|
|
|
//! Struct(vec![FieldInfo {
|
2023-10-22 19:04:50 +00:00
|
|
|
//! span: <span of x>,
|
|
|
|
//! name: Some(<ident of x>),
|
|
|
|
//! self_: <expr for &self.x>,
|
|
|
|
//! other: vec![<expr for &other.x>],
|
|
|
|
//! }])
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
|
|
|
//! For the `B` impl, called with `B(a)` and `B(b)`,
|
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2015-01-12 13:00:19 +00:00
|
|
|
//! Struct(vec![FieldInfo {
|
2023-10-22 19:04:50 +00:00
|
|
|
//! span: <span of i32>,
|
|
|
|
//! name: None,
|
|
|
|
//! self_: <expr for &a>,
|
|
|
|
//! other: vec![<expr for &b>],
|
|
|
|
//! }])
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
|
|
|
//! ## Enums
|
|
|
|
//!
|
|
|
|
//! When generating the `expr` for a call with `self == C0(a)` and `other
|
|
|
|
//! == C0(b)`, the SubstructureFields is
|
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2023-10-22 19:04:50 +00:00
|
|
|
//! EnumMatching(
|
|
|
|
//! 0,
|
|
|
|
//! <ast::Variant for C0>,
|
|
|
|
//! vec![FieldInfo {
|
|
|
|
//! span: <span of i32>,
|
|
|
|
//! name: None,
|
|
|
|
//! self_: <expr for &a>,
|
|
|
|
//! other: vec![<expr for &b>],
|
|
|
|
//! }],
|
|
|
|
//! )
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2014-07-06 19:19:12 +00:00
|
|
|
//! For `C1 {x}` and `C1 {x}`,
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2023-10-22 19:04:50 +00:00
|
|
|
//! EnumMatching(
|
|
|
|
//! 1,
|
|
|
|
//! <ast::Variant for C1>,
|
|
|
|
//! vec![FieldInfo {
|
|
|
|
//! span: <span of x>,
|
|
|
|
//! name: Some(<ident of x>),
|
|
|
|
//! self_: <expr for &self.x>,
|
|
|
|
//! other: vec![<expr for &other.x>],
|
|
|
|
//! }],
|
|
|
|
//! )
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2024-04-14 09:31:51 +00:00
|
|
|
//! For the discriminants,
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2024-04-14 09:31:51 +00:00
|
|
|
//! EnumDiscr(
|
|
|
|
//! &[<ident of self discriminant>, <ident of other discriminant>],
|
2023-10-22 19:04:50 +00:00
|
|
|
//! <expr to combine with>,
|
|
|
|
//! )
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2023-10-22 19:04:50 +00:00
|
|
|
//!
|
2022-07-08 05:32:27 +00:00
|
|
|
//! Note that this setup doesn't allow for the brute-force "match every variant
|
|
|
|
//! against every other variant" approach, which is bad because it produces a
|
|
|
|
//! quadratic amount of code (see #15375).
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
|
|
|
//! ## Static
|
|
|
|
//!
|
2015-01-12 13:00:19 +00:00
|
|
|
//! A static method on the types above would result in,
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2023-09-16 09:37:41 +00:00
|
|
|
//! ```text
|
2015-10-08 00:20:57 +00:00
|
|
|
//! StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2015-10-08 00:20:57 +00:00
|
|
|
//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
|
2014-06-09 20:12:30 +00:00
|
|
|
//!
|
2023-10-22 19:04:50 +00:00
|
|
|
//! StaticEnum(
|
|
|
|
//! <ast::EnumDef of C>,
|
|
|
|
//! vec![
|
|
|
|
//! (<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
|
|
|
|
//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)])),
|
|
|
|
//! ],
|
|
|
|
//! )
|
2014-09-16 11:27:34 +00:00
|
|
|
//! ```
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
use std::cell::RefCell;
|
|
|
|
use std::ops::Not;
|
|
|
|
use std::{iter, vec};
|
2014-11-06 08:05:53 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) use StaticFields::*;
|
|
|
|
pub(crate) use SubstructureFields::*;
|
2020-02-29 17:37:32 +00:00
|
|
|
use rustc_ast::ptr::P;
|
2022-08-30 22:34:35 +00:00
|
|
|
use rustc_ast::{
|
2024-08-24 17:22:48 +00:00
|
|
|
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
|
|
|
Generics, Mutability, PatKind, VariantData,
|
2022-08-30 22:34:35 +00:00
|
|
|
};
|
2025-02-09 21:49:33 +00:00
|
|
|
use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprPacked};
|
2019-12-29 14:23:55 +00:00
|
|
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
2025-02-09 21:49:33 +00:00
|
|
|
use rustc_hir::Attribute;
|
2024-12-12 23:29:23 +00:00
|
|
|
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
2022-11-21 22:17:20 +00:00
|
|
|
use thin_vec::{ThinVec, thin_vec};
|
2022-06-29 23:15:07 +00:00
|
|
|
use ty::{Bounds, Path, Ref, Self_, Ty};
|
2024-07-28 22:13:50 +00:00
|
|
|
|
2023-04-08 19:37:41 +00:00
|
|
|
use crate::{deriving, errors};
|
2014-05-29 03:19:05 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) mod ty;
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) struct TraitDef<'a> {
|
2014-12-31 04:25:18 +00:00
|
|
|
/// The span for the current #[derive(Foo)] header.
|
2014-03-27 22:39:48 +00:00
|
|
|
pub span: Span,
|
2013-12-07 00:57:44 +00:00
|
|
|
|
2013-05-06 15:23:51 +00:00
|
|
|
/// Path of the trait, including any type parameters
|
2020-07-14 05:05:26 +00:00
|
|
|
pub path: Path,
|
2014-02-09 00:39:53 +00:00
|
|
|
|
2022-08-26 12:59:12 +00:00
|
|
|
/// Whether to skip adding the current trait as a bound to the type parameters of the type.
|
|
|
|
pub skip_path_as_bound: bool,
|
|
|
|
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
/// Whether `Copy` is needed as an additional bound on type parameters in a packed struct.
|
|
|
|
pub needs_copy_as_bound_if_packed: bool,
|
|
|
|
|
2013-05-06 15:23:51 +00:00
|
|
|
/// Additional bounds required of any type parameters of the type,
|
|
|
|
/// other than the current trait
|
2020-07-14 05:05:26 +00:00
|
|
|
pub additional_bounds: Vec<Ty>,
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2016-08-29 11:14:25 +00:00
|
|
|
/// Can this trait be derived for unions?
|
|
|
|
pub supports_unions: bool,
|
|
|
|
|
2014-03-27 22:39:48 +00:00
|
|
|
pub methods: Vec<MethodDef<'a>>,
|
2015-01-25 05:29:24 +00:00
|
|
|
|
2020-07-14 05:05:26 +00:00
|
|
|
pub associated_types: Vec<(Ident, Ty)>,
|
2022-09-20 11:55:07 +00:00
|
|
|
|
|
|
|
pub is_const: bool,
|
2014-03-27 22:39:48 +00:00
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) struct MethodDef<'a> {
|
2013-03-28 10:50:10 +00:00
|
|
|
/// name of the method
|
2020-07-08 01:04:10 +00:00
|
|
|
pub name: Symbol,
|
2018-11-27 02:59:49 +00:00
|
|
|
/// List of generics, e.g., `R: rand::Rng`
|
2020-07-14 05:05:26 +00:00
|
|
|
pub generics: Bounds,
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2022-06-29 23:15:07 +00:00
|
|
|
/// Is there is a `&self` argument? If not, it is a static function.
|
|
|
|
pub explicit_self: bool,
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
/// Arguments other than the self argument.
|
|
|
|
pub nonself_args: Vec<(Ty, Symbol)>,
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2019-02-08 13:53:55 +00:00
|
|
|
/// Returns type
|
2020-07-14 05:05:26 +00:00
|
|
|
pub ret_ty: Ty,
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2022-08-17 02:34:33 +00:00
|
|
|
pub attributes: ast::AttrVec,
|
2013-11-19 00:13:34 +00:00
|
|
|
|
2023-01-14 21:16:25 +00:00
|
|
|
pub fieldless_variants_strategy: FieldlessVariantsStrategy,
|
2016-05-12 15:54:05 +00:00
|
|
|
|
2014-04-22 06:25:18 +00:00
|
|
|
pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 21:16:25 +00:00
|
|
|
/// How to handle fieldless enum variants.
|
|
|
|
#[derive(PartialEq)]
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) enum FieldlessVariantsStrategy {
|
2023-01-14 21:16:25 +00:00
|
|
|
/// Combine fieldless variants into a single match arm.
|
|
|
|
/// This assumes that relevant information has been handled
|
|
|
|
/// by looking at the enum's discriminant.
|
|
|
|
Unify,
|
|
|
|
/// Don't do anything special about fieldless variants. They are
|
|
|
|
/// handled like any other variant.
|
|
|
|
Default,
|
|
|
|
/// If all variants of the enum are fieldless, expand the special
|
|
|
|
/// `AllFieldLessEnum` substructure, so that the entire enum can be handled
|
|
|
|
/// at once.
|
|
|
|
SpecializeIfAllVariantsFieldless,
|
|
|
|
}
|
|
|
|
|
2013-03-28 10:50:10 +00:00
|
|
|
/// All the data about the data structure/method being derived upon.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) struct Substructure<'a> {
|
2013-05-06 15:23:51 +00:00
|
|
|
/// ident of self
|
2014-03-27 22:39:48 +00:00
|
|
|
pub type_ident: Ident,
|
2022-07-07 21:57:34 +00:00
|
|
|
/// Verbatim access to any non-selflike arguments, i.e. arguments that
|
|
|
|
/// don't have type `&Self`.
|
2022-07-04 22:25:47 +00:00
|
|
|
pub nonselflike_args: &'a [P<Expr>],
|
2016-07-19 17:32:06 +00:00
|
|
|
pub fields: &'a SubstructureFields<'a>,
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2013-11-07 07:49:01 +00:00
|
|
|
/// Summary of the relevant parts of a struct/enum field.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) struct FieldInfo {
|
2014-03-27 22:39:48 +00:00
|
|
|
pub span: Span,
|
2013-11-07 07:49:01 +00:00
|
|
|
/// None for tuple structs/normal enum variants, Some for normal
|
|
|
|
/// structs/struct enum variants.
|
2014-03-27 22:39:48 +00:00
|
|
|
pub name: Option<Ident>,
|
2013-11-07 07:49:01 +00:00
|
|
|
/// The expression corresponding to this field of `self`
|
|
|
|
/// (specifically, a reference to it).
|
2022-07-04 22:47:04 +00:00
|
|
|
pub self_expr: P<Expr>,
|
2013-11-07 07:49:01 +00:00
|
|
|
/// The expressions corresponding to references to this field in
|
2022-07-04 22:47:04 +00:00
|
|
|
/// the other selflike arguments.
|
|
|
|
pub other_selflike_exprs: Vec<P<Expr>>,
|
2014-03-27 22:39:48 +00:00
|
|
|
}
|
2013-11-07 07:49:01 +00:00
|
|
|
|
2024-02-13 23:31:06 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) enum IsTuple {
|
2024-02-13 23:31:06 +00:00
|
|
|
No,
|
|
|
|
Yes,
|
|
|
|
}
|
|
|
|
|
2013-11-07 07:49:01 +00:00
|
|
|
/// Fields for a static method
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) enum StaticFields {
|
2016-08-15 18:28:17 +00:00
|
|
|
/// Tuple and unit structs/enum variants like this.
|
2024-02-13 23:31:06 +00:00
|
|
|
Unnamed(Vec<Span>, IsTuple),
|
2013-11-07 07:49:01 +00:00
|
|
|
/// Normal structs/struct variants.
|
2024-08-24 17:22:48 +00:00
|
|
|
Named(Vec<(Ident, Span, Option<AnonConst>)>),
|
2013-11-07 07:49:01 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 13:12:58 +00:00
|
|
|
/// A summary of the possible sets of fields.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) enum SubstructureFields<'a> {
|
2023-01-14 21:16:25 +00:00
|
|
|
/// A non-static method where `Self` is a struct.
|
2022-07-04 22:59:17 +00:00
|
|
|
Struct(&'a ast::VariantData, Vec<FieldInfo>),
|
2022-07-08 05:32:27 +00:00
|
|
|
|
2023-01-14 21:16:25 +00:00
|
|
|
/// A non-static method handling the entire enum at once
|
|
|
|
/// (after it has been determined that none of the enum
|
|
|
|
/// variants has any fields).
|
|
|
|
AllFieldlessEnum(&'a ast::EnumDef),
|
|
|
|
|
2024-01-03 16:45:41 +00:00
|
|
|
/// Matching variants of the enum: variant index, ast::Variant,
|
2014-09-16 11:27:34 +00:00
|
|
|
/// fields: the field name is only non-`None` in the case of a struct
|
|
|
|
/// variant.
|
2025-01-07 17:28:42 +00:00
|
|
|
EnumMatching(&'a ast::Variant, Vec<FieldInfo>),
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
/// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as
|
2022-07-08 05:32:27 +00:00
|
|
|
/// if they were fields. The second field is the expression to combine the
|
2024-04-14 09:31:51 +00:00
|
|
|
/// discriminant expression with; it will be `None` if no match is necessary.
|
|
|
|
EnumDiscr(FieldInfo, Option<P<Expr>>),
|
2014-07-06 19:19:12 +00:00
|
|
|
|
2014-09-17 13:02:26 +00:00
|
|
|
/// A static method where `Self` is a struct.
|
2015-10-08 00:20:57 +00:00
|
|
|
StaticStruct(&'a ast::VariantData, StaticFields),
|
2022-07-08 05:32:27 +00:00
|
|
|
|
2014-09-17 13:02:26 +00:00
|
|
|
/// A static method where `Self` is an enum.
|
2025-01-07 17:28:42 +00:00
|
|
|
StaticEnum(&'a ast::EnumDef),
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-16 11:27:34 +00:00
|
|
|
/// Combine the values of all the fields together. The last argument is
|
2014-09-17 13:12:58 +00:00
|
|
|
/// all the fields of all the structures.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) type CombineSubstructureFunc<'a> =
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
Box<dyn FnMut(&ExtCtxt<'_>, Span, &Substructure<'_>) -> BlockOrExpr + 'a>;
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) fn combine_substructure(
|
2019-06-21 16:51:27 +00:00
|
|
|
f: CombineSubstructureFunc<'_>,
|
|
|
|
) -> RefCell<CombineSubstructureFunc<'_>> {
|
2014-04-22 06:25:18 +00:00
|
|
|
RefCell::new(f)
|
|
|
|
}
|
|
|
|
|
2021-09-28 22:46:29 +00:00
|
|
|
struct TypeParameter {
|
2022-11-21 22:17:20 +00:00
|
|
|
bound_generic_params: ThinVec<ast::GenericParam>,
|
2021-09-28 22:46:29 +00:00
|
|
|
ty: P<ast::Ty>,
|
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// The code snippets built up for derived code are sometimes used as blocks
|
|
|
|
/// (e.g. in a function body) and sometimes used as expressions (e.g. in a match
|
|
|
|
/// arm). This structure avoids committing to either form until necessary,
|
|
|
|
/// avoiding the insertion of any unnecessary blocks.
|
|
|
|
///
|
|
|
|
/// The statements come before the expression.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<P<Expr>>);
|
2022-06-28 03:10:36 +00:00
|
|
|
|
|
|
|
impl BlockOrExpr {
|
2024-07-06 12:08:04 +00:00
|
|
|
pub(crate) fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr {
|
2022-06-28 03:10:36 +00:00
|
|
|
BlockOrExpr(stmts, None)
|
|
|
|
}
|
|
|
|
|
2024-07-06 12:08:04 +00:00
|
|
|
pub(crate) fn new_expr(expr: P<Expr>) -> BlockOrExpr {
|
2023-01-30 03:13:27 +00:00
|
|
|
BlockOrExpr(ThinVec::new(), Some(expr))
|
2022-06-28 03:10:36 +00:00
|
|
|
}
|
|
|
|
|
2024-07-06 12:08:04 +00:00
|
|
|
pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr {
|
2022-07-08 05:32:27 +00:00
|
|
|
BlockOrExpr(stmts, expr)
|
2022-06-28 03:10:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Converts it into a block.
|
|
|
|
fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> P<ast::Block> {
|
|
|
|
if let Some(expr) = self.1 {
|
|
|
|
self.0.push(cx.stmt_expr(expr));
|
|
|
|
}
|
|
|
|
cx.block(span, self.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Converts it into an expression.
|
|
|
|
fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> {
|
|
|
|
if self.0.is_empty() {
|
|
|
|
match self.1 {
|
2023-01-30 03:13:27 +00:00
|
|
|
None => cx.expr_block(cx.block(span, ThinVec::new())),
|
2022-06-28 03:10:36 +00:00
|
|
|
Some(expr) => expr,
|
|
|
|
}
|
2024-08-07 10:41:49 +00:00
|
|
|
} else if let [stmt] = self.0.as_slice()
|
|
|
|
&& let ast::StmtKind::Expr(expr) = &stmt.kind
|
2022-07-08 05:27:42 +00:00
|
|
|
&& self.1.is_none()
|
|
|
|
{
|
|
|
|
// There's only a single statement expression. Pull it out.
|
|
|
|
expr.clone()
|
2022-06-28 03:10:36 +00:00
|
|
|
} else {
|
2022-07-08 05:27:42 +00:00
|
|
|
// Multiple statements and/or expressions.
|
2022-06-28 03:10:36 +00:00
|
|
|
cx.expr_block(self.into_block(cx, span))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 21:43:26 +00:00
|
|
|
/// This method helps to extract all the type parameters referenced from a
|
|
|
|
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
|
|
|
|
/// is not global and starts with `T`, or a `TyQPath`.
|
2021-09-28 22:46:29 +00:00
|
|
|
/// Also include bound generic params from the input type.
|
2019-06-16 09:41:24 +00:00
|
|
|
fn find_type_parameters(
|
|
|
|
ty: &ast::Ty,
|
2020-04-19 11:00:18 +00:00
|
|
|
ty_param_names: &[Symbol],
|
2019-06-16 09:41:24 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2021-09-28 22:46:29 +00:00
|
|
|
) -> Vec<TypeParameter> {
|
2020-02-29 17:37:32 +00:00
|
|
|
use rustc_ast::visit;
|
2015-03-24 21:43:26 +00:00
|
|
|
|
2019-06-14 16:39:39 +00:00
|
|
|
struct Visitor<'a, 'b> {
|
2016-06-24 03:23:44 +00:00
|
|
|
cx: &'a ExtCtxt<'b>,
|
2020-04-19 11:00:18 +00:00
|
|
|
ty_param_names: &'a [Symbol],
|
2022-11-21 22:17:20 +00:00
|
|
|
bound_generic_params_stack: ThinVec<ast::GenericParam>,
|
2021-09-28 22:46:29 +00:00
|
|
|
type_params: Vec<TypeParameter>,
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
|
|
|
|
2016-12-06 10:26:52 +00:00
|
|
|
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
|
|
|
|
fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
2024-06-04 19:09:15 +00:00
|
|
|
let stack_len = self.bound_generic_params_stack.len();
|
|
|
|
if let ast::TyKind::BareFn(bare_fn) = &ty.kind
|
|
|
|
&& !bare_fn.generic_params.is_empty()
|
|
|
|
{
|
|
|
|
// Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so
|
|
|
|
// that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622
|
|
|
|
self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned());
|
|
|
|
}
|
|
|
|
|
2022-12-06 13:22:36 +00:00
|
|
|
if let ast::TyKind::Path(_, path) = &ty.kind
|
|
|
|
&& let Some(segment) = path.segments.first()
|
|
|
|
&& self.ty_param_names.contains(&segment.ident.name)
|
|
|
|
{
|
|
|
|
self.type_params.push(TypeParameter {
|
|
|
|
bound_generic_params: self.bound_generic_params_stack.clone(),
|
|
|
|
ty: P(ty.clone()),
|
|
|
|
});
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
|
|
|
|
2024-06-04 19:09:15 +00:00
|
|
|
visit::walk_ty(self, ty);
|
|
|
|
self.bound_generic_params_stack.truncate(stack_len);
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
2016-06-24 03:23:44 +00:00
|
|
|
|
2021-09-28 22:46:29 +00:00
|
|
|
// Place bound generic params on a stack, to extract them when a type is encountered.
|
2022-08-11 01:05:26 +00:00
|
|
|
fn visit_poly_trait_ref(&mut self, trait_ref: &'a ast::PolyTraitRef) {
|
2021-09-29 01:18:56 +00:00
|
|
|
let stack_len = self.bound_generic_params_stack.len();
|
2022-08-13 13:50:01 +00:00
|
|
|
self.bound_generic_params_stack.extend(trait_ref.bound_generic_params.iter().cloned());
|
2021-09-28 22:46:29 +00:00
|
|
|
|
2022-08-11 01:05:26 +00:00
|
|
|
visit::walk_poly_trait_ref(self, trait_ref);
|
2021-09-28 22:46:29 +00:00
|
|
|
|
|
|
|
self.bound_generic_params_stack.truncate(stack_len);
|
|
|
|
}
|
|
|
|
|
2020-11-03 17:34:57 +00:00
|
|
|
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
|
2023-12-18 09:54:03 +00:00
|
|
|
self.cx.dcx().emit_err(errors::DeriveMacroCall { span: mac.span() });
|
2016-06-24 03:23:44 +00:00
|
|
|
}
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 22:46:29 +00:00
|
|
|
let mut visitor = Visitor {
|
|
|
|
cx,
|
|
|
|
ty_param_names,
|
2022-11-21 22:17:20 +00:00
|
|
|
bound_generic_params_stack: ThinVec::new(),
|
2021-09-28 22:46:29 +00:00
|
|
|
type_params: Vec::new(),
|
|
|
|
};
|
2015-03-24 21:43:26 +00:00
|
|
|
visit::Visitor::visit_ty(&mut visitor, ty);
|
|
|
|
|
2021-09-28 22:46:29 +00:00
|
|
|
visitor.type_params
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2013-12-10 07:16:18 +00:00
|
|
|
impl<'a> TraitDef<'a> {
|
2024-07-06 12:08:04 +00:00
|
|
|
pub(crate) fn expand(
|
2017-10-02 13:15:23 +00:00
|
|
|
self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2015-03-27 01:07:49 +00:00
|
|
|
mitem: &ast::MetaItem,
|
2015-05-12 02:15:02 +00:00
|
|
|
item: &'a Annotatable,
|
2018-07-12 09:58:16 +00:00
|
|
|
push: &mut dyn FnMut(Annotatable),
|
|
|
|
) {
|
2016-08-26 16:23:42 +00:00
|
|
|
self.expand_ext(cx, mitem, item, push, false);
|
|
|
|
}
|
|
|
|
|
2024-07-06 12:08:04 +00:00
|
|
|
pub(crate) fn expand_ext(
|
2017-10-02 13:15:23 +00:00
|
|
|
self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2016-08-26 16:23:42 +00:00
|
|
|
mitem: &ast::MetaItem,
|
|
|
|
item: &'a Annotatable,
|
2018-07-12 09:58:16 +00:00
|
|
|
push: &mut dyn FnMut(Annotatable),
|
2016-08-26 16:23:42 +00:00
|
|
|
from_scratch: bool,
|
|
|
|
) {
|
2022-12-06 13:22:36 +00:00
|
|
|
match item {
|
|
|
|
Annotatable::Item(item) => {
|
2025-02-09 21:49:33 +00:00
|
|
|
let is_packed = matches!(
|
|
|
|
AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, true),
|
|
|
|
Some(Attribute::Parsed(AttributeKind::Repr(r))) if r.iter().any(|(x, _)| matches!(x, ReprPacked(..)))
|
|
|
|
);
|
2017-11-19 15:04:24 +00:00
|
|
|
|
2022-12-06 13:22:36 +00:00
|
|
|
let newitem = match &item.kind {
|
|
|
|
ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
|
2017-10-02 13:15:23 +00:00
|
|
|
cx,
|
2023-11-21 19:07:32 +00:00
|
|
|
struct_def,
|
2017-10-02 13:15:23 +00:00
|
|
|
item.ident,
|
|
|
|
generics,
|
|
|
|
from_scratch,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed,
|
2019-12-22 22:42:04 +00:00
|
|
|
),
|
2022-12-06 13:22:36 +00:00
|
|
|
ast::ItemKind::Enum(enum_def, generics) => {
|
2022-11-21 00:48:25 +00:00
|
|
|
// We ignore `is_packed` here, because `repr(packed)`
|
|
|
|
// enums cause an error later on.
|
2017-10-02 13:15:23 +00:00
|
|
|
//
|
|
|
|
// This can only cause further compilation errors
|
2022-11-21 00:48:25 +00:00
|
|
|
// downstream in blatantly illegal code, so it is fine.
|
2020-04-05 18:36:39 +00:00
|
|
|
self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
|
2015-04-28 05:34:39 +00:00
|
|
|
}
|
2022-12-06 13:22:36 +00:00
|
|
|
ast::ItemKind::Union(struct_def, generics) => {
|
2016-08-24 18:10:19 +00:00
|
|
|
if self.supports_unions {
|
2016-08-26 16:23:42 +00:00
|
|
|
self.expand_struct_def(
|
|
|
|
cx,
|
2023-11-21 19:07:32 +00:00
|
|
|
struct_def,
|
2016-08-26 16:23:42 +00:00
|
|
|
item.ident,
|
2017-10-02 13:15:23 +00:00
|
|
|
generics,
|
|
|
|
from_scratch,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed,
|
2017-10-02 13:15:23 +00:00
|
|
|
)
|
2016-08-24 18:10:19 +00:00
|
|
|
} else {
|
2023-12-18 09:54:03 +00:00
|
|
|
cx.dcx().emit_err(errors::DeriveUnion { span: mitem.span });
|
2016-08-24 18:10:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-11-19 15:04:24 +00:00
|
|
|
_ => unreachable!(),
|
2015-04-28 05:34:39 +00:00
|
|
|
};
|
|
|
|
// Keep the lint attributes of the previous item to control how the
|
|
|
|
// generated implementations are linted
|
|
|
|
let mut attrs = newitem.attrs.clone();
|
2016-07-19 17:32:06 +00:00
|
|
|
attrs.extend(
|
|
|
|
item.attrs
|
|
|
|
.iter()
|
2019-03-17 11:17:47 +00:00
|
|
|
.filter(|a| {
|
2019-05-08 04:33:06 +00:00
|
|
|
[
|
|
|
|
sym::allow,
|
|
|
|
sym::warn,
|
|
|
|
sym::deny,
|
|
|
|
sym::forbid,
|
|
|
|
sym::stable,
|
|
|
|
sym::unstable,
|
|
|
|
]
|
|
|
|
.contains(&a.name_or_empty())
|
2019-03-17 11:17:47 +00:00
|
|
|
})
|
2016-07-19 17:32:06 +00:00
|
|
|
.cloned(),
|
|
|
|
);
|
2020-03-06 18:28:44 +00:00
|
|
|
push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
|
2014-02-13 07:53:52 +00:00
|
|
|
}
|
2020-11-18 22:55:59 +00:00
|
|
|
_ => unreachable!(),
|
2015-04-28 05:34:39 +00:00
|
|
|
}
|
2013-06-07 07:46:44 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 21:43:26 +00:00
|
|
|
/// Given that we are deriving a trait `DerivedTrait` for a type like:
|
2014-09-16 11:27:34 +00:00
|
|
|
///
|
2017-06-20 07:15:16 +00:00
|
|
|
/// ```ignore (only-for-syntax-highlight)
|
2023-10-22 19:04:50 +00:00
|
|
|
/// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
|
|
|
|
/// where
|
|
|
|
/// C: WhereTrait,
|
|
|
|
/// {
|
2015-03-24 21:43:26 +00:00
|
|
|
/// a: A,
|
|
|
|
/// b: B::Item,
|
|
|
|
/// b1: <B as DeclaredTrait>::Item,
|
|
|
|
/// c1: <C as WhereTrait>::Item,
|
|
|
|
/// c2: Option<<C as WhereTrait>::Item>,
|
|
|
|
/// ...
|
|
|
|
/// }
|
2014-09-16 11:27:34 +00:00
|
|
|
/// ```
|
|
|
|
///
|
2015-03-24 21:43:26 +00:00
|
|
|
/// create an impl like:
|
|
|
|
///
|
2017-06-20 07:15:16 +00:00
|
|
|
/// ```ignore (only-for-syntax-highlight)
|
2023-10-22 19:04:50 +00:00
|
|
|
/// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
|
|
|
|
/// where
|
|
|
|
/// C: WhereTrait,
|
2015-03-24 21:43:26 +00:00
|
|
|
/// A: DerivedTrait + B1 + ... + BN,
|
|
|
|
/// B: DerivedTrait + B1 + ... + BN,
|
|
|
|
/// C: DerivedTrait + B1 + ... + BN,
|
2023-10-22 19:04:50 +00:00
|
|
|
/// B::Item: DerivedTrait + B1 + ... + BN,
|
2015-03-24 21:43:26 +00:00
|
|
|
/// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
|
|
|
|
/// ...
|
|
|
|
/// {
|
|
|
|
/// ...
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and
|
|
|
|
/// therefore does not get bound by the derived trait.
|
2013-12-07 00:57:44 +00:00
|
|
|
fn create_derived_impl(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2014-02-14 16:09:51 +00:00
|
|
|
type_ident: Ident,
|
|
|
|
generics: &Generics,
|
2015-03-24 21:43:26 +00:00
|
|
|
field_tys: Vec<P<ast::Ty>>,
|
2019-12-12 05:41:18 +00:00
|
|
|
methods: Vec<P<ast::AssocItem>>,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed: bool,
|
2016-07-19 17:32:06 +00:00
|
|
|
) -> P<ast::Item> {
|
2013-12-07 00:57:44 +00:00
|
|
|
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2019-12-07 23:08:09 +00:00
|
|
|
// Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
|
2019-12-12 05:41:18 +00:00
|
|
|
let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
|
|
|
|
P(ast::AssocItem {
|
2015-01-25 05:29:24 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: self.span,
|
2017-08-07 05:54:09 +00:00
|
|
|
ident,
|
2020-08-21 23:11:00 +00:00
|
|
|
vis: ast::Visibility {
|
|
|
|
span: self.span.shrink_to_lo(),
|
|
|
|
kind: ast::VisibilityKind::Inherited,
|
|
|
|
tokens: None,
|
|
|
|
},
|
2022-08-17 02:34:33 +00:00
|
|
|
attrs: ast::AttrVec::new(),
|
2022-10-10 02:05:24 +00:00
|
|
|
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
|
2021-11-07 08:43:49 +00:00
|
|
|
defaultness: ast::Defaultness::Final,
|
|
|
|
generics: Generics::default(),
|
2024-02-19 13:25:33 +00:00
|
|
|
where_clauses: ast::TyAliasWhereClauses::default(),
|
2021-11-07 08:43:49 +00:00
|
|
|
bounds: Vec::new(),
|
|
|
|
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
|
|
|
|
})),
|
2017-07-12 16:50:05 +00:00
|
|
|
tokens: None,
|
2019-12-12 05:41:18 +00:00
|
|
|
})
|
|
|
|
});
|
2015-01-25 05:29:24 +00:00
|
|
|
|
2022-11-14 04:43:10 +00:00
|
|
|
let mut where_clause = ast::WhereClause::default();
|
2021-11-03 04:19:06 +00:00
|
|
|
where_clause.span = generics.where_clause.span;
|
2021-11-20 18:46:36 +00:00
|
|
|
let ctxt = self.span.ctxt();
|
|
|
|
let span = generics.span.with_ctxt(ctxt);
|
2014-03-19 12:16:56 +00:00
|
|
|
|
2017-10-16 19:07:26 +00:00
|
|
|
// Create the generic parameters
|
2022-11-21 22:17:20 +00:00
|
|
|
let params: ThinVec<_> = generics
|
2022-11-14 04:43:10 +00:00
|
|
|
.params
|
|
|
|
.iter()
|
|
|
|
.map(|param| match ¶m.kind {
|
|
|
|
GenericParamKind::Lifetime { .. } => param.clone(),
|
|
|
|
GenericParamKind::Type { .. } => {
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
// Extra restrictions on the generics parameters to the
|
|
|
|
// type being derived upon.
|
|
|
|
let bounds: Vec<_> = self
|
|
|
|
.additional_bounds
|
|
|
|
.iter()
|
2023-02-07 20:59:48 +00:00
|
|
|
.map(|p| {
|
|
|
|
cx.trait_bound(
|
|
|
|
p.to_path(cx, self.span, type_ident, generics),
|
|
|
|
self.is_const,
|
|
|
|
)
|
|
|
|
})
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
.chain(
|
|
|
|
// Add a bound for the current trait.
|
|
|
|
self.skip_path_as_bound
|
|
|
|
.not()
|
2023-02-07 20:59:48 +00:00
|
|
|
.then(|| cx.trait_bound(trait_path.clone(), self.is_const)),
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
)
|
|
|
|
.chain({
|
|
|
|
// Add a `Copy` bound if required.
|
|
|
|
if is_packed && self.needs_copy_as_bound_if_packed {
|
|
|
|
let p = deriving::path_std!(marker::Copy);
|
2023-02-07 20:59:48 +00:00
|
|
|
Some(cx.trait_bound(
|
|
|
|
p.to_path(cx, self.span, type_ident, generics),
|
|
|
|
self.is_const,
|
|
|
|
))
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.chain(
|
|
|
|
// Also add in any bounds from the declaration.
|
|
|
|
param.bounds.iter().cloned(),
|
|
|
|
)
|
|
|
|
.collect();
|
2018-05-27 00:43:03 +00:00
|
|
|
|
2022-11-14 04:43:10 +00:00
|
|
|
cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
|
|
|
|
}
|
|
|
|
GenericParamKind::Const { ty, kw_span, .. } => {
|
|
|
|
let const_nodefault_kind = GenericParamKind::Const {
|
|
|
|
ty: ty.clone(),
|
|
|
|
kw_span: kw_span.with_ctxt(ctxt),
|
|
|
|
|
|
|
|
// We can't have default values inside impl block
|
|
|
|
default: None,
|
|
|
|
};
|
|
|
|
let mut param_clone = param.clone();
|
|
|
|
param_clone.kind = const_nodefault_kind;
|
|
|
|
param_clone
|
|
|
|
}
|
|
|
|
})
|
2024-11-05 16:55:34 +00:00
|
|
|
.map(|mut param| {
|
|
|
|
// Remove all attributes, because there might be helper attributes
|
|
|
|
// from other macros that will not be valid in the expanded implementation.
|
|
|
|
param.attrs.clear();
|
|
|
|
param
|
|
|
|
})
|
2022-11-14 04:43:10 +00:00
|
|
|
.collect();
|
2014-12-14 05:35:35 +00:00
|
|
|
|
|
|
|
// and similarly for where clauses
|
|
|
|
where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
|
2024-11-25 08:38:35 +00:00
|
|
|
ast::WherePredicate {
|
2025-02-05 10:58:29 +00:00
|
|
|
attrs: clause.attrs.clone(),
|
2024-11-25 08:38:35 +00:00
|
|
|
kind: clause.kind.clone(),
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: clause.span.with_ctxt(ctxt),
|
2025-02-05 10:58:29 +00:00
|
|
|
is_placeholder: false,
|
2014-12-14 05:35:35 +00:00
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
2023-10-22 19:08:20 +00:00
|
|
|
let ty_param_names: Vec<Symbol> = params
|
2023-10-22 19:05:45 +00:00
|
|
|
.iter()
|
|
|
|
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
2023-10-22 19:08:20 +00:00
|
|
|
.map(|ty_param| ty_param.ident.name)
|
|
|
|
.collect();
|
2023-10-22 19:05:45 +00:00
|
|
|
|
2023-10-22 19:08:20 +00:00
|
|
|
if !ty_param_names.is_empty() {
|
2023-10-22 19:05:45 +00:00
|
|
|
for field_ty in field_tys {
|
|
|
|
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
|
|
|
|
|
|
|
|
for field_ty_param in field_ty_params {
|
|
|
|
// if we have already handled this type, skip it
|
|
|
|
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
|
|
|
|
&& let [sole_segment] = &*p.segments
|
|
|
|
&& ty_param_names.contains(&sole_segment.ident.name)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let mut bounds: Vec<_> = self
|
|
|
|
.additional_bounds
|
|
|
|
.iter()
|
|
|
|
.map(|p| {
|
|
|
|
cx.trait_bound(
|
2023-02-07 20:59:48 +00:00
|
|
|
p.to_path(cx, self.span, type_ident, generics),
|
|
|
|
self.is_const,
|
2023-10-22 19:05:45 +00:00
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect();
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
|
2023-10-22 19:05:45 +00:00
|
|
|
// Require the current trait.
|
|
|
|
if !self.skip_path_as_bound {
|
|
|
|
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
|
|
|
|
}
|
2015-03-24 21:43:26 +00:00
|
|
|
|
2023-10-22 19:05:45 +00:00
|
|
|
// Add a `Copy` bound if required.
|
|
|
|
if is_packed && self.needs_copy_as_bound_if_packed {
|
|
|
|
let p = deriving::path_std!(marker::Copy);
|
|
|
|
bounds.push(cx.trait_bound(
|
|
|
|
p.to_path(cx, self.span, type_ident, generics),
|
|
|
|
self.is_const,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
if !bounds.is_empty() {
|
|
|
|
let predicate = ast::WhereBoundPredicate {
|
|
|
|
bound_generic_params: field_ty_param.bound_generic_params,
|
|
|
|
bounded_ty: field_ty_param.ty,
|
|
|
|
bounds,
|
|
|
|
};
|
|
|
|
|
2024-11-25 08:38:35 +00:00
|
|
|
let kind = ast::WherePredicateKind::BoundPredicate(predicate);
|
2025-02-05 10:58:29 +00:00
|
|
|
let predicate = ast::WherePredicate {
|
|
|
|
attrs: ThinVec::new(),
|
|
|
|
kind,
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: self.span,
|
|
|
|
is_placeholder: false,
|
|
|
|
};
|
2023-10-22 19:05:45 +00:00
|
|
|
where_clause.predicates.push(predicate);
|
2017-10-16 19:07:26 +00:00
|
|
|
}
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-19 12:16:56 +00:00
|
|
|
let trait_generics = Generics { params, where_clause, span };
|
2013-06-07 07:30:38 +00:00
|
|
|
|
|
|
|
// Create the reference to the trait.
|
|
|
|
let trait_ref = cx.trait_ref(trait_path);
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2018-05-27 20:54:10 +00:00
|
|
|
let self_params: Vec<_> = generics
|
|
|
|
.params
|
|
|
|
.iter()
|
|
|
|
.map(|param| match param.kind {
|
2018-05-30 15:49:39 +00:00
|
|
|
GenericParamKind::Lifetime { .. } => {
|
2021-11-20 18:46:36 +00:00
|
|
|
GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident))
|
2018-05-27 20:54:10 +00:00
|
|
|
}
|
|
|
|
GenericParamKind::Type { .. } => {
|
2021-11-20 18:46:36 +00:00
|
|
|
GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
|
2018-05-27 20:54:10 +00:00
|
|
|
}
|
2019-02-05 15:50:00 +00:00
|
|
|
GenericParamKind::Const { .. } => {
|
2021-11-20 18:46:36 +00:00
|
|
|
GenericArg::Const(cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident))
|
2019-02-05 15:50:00 +00:00
|
|
|
}
|
2018-05-27 20:54:10 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2018-02-08 08:58:13 +00:00
|
|
|
|
2013-06-07 07:30:38 +00:00
|
|
|
// Create the type of `self`.
|
2019-09-21 19:01:10 +00:00
|
|
|
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
2018-05-27 20:54:10 +00:00
|
|
|
let self_type = cx.ty_path(path);
|
2016-07-19 17:32:06 +00:00
|
|
|
|
2023-02-16 17:17:55 +00:00
|
|
|
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
2014-02-14 05:07:09 +00:00
|
|
|
let opt_trait_ref = Some(trait_ref);
|
2020-05-07 05:23:44 +00:00
|
|
|
|
2016-07-19 17:32:06 +00:00
|
|
|
cx.item(
|
|
|
|
self.span,
|
2021-10-17 20:20:30 +00:00
|
|
|
Ident::empty(),
|
2022-08-17 02:20:25 +00:00
|
|
|
attrs,
|
2021-11-07 08:43:49 +00:00
|
|
|
ast::ItemKind::Impl(Box::new(ast::Impl {
|
2024-05-17 17:17:48 +00:00
|
|
|
safety: ast::Safety::Default,
|
2020-01-14 04:30:20 +00:00
|
|
|
polarity: ast::ImplPolarity::Positive,
|
|
|
|
defaultness: ast::Defaultness::Final,
|
2022-09-20 11:55:07 +00:00
|
|
|
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
|
2020-01-14 04:30:20 +00:00
|
|
|
generics: trait_generics,
|
|
|
|
of_trait: opt_trait_ref,
|
|
|
|
self_ty: self_type,
|
|
|
|
items: methods.into_iter().chain(associated_types).collect(),
|
2021-08-05 01:53:21 +00:00
|
|
|
})),
|
2016-07-19 17:32:06 +00:00
|
|
|
)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-02-22 05:33:23 +00:00
|
|
|
fn expand_struct_def(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2015-10-08 00:20:57 +00:00
|
|
|
struct_def: &'a VariantData,
|
2014-02-22 05:33:23 +00:00
|
|
|
type_ident: Ident,
|
2016-08-26 16:23:42 +00:00
|
|
|
generics: &Generics,
|
2017-10-02 13:15:23 +00:00
|
|
|
from_scratch: bool,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed: bool,
|
2016-07-19 17:32:06 +00:00
|
|
|
) -> P<ast::Item> {
|
|
|
|
let field_tys: Vec<P<ast::Ty>> =
|
2016-04-06 08:19:10 +00:00
|
|
|
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
|
2019-12-22 22:42:04 +00:00
|
|
|
|
2016-07-19 17:32:06 +00:00
|
|
|
let methods = self
|
|
|
|
.methods
|
|
|
|
.iter()
|
|
|
|
.map(|method_def| {
|
2022-07-04 22:25:47 +00:00
|
|
|
let (explicit_self, selflike_args, nonselflike_args, nonself_arg_tys) =
|
|
|
|
method_def.extract_arg_details(cx, self, type_ident, generics);
|
2016-07-19 17:32:06 +00:00
|
|
|
|
2016-08-26 16:23:42 +00:00
|
|
|
let body = if from_scratch || method_def.is_static() {
|
2016-07-19 17:32:06 +00:00
|
|
|
method_def.expand_static_struct_method_body(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
struct_def,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
&nonselflike_args,
|
2016-07-19 17:32:06 +00:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
method_def.expand_struct_method_body(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
struct_def,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
&selflike_args,
|
|
|
|
&nonselflike_args,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed,
|
2017-10-02 13:15:23 +00:00
|
|
|
)
|
2016-07-19 17:32:06 +00:00
|
|
|
};
|
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
method_def.create_method(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
type_ident,
|
|
|
|
generics,
|
|
|
|
explicit_self,
|
|
|
|
nonself_arg_tys,
|
|
|
|
body,
|
|
|
|
)
|
2016-07-19 17:32:06 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2013-03-28 10:50:10 +00:00
|
|
|
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-02-22 05:33:23 +00:00
|
|
|
fn expand_enum_def(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2015-05-01 01:10:06 +00:00
|
|
|
enum_def: &'a EnumDef,
|
2013-09-02 00:50:59 +00:00
|
|
|
type_ident: Ident,
|
2016-08-26 16:23:42 +00:00
|
|
|
generics: &Generics,
|
|
|
|
from_scratch: bool,
|
2016-07-19 17:32:06 +00:00
|
|
|
) -> P<ast::Item> {
|
2015-03-24 21:43:26 +00:00
|
|
|
let mut field_tys = Vec::new();
|
|
|
|
|
2015-06-10 16:22:20 +00:00
|
|
|
for variant in &enum_def.variants {
|
2016-04-06 08:19:10 +00:00
|
|
|
field_tys.extend(variant.data.fields().iter().map(|field| field.ty.clone()));
|
2015-03-24 21:43:26 +00:00
|
|
|
}
|
|
|
|
|
2016-07-19 17:32:06 +00:00
|
|
|
let methods = self
|
|
|
|
.methods
|
|
|
|
.iter()
|
|
|
|
.map(|method_def| {
|
2022-07-04 22:25:47 +00:00
|
|
|
let (explicit_self, selflike_args, nonselflike_args, nonself_arg_tys) =
|
|
|
|
method_def.extract_arg_details(cx, self, type_ident, generics);
|
2016-07-19 17:32:06 +00:00
|
|
|
|
2016-08-26 16:23:42 +00:00
|
|
|
let body = if from_scratch || method_def.is_static() {
|
2016-07-19 17:32:06 +00:00
|
|
|
method_def.expand_static_enum_method_body(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
enum_def,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
&nonselflike_args,
|
2016-07-19 17:32:06 +00:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
method_def.expand_enum_method_body(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
enum_def,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
selflike_args,
|
|
|
|
&nonselflike_args,
|
2016-07-19 17:32:06 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
method_def.create_method(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
type_ident,
|
|
|
|
generics,
|
|
|
|
explicit_self,
|
|
|
|
nonself_arg_tys,
|
|
|
|
body,
|
|
|
|
)
|
2016-07-19 17:32:06 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2013-03-28 10:50:10 +00:00
|
|
|
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
let is_packed = false; // enums are never packed
|
|
|
|
self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-10 07:16:18 +00:00
|
|
|
impl<'a> MethodDef<'a> {
|
2013-03-28 10:50:10 +00:00
|
|
|
fn call_substructure_method(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2013-09-02 00:50:59 +00:00
|
|
|
type_ident: Ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args: &[P<Expr>],
|
2019-02-04 12:49:54 +00:00
|
|
|
fields: &SubstructureFields<'_>,
|
2022-06-28 03:10:36 +00:00
|
|
|
) -> BlockOrExpr {
|
2021-11-20 18:46:36 +00:00
|
|
|
let span = trait_.span;
|
2022-07-04 22:25:47 +00:00
|
|
|
let substructure = Substructure { type_ident, nonselflike_args, fields };
|
2014-04-22 06:25:18 +00:00
|
|
|
let mut f = self.combine_substructure.borrow_mut();
|
2019-02-04 12:49:54 +00:00
|
|
|
let f: &mut CombineSubstructureFunc<'_> = &mut *f;
|
2021-11-20 18:46:36 +00:00
|
|
|
f(cx, span, &substructure)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-02-09 00:39:53 +00:00
|
|
|
fn get_ret_ty(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2014-02-09 00:39:53 +00:00
|
|
|
generics: &Generics,
|
|
|
|
type_ident: Ident,
|
|
|
|
) -> P<ast::Ty> {
|
|
|
|
self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
|
2013-05-06 15:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_static(&self) -> bool {
|
2022-06-29 23:15:07 +00:00
|
|
|
!self.explicit_self
|
2013-05-06 15:23:51 +00:00
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
// The return value includes:
|
|
|
|
// - explicit_self: The `&self` arg, if present.
|
|
|
|
// - selflike_args: Expressions for `&self` (if present) and also any other
|
|
|
|
// args with the same type (e.g. the `other` arg in `PartialEq::eq`).
|
|
|
|
// - nonselflike_args: Expressions for all the remaining args.
|
|
|
|
// - nonself_arg_tys: Additional information about all the args other than
|
|
|
|
// `&self`.
|
|
|
|
fn extract_arg_details(
|
2016-07-19 17:32:06 +00:00
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2016-07-19 17:32:06 +00:00
|
|
|
type_ident: Ident,
|
|
|
|
generics: &Generics,
|
2022-11-23 00:55:16 +00:00
|
|
|
) -> (Option<ast::ExplicitSelf>, ThinVec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
|
|
|
|
let mut selflike_args = ThinVec::new();
|
2022-07-04 22:25:47 +00:00
|
|
|
let mut nonselflike_args = Vec::new();
|
|
|
|
let mut nonself_arg_tys = Vec::new();
|
2021-11-20 18:46:36 +00:00
|
|
|
let span = trait_.span;
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2023-02-15 11:43:41 +00:00
|
|
|
let explicit_self = self.explicit_self.then(|| {
|
2022-06-29 23:15:07 +00:00
|
|
|
let (self_expr, explicit_self) = ty::get_explicit_self(cx, span);
|
2022-07-04 22:25:47 +00:00
|
|
|
selflike_args.push(self_expr);
|
2023-02-15 11:43:41 +00:00
|
|
|
explicit_self
|
|
|
|
});
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
for (ty, name) in self.nonself_args.iter() {
|
2021-11-20 18:46:36 +00:00
|
|
|
let ast_ty = ty.to_ty(cx, span, type_ident, generics);
|
|
|
|
let ident = Ident::new(*name, span);
|
2022-07-04 22:25:47 +00:00
|
|
|
nonself_arg_tys.push((ident, ast_ty));
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2021-11-20 18:46:36 +00:00
|
|
|
let arg_expr = cx.expr_ident(span, ident);
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2022-07-07 21:57:34 +00:00
|
|
|
match ty {
|
|
|
|
// Selflike (`&Self`) arguments only occur in non-static methods.
|
2022-07-06 06:13:51 +00:00
|
|
|
Ref(box Self_, _) if !self.is_static() => selflike_args.push(arg_expr),
|
2023-12-18 09:54:03 +00:00
|
|
|
Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"),
|
2022-07-04 22:25:47 +00:00
|
|
|
_ => nonselflike_args.push(arg_expr),
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2022-07-04 22:25:47 +00:00
|
|
|
(explicit_self, selflike_args, nonselflike_args, nonself_arg_tys)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-02-09 00:39:53 +00:00
|
|
|
fn create_method(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2013-09-02 00:50:59 +00:00
|
|
|
type_ident: Ident,
|
2013-05-06 15:23:51 +00:00
|
|
|
generics: &Generics,
|
2016-03-06 12:54:44 +00:00
|
|
|
explicit_self: Option<ast::ExplicitSelf>,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonself_arg_tys: Vec<(Ident, P<ast::Ty>)>,
|
2022-06-28 03:10:36 +00:00
|
|
|
body: BlockOrExpr,
|
2019-12-12 05:41:18 +00:00
|
|
|
) -> P<ast::AssocItem> {
|
2021-11-20 18:46:36 +00:00
|
|
|
let span = trait_.span;
|
2019-02-28 22:43:53 +00:00
|
|
|
// Create the generics that aren't for `Self`.
|
2021-11-20 18:46:36 +00:00
|
|
|
let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2014-02-09 12:37:33 +00:00
|
|
|
let args = {
|
2022-07-04 22:25:47 +00:00
|
|
|
let self_arg = explicit_self.map(|explicit_self| {
|
2021-11-20 18:46:36 +00:00
|
|
|
let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(span);
|
2019-12-03 15:38:34 +00:00
|
|
|
ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident)
|
2016-03-06 12:54:44 +00:00
|
|
|
});
|
2022-07-04 22:25:47 +00:00
|
|
|
let nonself_args =
|
|
|
|
nonself_arg_tys.into_iter().map(|(name, ty)| cx.param(span, name, ty));
|
|
|
|
self_arg.into_iter().chain(nonself_args).collect()
|
2014-02-09 12:37:33 +00:00
|
|
|
};
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2014-02-09 00:39:53 +00:00
|
|
|
let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2021-11-20 18:46:36 +00:00
|
|
|
let method_ident = Ident::new(self.name, span);
|
2020-02-15 03:10:59 +00:00
|
|
|
let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type));
|
2022-06-28 03:10:36 +00:00
|
|
|
let body_block = body.into_block(cx, span);
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2021-11-20 18:46:36 +00:00
|
|
|
let trait_lo_sp = span.shrink_to_lo();
|
2019-10-27 22:14:35 +00:00
|
|
|
|
2022-06-28 01:44:37 +00:00
|
|
|
let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span };
|
2021-11-07 08:43:49 +00:00
|
|
|
let defaultness = ast::Defaultness::Final;
|
2019-10-27 22:14:35 +00:00
|
|
|
|
2013-03-28 10:50:10 +00:00
|
|
|
// Create the method.
|
2019-12-12 05:41:18 +00:00
|
|
|
P(ast::AssocItem {
|
2013-09-07 02:11:55 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2015-03-10 10:28:44 +00:00
|
|
|
attrs: self.attributes.clone(),
|
2021-11-20 18:46:36 +00:00
|
|
|
span,
|
2020-08-21 23:11:00 +00:00
|
|
|
vis: ast::Visibility {
|
|
|
|
span: trait_lo_sp,
|
|
|
|
kind: ast::VisibilityKind::Inherited,
|
|
|
|
tokens: None,
|
|
|
|
},
|
2015-03-10 10:28:44 +00:00
|
|
|
ident: method_ident,
|
2021-11-07 08:43:49 +00:00
|
|
|
kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
|
|
|
|
defaultness,
|
2021-08-05 01:53:21 +00:00
|
|
|
sig,
|
2021-11-07 08:43:49 +00:00
|
|
|
generics: fn_generics,
|
2025-01-09 00:38:25 +00:00
|
|
|
contract: None,
|
2021-11-07 08:43:49 +00:00
|
|
|
body: Some(body_block),
|
|
|
|
})),
|
2017-07-12 16:50:05 +00:00
|
|
|
tokens: None,
|
2019-12-12 05:41:18 +00:00
|
|
|
})
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
/// The normal case uses field access.
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
2017-06-20 07:15:16 +00:00
|
|
|
/// ```
|
2014-12-31 04:25:18 +00:00
|
|
|
/// #[derive(PartialEq)]
|
2017-06-20 07:15:16 +00:00
|
|
|
/// # struct Dummy;
|
2022-07-07 01:09:07 +00:00
|
|
|
/// struct A { x: u8, y: u8 }
|
2014-09-16 11:27:34 +00:00
|
|
|
///
|
|
|
|
/// // equivalent to:
|
|
|
|
/// impl PartialEq for A {
|
2018-04-19 19:17:06 +00:00
|
|
|
/// fn eq(&self, other: &A) -> bool {
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
/// self.x == other.x && self.y == other.y
|
2014-09-16 11:27:34 +00:00
|
|
|
/// }
|
|
|
|
/// }
|
2022-04-15 22:04:34 +00:00
|
|
|
/// ```
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
/// But if the struct is `repr(packed)`, we can't use something like
|
2022-07-11 02:54:52 +00:00
|
|
|
/// `&self.x` because that might cause an unaligned ref. So for any trait
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
/// method that takes a reference, we use a local block to force a copy.
|
|
|
|
/// This requires that the field impl `Copy`.
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
2023-05-06 21:12:29 +00:00
|
|
|
/// ```rust,ignore (example)
|
2022-07-07 01:09:07 +00:00
|
|
|
/// # struct A { x: u8, y: u8 }
|
2017-10-02 13:15:23 +00:00
|
|
|
/// impl PartialEq for A {
|
2018-04-19 19:17:06 +00:00
|
|
|
/// fn eq(&self, other: &A) -> bool {
|
2022-07-11 02:54:52 +00:00
|
|
|
/// // Desugars to `{ self.x }.eq(&{ other.y }) && ...`
|
|
|
|
/// { self.x } == { other.y } && { self.y } == { other.y }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// impl Hash for A {
|
|
|
|
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
|
|
|
/// ::core::hash::Hash::hash(&{ self.x }, state);
|
2023-10-22 19:04:50 +00:00
|
|
|
/// ::core::hash::Hash::hash(&{ self.y }, state);
|
2017-10-02 13:15:23 +00:00
|
|
|
/// }
|
|
|
|
/// }
|
2023-03-04 03:25:36 +00:00
|
|
|
/// ```
|
2015-05-01 01:10:06 +00:00
|
|
|
fn expand_struct_method_body<'b>(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2016-07-19 17:32:06 +00:00
|
|
|
trait_: &TraitDef<'b>,
|
|
|
|
struct_def: &'b VariantData,
|
|
|
|
type_ident: Ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
selflike_args: &[P<Expr>],
|
|
|
|
nonselflike_args: &[P<Expr>],
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed: bool,
|
2022-06-28 03:10:36 +00:00
|
|
|
) -> BlockOrExpr {
|
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-04 23:04:41 +00:00
|
|
|
assert!(selflike_args.len() == 1 || selflike_args.len() == 2);
|
|
|
|
|
2022-11-21 00:48:25 +00:00
|
|
|
let selflike_fields =
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, is_packed);
|
2022-11-21 00:48:25 +00:00
|
|
|
self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
|
|
|
&Struct(struct_def, selflike_fields),
|
|
|
|
)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2013-05-06 15:23:51 +00:00
|
|
|
fn expand_static_struct_method_body(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2015-10-08 00:20:57 +00:00
|
|
|
struct_def: &VariantData,
|
2013-09-02 00:50:59 +00:00
|
|
|
type_ident: Ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args: &[P<Expr>],
|
2022-06-28 03:10:36 +00:00
|
|
|
) -> BlockOrExpr {
|
2014-02-09 00:39:53 +00:00
|
|
|
let summary = trait_.summarise_struct(cx, struct_def);
|
2013-03-28 10:50:10 +00:00
|
|
|
|
2014-02-09 00:39:53 +00:00
|
|
|
self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
2013-05-06 15:23:51 +00:00
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args,
|
2013-05-06 15:23:51 +00:00
|
|
|
&StaticStruct(struct_def, summary),
|
|
|
|
)
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2017-06-20 07:15:16 +00:00
|
|
|
/// ```
|
2014-12-31 04:25:18 +00:00
|
|
|
/// #[derive(PartialEq)]
|
2017-06-20 07:15:16 +00:00
|
|
|
/// # struct Dummy;
|
2014-09-16 11:27:34 +00:00
|
|
|
/// enum A {
|
|
|
|
/// A1,
|
2015-01-17 23:55:21 +00:00
|
|
|
/// A2(i32)
|
2014-09-16 11:27:34 +00:00
|
|
|
/// }
|
2022-06-22 05:26:47 +00:00
|
|
|
/// ```
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
2022-06-22 05:26:47 +00:00
|
|
|
/// is equivalent to:
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
2022-06-22 05:26:47 +00:00
|
|
|
/// ```
|
2022-09-16 11:10:25 +00:00
|
|
|
/// #![feature(core_intrinsics)]
|
|
|
|
/// enum A {
|
|
|
|
/// A1,
|
|
|
|
/// A2(i32)
|
|
|
|
/// }
|
2022-06-22 05:26:47 +00:00
|
|
|
/// impl ::core::cmp::PartialEq for A {
|
|
|
|
/// #[inline]
|
2022-04-15 22:04:34 +00:00
|
|
|
/// fn eq(&self, other: &A) -> bool {
|
2024-04-14 09:31:51 +00:00
|
|
|
/// let __self_discr = ::core::intrinsics::discriminant_value(self);
|
|
|
|
/// let __arg1_discr = ::core::intrinsics::discriminant_value(other);
|
|
|
|
/// __self_discr == __arg1_discr
|
2023-10-22 19:04:50 +00:00
|
|
|
/// && match (self, other) {
|
|
|
|
/// (A::A2(__self_0), A::A2(__arg1_0)) => *__self_0 == *__arg1_0,
|
2022-07-06 06:13:51 +00:00
|
|
|
/// _ => true,
|
2014-09-16 11:27:34 +00:00
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2023-10-22 19:04:50 +00:00
|
|
|
///
|
2024-04-14 09:31:51 +00:00
|
|
|
/// Creates a discriminant check combined with a match for a tuple of all
|
2022-07-08 05:32:27 +00:00
|
|
|
/// `selflike_args`, with an arm for each variant with fields, possibly an
|
2023-01-14 21:16:25 +00:00
|
|
|
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
|
|
|
|
/// `Unify`), and possibly a default arm.
|
2022-06-22 05:26:47 +00:00
|
|
|
fn expand_enum_method_body<'b>(
|
2016-07-19 17:32:06 +00:00
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2016-07-19 17:32:06 +00:00
|
|
|
trait_: &TraitDef<'b>,
|
|
|
|
enum_def: &'b EnumDef,
|
|
|
|
type_ident: Ident,
|
2023-07-16 21:35:16 +00:00
|
|
|
mut selflike_args: ThinVec<P<Expr>>,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args: &[P<Expr>],
|
2022-06-28 03:10:36 +00:00
|
|
|
) -> BlockOrExpr {
|
2023-07-16 21:35:16 +00:00
|
|
|
assert!(
|
|
|
|
!selflike_args.is_empty(),
|
|
|
|
"static methods must use `expand_static_enum_method_body`",
|
|
|
|
);
|
|
|
|
|
2021-11-20 18:46:36 +00:00
|
|
|
let span = trait_.span;
|
2014-07-06 19:19:12 +00:00
|
|
|
let variants = &enum_def.variants;
|
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
// Traits that unify fieldless variants always use the discriminant(s).
|
2023-01-14 21:16:25 +00:00
|
|
|
let unify_fieldless_variants =
|
|
|
|
self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
|
2022-07-08 05:32:27 +00:00
|
|
|
|
2023-07-16 22:33:29 +00:00
|
|
|
// For zero-variant enum, this function body is unreachable. Generate
|
|
|
|
// `match *self {}`. This produces machine code identical to `unsafe {
|
|
|
|
// core::intrinsics::unreachable() }` while being safe and stable.
|
2022-07-08 05:31:09 +00:00
|
|
|
if variants.is_empty() {
|
2023-07-16 21:35:16 +00:00
|
|
|
selflike_args.truncate(1);
|
|
|
|
let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap());
|
|
|
|
let match_arms = ThinVec::new();
|
|
|
|
let expr = cx.expr_match(span, match_arg, match_arms);
|
|
|
|
return BlockOrExpr(ThinVec::new(), Some(expr));
|
2022-07-08 05:31:09 +00:00
|
|
|
}
|
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
let prefixes = iter::once("__self".to_string())
|
2018-11-05 14:30:04 +00:00
|
|
|
.chain(
|
2022-07-04 22:25:47 +00:00
|
|
|
selflike_args
|
2018-11-05 14:30:04 +00:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.skip(1)
|
2023-07-25 20:00:13 +00:00
|
|
|
.map(|(arg_count, _selflike_arg)| format!("__arg{arg_count}")),
|
2018-11-05 14:30:04 +00:00
|
|
|
)
|
|
|
|
.collect::<Vec<String>>();
|
2019-12-22 22:42:04 +00:00
|
|
|
|
2022-07-08 05:32:27 +00:00
|
|
|
// Build a series of let statements mapping each selflike_arg
|
|
|
|
// to its discriminant value.
|
|
|
|
//
|
|
|
|
// e.g. for `PartialEq::eq` builds two statements:
|
|
|
|
// ```
|
2024-04-14 09:31:51 +00:00
|
|
|
// let __self_discr = ::core::intrinsics::discriminant_value(self);
|
|
|
|
// let __arg1_discr = ::core::intrinsics::discriminant_value(other);
|
2022-07-08 05:32:27 +00:00
|
|
|
// ```
|
2024-04-14 09:31:51 +00:00
|
|
|
let get_discr_pieces = |cx: &ExtCtxt<'_>| {
|
|
|
|
let discr_idents: Vec<_> = prefixes
|
2022-07-08 05:32:27 +00:00
|
|
|
.iter()
|
2024-04-14 09:31:51 +00:00
|
|
|
.map(|name| Ident::from_str_and_span(&format!("{name}_discr"), span))
|
2022-07-08 05:32:27 +00:00
|
|
|
.collect();
|
2014-07-06 19:19:12 +00:00
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
let mut discr_exprs: Vec<_> = discr_idents
|
2022-07-08 05:32:27 +00:00
|
|
|
.iter()
|
|
|
|
.map(|&ident| cx.expr_addr_of(span, cx.expr_ident(span, ident)))
|
|
|
|
.collect();
|
2014-07-06 19:19:12 +00:00
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
let self_expr = discr_exprs.remove(0);
|
|
|
|
let other_selflike_exprs = discr_exprs;
|
|
|
|
let discr_field = FieldInfo { span, name: None, self_expr, other_selflike_exprs };
|
2022-07-08 05:32:27 +00:00
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
let discr_let_stmts: ThinVec<_> = iter::zip(&discr_idents, &selflike_args)
|
2022-07-08 05:32:27 +00:00
|
|
|
.map(|(&ident, selflike_arg)| {
|
|
|
|
let variant_value = deriving::call_intrinsic(
|
|
|
|
cx,
|
|
|
|
span,
|
|
|
|
sym::discriminant_value,
|
2022-11-23 00:55:16 +00:00
|
|
|
thin_vec![selflike_arg.clone()],
|
2022-07-08 05:32:27 +00:00
|
|
|
);
|
|
|
|
cx.stmt_let(span, false, ident, variant_value)
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
(discr_field, discr_let_stmts)
|
2022-07-08 05:32:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// There are some special cases involving fieldless enums where no
|
|
|
|
// match is necessary.
|
|
|
|
let all_fieldless = variants.iter().all(|v| v.data.fields().is_empty());
|
|
|
|
if all_fieldless {
|
2023-01-14 21:16:25 +00:00
|
|
|
if variants.len() > 1 {
|
|
|
|
match self.fieldless_variants_strategy {
|
|
|
|
FieldlessVariantsStrategy::Unify => {
|
2024-04-14 09:31:51 +00:00
|
|
|
// If the type is fieldless and the trait uses the discriminant and
|
2023-01-14 21:16:25 +00:00
|
|
|
// there are multiple variants, we need just an operation on
|
2024-04-14 09:31:51 +00:00
|
|
|
// the discriminant(s).
|
|
|
|
let (discr_field, mut discr_let_stmts) = get_discr_pieces(cx);
|
|
|
|
let mut discr_check = self.call_substructure_method(
|
2023-01-14 21:16:25 +00:00
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
2024-04-14 09:31:51 +00:00
|
|
|
&EnumDiscr(discr_field, None),
|
2023-01-14 21:16:25 +00:00
|
|
|
);
|
2024-04-14 09:31:51 +00:00
|
|
|
discr_let_stmts.append(&mut discr_check.0);
|
|
|
|
return BlockOrExpr(discr_let_stmts, discr_check.1);
|
2023-01-14 21:16:25 +00:00
|
|
|
}
|
|
|
|
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => {
|
|
|
|
return self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
|
|
|
&AllFieldlessEnum(enum_def),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
FieldlessVariantsStrategy::Default => (),
|
|
|
|
}
|
2024-08-07 10:41:49 +00:00
|
|
|
} else if let [variant] = variants.as_slice() {
|
2022-07-08 05:32:27 +00:00
|
|
|
// If there is a single variant, we don't need an operation on
|
2024-04-14 09:31:51 +00:00
|
|
|
// the discriminant(s). Just use the most degenerate result.
|
2022-07-08 05:32:27 +00:00
|
|
|
return self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
2025-01-07 17:28:42 +00:00
|
|
|
&EnumMatching(variant, Vec::new()),
|
2022-07-08 05:32:27 +00:00
|
|
|
);
|
2023-01-14 21:16:25 +00:00
|
|
|
}
|
2022-07-08 05:32:27 +00:00
|
|
|
}
|
2016-05-12 15:54:05 +00:00
|
|
|
|
2014-07-06 19:19:12 +00:00
|
|
|
// These arms are of the form:
|
|
|
|
// (Variant1, Variant1, ...) => Body1
|
|
|
|
// (Variant2, Variant2, ...) => Body2
|
|
|
|
// ...
|
2022-07-04 22:25:47 +00:00
|
|
|
// where each tuple has length = selflike_args.len()
|
2023-01-30 04:10:59 +00:00
|
|
|
let mut match_arms: ThinVec<ast::Arm> = variants
|
2016-07-19 17:32:06 +00:00
|
|
|
.iter()
|
2025-01-07 17:28:42 +00:00
|
|
|
.filter(|&v| !(unify_fieldless_variants && v.data.fields().is_empty()))
|
|
|
|
.map(|variant| {
|
2014-07-06 19:19:12 +00:00
|
|
|
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
|
|
|
|
// (see "Final wrinkle" note below for why.)
|
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-04 23:04:41 +00:00
|
|
|
|
2022-11-14 02:59:54 +00:00
|
|
|
let fields = trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes);
|
2022-07-06 06:13:51 +00:00
|
|
|
|
|
|
|
let sp = variant.span.with_ctxt(trait_.span.ctxt());
|
|
|
|
let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
|
2022-08-30 22:34:35 +00:00
|
|
|
let by_ref = ByRef::No; // because enums can't be repr(packed)
|
2022-11-23 00:55:16 +00:00
|
|
|
let mut subpats = trait_.create_struct_patterns(
|
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-04 23:04:41 +00:00
|
|
|
cx,
|
2022-07-06 06:13:51 +00:00
|
|
|
variant_path,
|
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-04 23:04:41 +00:00
|
|
|
&variant.data,
|
|
|
|
&prefixes,
|
2022-08-30 22:34:35 +00:00
|
|
|
by_ref,
|
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-04 23:04:41 +00:00
|
|
|
);
|
|
|
|
|
2022-07-08 05:32:27 +00:00
|
|
|
// `(VariantK, VariantK, ...)` or just `VariantK`.
|
2022-07-04 05:08:28 +00:00
|
|
|
let single_pat = if subpats.len() == 1 {
|
|
|
|
subpats.pop().unwrap()
|
|
|
|
} else {
|
|
|
|
cx.pat_tuple(span, subpats)
|
|
|
|
};
|
2014-07-06 19:19:12 +00:00
|
|
|
|
|
|
|
// For the BodyK, we need to delegate to our caller,
|
|
|
|
// passing it an EnumMatching to indicate which case
|
|
|
|
// we are in.
|
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-04 23:04:41 +00:00
|
|
|
//
|
2014-07-06 19:19:12 +00:00
|
|
|
// Now, for some given VariantK, we have built up
|
|
|
|
// expressions for referencing every field of every
|
|
|
|
// Self arg, assuming all are instances of VariantK.
|
|
|
|
// Build up code associated with such a case.
|
2025-01-07 17:28:42 +00:00
|
|
|
let substructure = EnumMatching(variant, fields);
|
2022-06-28 03:10:36 +00:00
|
|
|
let arm_expr = self
|
2022-07-04 22:25:47 +00:00
|
|
|
.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
|
|
|
&substructure,
|
|
|
|
)
|
2022-06-28 03:10:36 +00:00
|
|
|
.into_expr(cx, span);
|
2014-07-06 19:19:12 +00:00
|
|
|
|
2021-11-20 18:46:36 +00:00
|
|
|
cx.arm(span, single_pat, arm_expr)
|
2016-07-19 17:32:06 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2016-05-12 15:54:05 +00:00
|
|
|
|
2022-07-08 05:32:27 +00:00
|
|
|
// Add a default arm to the match, if necessary.
|
|
|
|
let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
|
2016-05-12 15:54:05 +00:00
|
|
|
let default = match first_fieldless {
|
2023-01-14 21:16:25 +00:00
|
|
|
Some(v) if unify_fieldless_variants => {
|
2022-07-08 05:32:27 +00:00
|
|
|
// We need a default case that handles all the fieldless
|
|
|
|
// variants. The index and actual variant aren't meaningful in
|
|
|
|
// this case, so just use dummy values.
|
2022-06-28 03:10:36 +00:00
|
|
|
Some(
|
|
|
|
self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args,
|
2025-01-07 17:28:42 +00:00
|
|
|
&EnumMatching(v, Vec::new()),
|
2022-06-28 03:10:36 +00:00
|
|
|
)
|
|
|
|
.into_expr(cx, span),
|
|
|
|
)
|
2016-05-12 15:54:05 +00:00
|
|
|
}
|
2022-07-04 22:25:47 +00:00
|
|
|
_ if variants.len() > 1 && selflike_args.len() > 1 => {
|
2022-07-08 05:32:27 +00:00
|
|
|
// Because we know that all the arguments will match if we reach
|
2016-05-12 15:54:05 +00:00
|
|
|
// the match expression we add the unreachable intrinsics as the
|
2022-07-08 05:32:27 +00:00
|
|
|
// result of the default which should help llvm in optimizing it.
|
2021-11-20 18:46:36 +00:00
|
|
|
Some(deriving::call_unreachable(cx, span))
|
2016-05-12 15:54:05 +00:00
|
|
|
}
|
2016-07-19 17:32:06 +00:00
|
|
|
_ => None,
|
2016-05-12 15:54:05 +00:00
|
|
|
};
|
|
|
|
if let Some(arm) = default {
|
2021-11-20 18:46:36 +00:00
|
|
|
match_arms.push(cx.arm(span, cx.pat_wild(span), arm));
|
2016-05-12 15:54:05 +00:00
|
|
|
}
|
|
|
|
|
2022-07-08 05:32:27 +00:00
|
|
|
// Create a match expression with one arm per discriminant plus
|
|
|
|
// possibly a default arm, e.g.:
|
|
|
|
// match (self, other) {
|
|
|
|
// (Variant1, Variant1, ...) => Body1
|
|
|
|
// (Variant2, Variant2, ...) => Body2,
|
|
|
|
// ...
|
2023-10-22 19:04:50 +00:00
|
|
|
// _ => ::core::intrinsics::unreachable(),
|
2022-07-08 05:32:27 +00:00
|
|
|
// }
|
2022-11-23 00:55:16 +00:00
|
|
|
let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
|
2022-07-04 22:25:47 +00:00
|
|
|
let match_arg = if selflike_args.len() == 1 {
|
|
|
|
selflike_args.pop().unwrap()
|
2022-07-04 05:08:28 +00:00
|
|
|
} else {
|
2022-07-04 22:25:47 +00:00
|
|
|
cx.expr(span, ast::ExprKind::Tup(selflike_args))
|
2022-07-04 05:08:28 +00:00
|
|
|
};
|
2022-07-08 05:32:27 +00:00
|
|
|
cx.expr_match(span, match_arg, match_arms)
|
|
|
|
};
|
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
// If the trait uses the discriminant and there are multiple variants, we need
|
|
|
|
// to add a discriminant check operation before the match. Otherwise, the match
|
2022-07-08 05:32:27 +00:00
|
|
|
// is enough.
|
2023-01-14 21:16:25 +00:00
|
|
|
if unify_fieldless_variants && variants.len() > 1 {
|
2024-04-14 09:31:51 +00:00
|
|
|
let (discr_field, mut discr_let_stmts) = get_discr_pieces(cx);
|
2022-07-08 05:32:27 +00:00
|
|
|
|
2024-04-14 09:31:51 +00:00
|
|
|
// Combine a discriminant check with the match.
|
|
|
|
let mut discr_check_plus_match = self.call_substructure_method(
|
2022-07-08 05:32:27 +00:00
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
|
|
|
nonselflike_args,
|
2024-04-14 09:31:51 +00:00
|
|
|
&EnumDiscr(discr_field, Some(get_match_expr(selflike_args))),
|
2022-07-08 05:32:27 +00:00
|
|
|
);
|
2024-04-14 09:31:51 +00:00
|
|
|
discr_let_stmts.append(&mut discr_check_plus_match.0);
|
|
|
|
BlockOrExpr(discr_let_stmts, discr_check_plus_match.1)
|
2022-07-08 05:32:27 +00:00
|
|
|
} else {
|
2023-01-30 03:13:27 +00:00
|
|
|
BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args)))
|
2014-07-06 19:19:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-06 15:23:51 +00:00
|
|
|
fn expand_static_enum_method_body(
|
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2019-02-04 12:49:54 +00:00
|
|
|
trait_: &TraitDef<'_>,
|
2014-01-09 13:05:33 +00:00
|
|
|
enum_def: &EnumDef,
|
2013-11-07 07:49:01 +00:00
|
|
|
type_ident: Ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args: &[P<Expr>],
|
2022-06-28 03:10:36 +00:00
|
|
|
) -> BlockOrExpr {
|
2016-07-19 17:32:06 +00:00
|
|
|
self.call_substructure_method(
|
|
|
|
cx,
|
|
|
|
trait_,
|
|
|
|
type_ident,
|
2022-07-04 22:25:47 +00:00
|
|
|
nonselflike_args,
|
2025-01-07 17:28:42 +00:00
|
|
|
&StaticEnum(enum_def),
|
2013-05-06 15:23:51 +00:00
|
|
|
)
|
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
2013-12-07 00:57:44 +00:00
|
|
|
// general helper methods.
|
|
|
|
impl<'a> TraitDef<'a> {
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
|
2014-02-28 21:09:09 +00:00
|
|
|
let mut named_idents = Vec::new();
|
|
|
|
let mut just_spans = Vec::new();
|
2016-07-19 17:32:06 +00:00
|
|
|
for field in struct_def.fields() {
|
2017-07-31 20:04:34 +00:00
|
|
|
let sp = field.span.with_ctxt(self.span.ctxt());
|
2016-04-06 08:19:10 +00:00
|
|
|
match field.ident {
|
2024-08-24 17:22:48 +00:00
|
|
|
Some(ident) => named_idents.push((ident, sp, field.default.clone())),
|
2016-04-02 13:47:53 +00:00
|
|
|
_ => just_spans.push(sp),
|
2013-12-07 00:57:44 +00:00
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
2013-05-06 15:23:51 +00:00
|
|
|
|
2024-02-13 23:31:06 +00:00
|
|
|
let is_tuple = match struct_def {
|
|
|
|
ast::VariantData::Tuple(..) => IsTuple::Yes,
|
|
|
|
_ => IsTuple::No,
|
|
|
|
};
|
2013-12-07 00:57:44 +00:00
|
|
|
match (just_spans.is_empty(), named_idents.is_empty()) {
|
2023-12-18 09:54:03 +00:00
|
|
|
(false, false) => cx
|
|
|
|
.dcx()
|
|
|
|
.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`"),
|
2013-12-07 00:57:44 +00:00
|
|
|
// named fields
|
|
|
|
(_, false) => Named(named_idents),
|
2019-03-23 21:06:58 +00:00
|
|
|
// unnamed fields
|
|
|
|
(false, _) => Unnamed(just_spans, is_tuple),
|
|
|
|
// empty
|
|
|
|
_ => Named(Vec::new()),
|
2013-12-07 00:57:44 +00:00
|
|
|
}
|
2013-03-28 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
fn create_struct_patterns(
|
2013-12-07 00:57:44 +00:00
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
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-04 23:04:41 +00:00
|
|
|
struct_path: ast::Path,
|
|
|
|
struct_def: &'a VariantData,
|
|
|
|
prefixes: &[String],
|
2022-08-30 22:34:35 +00:00
|
|
|
by_ref: ByRef,
|
2022-11-23 00:55:16 +00:00
|
|
|
) -> ThinVec<P<ast::Pat>> {
|
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-04 23:04:41 +00:00
|
|
|
prefixes
|
2016-07-19 17:32:06 +00:00
|
|
|
.iter()
|
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-04 23:04:41 +00:00
|
|
|
.map(|prefix| {
|
2022-07-07 21:57:34 +00:00
|
|
|
let pieces_iter =
|
|
|
|
struct_def.fields().iter().enumerate().map(|(i, struct_field)| {
|
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-04 23:04:41 +00:00
|
|
|
let sp = struct_field.span.with_ctxt(self.span.ctxt());
|
|
|
|
let ident = self.mk_pattern_ident(prefix, i);
|
|
|
|
let path = ident.with_span_pos(sp);
|
|
|
|
(
|
|
|
|
sp,
|
|
|
|
struct_field.ident,
|
2022-08-30 22:34:35 +00:00
|
|
|
cx.pat(
|
|
|
|
path.span,
|
2024-04-16 23:23:30 +00:00
|
|
|
PatKind::Ident(BindingMode(by_ref, Mutability::Not), path, None),
|
2022-08-30 22:34:35 +00:00
|
|
|
),
|
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-04 23:04:41 +00:00
|
|
|
)
|
2022-07-07 21:57:34 +00:00
|
|
|
});
|
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-04 23:04:41 +00:00
|
|
|
|
|
|
|
let struct_path = struct_path.clone();
|
|
|
|
match *struct_def {
|
2023-12-19 22:47:30 +00:00
|
|
|
VariantData::Struct { .. } => {
|
2022-07-07 21:57:34 +00:00
|
|
|
let field_pats = pieces_iter
|
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-04 23:04:41 +00:00
|
|
|
.map(|(sp, ident, pat)| {
|
|
|
|
if ident.is_none() {
|
2023-12-18 09:54:03 +00:00
|
|
|
cx.dcx().span_bug(
|
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-04 23:04:41 +00:00
|
|
|
sp,
|
|
|
|
"a braced struct with unnamed fields in `derive`",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
ast::PatField {
|
|
|
|
ident: ident.unwrap(),
|
|
|
|
is_shorthand: false,
|
|
|
|
attrs: ast::AttrVec::new(),
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: pat.span.with_ctxt(self.span.ctxt()),
|
|
|
|
pat,
|
|
|
|
is_placeholder: false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
cx.pat_struct(self.span, struct_path, field_pats)
|
|
|
|
}
|
|
|
|
VariantData::Tuple(..) => {
|
2022-07-07 21:57:34 +00:00
|
|
|
let subpats = pieces_iter.map(|(_, _, subpat)| subpat).collect();
|
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-04 23:04:41 +00:00
|
|
|
cx.pat_tuple_struct(self.span, struct_path, subpats)
|
|
|
|
}
|
|
|
|
VariantData::Unit(..) => cx.pat_path(self.span, struct_path),
|
|
|
|
}
|
2016-07-19 17:32:06 +00:00
|
|
|
})
|
|
|
|
.collect()
|
2013-12-07 00:57:44 +00:00
|
|
|
}
|
2013-06-07 07:30:38 +00:00
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
fn create_fields<F>(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec<FieldInfo>
|
|
|
|
where
|
|
|
|
F: Fn(usize, &ast::FieldDef, Span) -> Vec<P<ast::Expr>>,
|
|
|
|
{
|
|
|
|
struct_def
|
|
|
|
.fields()
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, struct_field)| {
|
|
|
|
// For this field, get an expr for each selflike_arg. E.g. for
|
|
|
|
// `PartialEq::eq`, one for each of `&self` and `other`.
|
|
|
|
let sp = struct_field.span.with_ctxt(self.span.ctxt());
|
|
|
|
let mut exprs: Vec<_> = mk_exprs(i, struct_field, sp);
|
|
|
|
let self_expr = exprs.remove(0);
|
|
|
|
let other_selflike_exprs = exprs;
|
|
|
|
FieldInfo {
|
|
|
|
span: sp.with_ctxt(self.span.ctxt()),
|
|
|
|
name: struct_field.ident,
|
|
|
|
self_expr,
|
|
|
|
other_selflike_exprs,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
2013-06-07 07:30:38 +00:00
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
fn mk_pattern_ident(&self, prefix: &str, i: usize) -> Ident {
|
2023-07-25 20:00:13 +00:00
|
|
|
Ident::from_str_and_span(&format!("{prefix}_{i}"), self.span)
|
2013-12-07 00:57:44 +00:00
|
|
|
}
|
2013-06-07 07:30:38 +00:00
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
fn create_struct_pattern_fields(
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
struct_def: &'a VariantData,
|
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-04 23:04:41 +00:00
|
|
|
prefixes: &[String],
|
|
|
|
) -> Vec<FieldInfo> {
|
|
|
|
self.create_fields(struct_def, |i, _struct_field, sp| {
|
|
|
|
prefixes
|
|
|
|
.iter()
|
|
|
|
.map(|prefix| {
|
|
|
|
let ident = self.mk_pattern_ident(prefix, i);
|
2022-11-14 02:59:54 +00:00
|
|
|
cx.expr_path(cx.path_ident(sp, ident))
|
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-04 23:04:41 +00:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
})
|
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::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.
2022-06-24 00:20:54 +00:00
|
|
|
}
|
|
|
|
|
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-04 23:04:41 +00:00
|
|
|
fn create_struct_field_access_fields(
|
2016-07-19 17:32:06 +00:00
|
|
|
&self,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\mod.rs:120:9
|
120 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1573:13
|
1573 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1556:13
|
1556 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1463:13
|
1463 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1433:36
|
1433 | fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:953:13
|
953 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:932:13
|
932 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:580:13
|
580 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:989:13
|
989 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:97:9
|
97 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\eq.rs:52:9
|
52 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\hash.rs:50:9
|
50 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\encodable.rs:150:9
|
150 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:176:9
|
176 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:106:9
|
106 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:57:9
|
57 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\default.rs:84:9
|
84 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:212:9
|
212 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\debug.rs:48:26
|
48 | fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:16:08 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
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-04 23:04:41 +00:00
|
|
|
selflike_args: &[P<Expr>],
|
|
|
|
struct_def: &'a VariantData,
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
is_packed: bool,
|
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-04 23:04:41 +00:00
|
|
|
) -> Vec<FieldInfo> {
|
|
|
|
self.create_fields(struct_def, |i, struct_field, sp| {
|
|
|
|
selflike_args
|
|
|
|
.iter()
|
2022-07-06 06:13:51 +00:00
|
|
|
.map(|selflike_arg| {
|
2022-07-07 01:09:07 +00:00
|
|
|
// Note: we must use `struct_field.span` rather than `sp` in the
|
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-04 23:04:41 +00:00
|
|
|
// `unwrap_or_else` case otherwise the hygiene is wrong and we get
|
|
|
|
// "field `0` of struct `Point` is private" errors on tuple
|
|
|
|
// structs.
|
2022-07-11 02:54:52 +00:00
|
|
|
let mut field_expr = cx.expr(
|
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-04 23:04:41 +00:00
|
|
|
sp,
|
2022-07-11 02:54:52 +00:00
|
|
|
ast::ExprKind::Field(
|
|
|
|
selflike_arg.clone(),
|
|
|
|
struct_field.ident.unwrap_or_else(|| {
|
|
|
|
Ident::from_str_and_span(&i.to_string(), struct_field.span)
|
|
|
|
}),
|
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-04 23:04:41 +00:00
|
|
|
),
|
2022-07-11 02:54:52 +00:00
|
|
|
);
|
Allow more deriving on packed structs.
Currently, deriving on packed structs has some non-trivial limitations,
related to the fact that taking references on unaligned fields is UB.
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`: `&self.0`
Plus, we disallow deriving any builtin traits other than `Default` for any
packed generic type, because it's possible that there might be
misaligned fields. This is a fairly broad restriction.
Plus, we disallow deriving any builtin traits other than `Default` for most
packed types that don't derive `Copy`. (The exceptions are those where the
alignments inherently satisfy the packing, e.g. in a type with
`repr(packed(N))` where all the fields have alignments of `N` or less
anyway. Such types are pretty strange, because the `packed` attribute is
not having any effect.)
This commit introduces a new, simpler approach to field accesses:
- Normal case: `&self.0`
- In a packed struct: `&{self.0}`
In the latter case, this requires that all fields impl `Copy`, which is
a new restriction. This means that the following example compiles under
the old approach and doesn't compile under the new approach.
```
#[derive(Debug)]
struct NonCopy(u8);
#[derive(Debug)
#[repr(packed)]
struct MyType(NonCopy);
```
(Note that the old approach's support for cases like this was brittle.
Changing the `u8` to a `u16` would be enough to stop it working. So not
much capability is lost here.)
However, the other constraints from the old rules are removed. We can now
derive builtin traits for packed generic structs like this:
```
trait Trait { type A; }
#[derive(Hash)]
#[repr(packed)]
pub struct Foo<T: Trait>(T, T::A);
```
To allow this, we add a `T: Copy` bound in the derived impl and a `T::A:
Copy` bound in where clauses. So `T` and `T::A` must impl `Copy`.
We can now also derive builtin traits for packed structs that don't derive
`Copy`, so long as the fields impl `Copy`:
```
#[derive(Hash)]
#[repr(packed)]
pub struct Foo(u32);
```
This includes types that hand-impl `Copy` rather than deriving it, such as the
following, that show up in winapi-0.2:
```
#[derive(Clone)]
#[repr(packed)]
struct MyType(i32);
impl Copy for MyType {}
```
The new approach is simpler to understand and implement, and it avoids
the need for the `unsafe_derive_on_repr_packed` check.
One exception is required for backwards-compatibility: we allow `[u8]`
fields for now. There is a new lint for this,
`byte_slice_in_packed_struct_with_derive`.
2022-11-21 03:40:32 +00:00
|
|
|
if is_packed {
|
2024-07-18 10:26:19 +00:00
|
|
|
// Fields in packed structs are wrapped in a block, e.g. `&{self.0}`,
|
|
|
|
// causing a copy instead of a (potentially misaligned) reference.
|
|
|
|
field_expr = cx.expr_block(
|
|
|
|
cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
|
|
|
|
);
|
2022-07-11 02:54:52 +00:00
|
|
|
}
|
|
|
|
cx.expr_addr_of(sp, field_expr)
|
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-04 23:04:41 +00:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
})
|
2013-06-07 07:30:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-05 01:23:55 +00:00
|
|
|
/// The function passed to `cs_fold` is called repeatedly with a value of this
|
|
|
|
/// type. It describes one part of the code generation. The result is always an
|
|
|
|
/// expression.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) enum CsFold<'a> {
|
2022-07-05 01:23:55 +00:00
|
|
|
/// The basic case: a field expression for one or more selflike args. E.g.
|
|
|
|
/// for `PartialEq::eq` this is something like `self.x == other.x`.
|
|
|
|
Single(&'a FieldInfo),
|
|
|
|
|
|
|
|
/// The combination of two field expressions. E.g. for `PartialEq::eq` this
|
|
|
|
/// is something like `<field1 equality> && <field2 equality>`.
|
|
|
|
Combine(Span, P<Expr>, P<Expr>),
|
|
|
|
|
|
|
|
// The fallback case for a struct or enum variant with no fields.
|
|
|
|
Fieldless,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Folds over fields, combining the expressions for each field in a sequence.
|
|
|
|
/// Statics may not be folded over.
|
2024-04-25 21:56:48 +00:00
|
|
|
pub(crate) fn cs_fold<F>(
|
2018-04-11 14:16:54 +00:00
|
|
|
use_foldl: bool,
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
cx: &ExtCtxt<'_>,
|
2018-04-11 14:16:54 +00:00
|
|
|
trait_span: Span,
|
2019-02-04 12:49:54 +00:00
|
|
|
substructure: &Substructure<'_>,
|
2022-07-05 01:23:55 +00:00
|
|
|
mut f: F,
|
2018-04-11 14:16:54 +00:00
|
|
|
) -> P<Expr>
|
2019-02-04 12:49:54 +00:00
|
|
|
where
|
compiler: fix few needless_pass_by_ref_mut clippy lints
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\clone.rs:160:9
|
160 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_ord.rs:72:9
|
72 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\partial_eq.rs:19:18
|
19 | fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\cmp\ord.rs:42:19
|
42 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:917:13
|
917 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1406:13
|
1406 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1157:13
|
1157 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1103:13
|
1103 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:1080:13
|
1080 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:859:13
|
859 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:805:13
|
805 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:467:13
|
467 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_builtin_macros\src\deriving\generic\mod.rs:457:13
|
457 | cx: &mut ExtCtxt<'_>,
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&ExtCtxt<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
2024-03-28 09:36:45 +00:00
|
|
|
F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> P<Expr>,
|
2018-04-11 14:16:54 +00:00
|
|
|
{
|
2022-07-08 05:32:27 +00:00
|
|
|
match substructure.fields {
|
|
|
|
EnumMatching(.., all_fields) | Struct(_, all_fields) => {
|
2022-07-05 01:23:55 +00:00
|
|
|
if all_fields.is_empty() {
|
|
|
|
return f(cx, CsFold::Fieldless);
|
|
|
|
}
|
|
|
|
|
|
|
|
let (base_field, rest) = if use_foldl {
|
|
|
|
all_fields.split_first().unwrap()
|
|
|
|
} else {
|
|
|
|
all_fields.split_last().unwrap()
|
|
|
|
};
|
|
|
|
|
|
|
|
let base_expr = f(cx, CsFold::Single(base_field));
|
|
|
|
|
|
|
|
let op = |old, field: &FieldInfo| {
|
|
|
|
let new = f(cx, CsFold::Single(field));
|
|
|
|
f(cx, CsFold::Combine(field.span, old, new))
|
2018-04-11 14:16:54 +00:00
|
|
|
};
|
|
|
|
|
2022-07-04 07:10:36 +00:00
|
|
|
if use_foldl {
|
2022-07-05 01:23:55 +00:00
|
|
|
rest.iter().fold(base_expr, op)
|
2022-07-04 07:10:36 +00:00
|
|
|
} else {
|
2022-07-05 01:23:55 +00:00
|
|
|
rest.iter().rfold(base_expr, op)
|
2022-07-04 07:10:36 +00:00
|
|
|
}
|
2018-04-11 14:16:54 +00:00
|
|
|
}
|
2024-04-14 09:31:51 +00:00
|
|
|
EnumDiscr(discr_field, match_expr) => {
|
|
|
|
let discr_check_expr = f(cx, CsFold::Single(discr_field));
|
2022-07-08 05:32:27 +00:00
|
|
|
if let Some(match_expr) = match_expr {
|
|
|
|
if use_foldl {
|
2024-04-14 09:31:51 +00:00
|
|
|
f(cx, CsFold::Combine(trait_span, discr_check_expr, match_expr.clone()))
|
2022-07-08 05:32:27 +00:00
|
|
|
} else {
|
2024-04-14 09:31:51 +00:00
|
|
|
f(cx, CsFold::Combine(trait_span, match_expr.clone(), discr_check_expr))
|
2022-07-08 05:32:27 +00:00
|
|
|
}
|
|
|
|
} else {
|
2024-04-14 09:31:51 +00:00
|
|
|
discr_check_expr
|
2022-07-08 05:32:27 +00:00
|
|
|
}
|
|
|
|
}
|
2023-12-18 09:54:03 +00:00
|
|
|
StaticEnum(..) | StaticStruct(..) => {
|
|
|
|
cx.dcx().span_bug(trait_span, "static function in `derive`")
|
|
|
|
}
|
|
|
|
AllFieldlessEnum(..) => cx.dcx().span_bug(trait_span, "fieldless enum in `derive`"),
|
2018-04-11 14:16:54 +00:00
|
|
|
}
|
|
|
|
}
|