Files
rust/compiler/rustc_builtin_macros/src/deriving/default.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

321 lines
12 KiB
Rust
Raw Normal View History

2024-02-24 02:52:59 -05:00
use core::ops::ControlFlow;
use rustc_ast as ast;
use rustc_ast::visit::visit_opt;
2024-02-24 15:22:42 -05:00
use rustc_ast::{EnumDef, VariantData, attr};
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use smallvec::SmallVec;
use thin_vec::{ThinVec, thin_vec};
2014-05-16 00:16:13 -07:00
2019-02-04 21:49:54 +09:00
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::errors;
2024-04-26 07:56:48 +10:00
pub(crate) fn expand_deriving_default(
cx: &ExtCtxt<'_>,
span: Span,
mitem: &ast::MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
2022-09-20 11:55:07 +00:00
is_const: bool,
) {
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
let trait_def = TraitDef {
span,
path: Path::new(vec![kw::Default, sym::Default]),
skip_path_as_bound: has_a_default_variant(item),
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 14:40:32 +11:00
needs_copy_as_bound_if_packed: false,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
name: kw::Default,
generics: Bounds::empty(),
explicit_self: false,
nonself_args: Vec::new(),
ret_ty: Self_,
attributes: thin_vec![cx.attr_word(sym::inline, span)],
2023-01-14 21:16:25 +00:00
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
match substr.fields {
StaticStruct(_, fields) => {
default_struct_substructure(cx, trait_span, substr, fields)
}
StaticEnum(enum_def) => {
default_enum_substructure(cx, trait_span, enum_def, item.span())
}
_ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
}
})),
}],
associated_types: Vec::new(),
2022-09-20 11:55:07 +00:00
is_const,
};
trait_def.expand(cx, mitem, item, push)
}
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
fn default_call(cx: &ExtCtxt<'_>, span: Span) -> ast::ptr::P<ast::Expr> {
// Note that `kw::Default` is "default" and `sym::Default` is "Default"!
let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
cx.expr_call_global(span, default_ident, ThinVec::new())
}
fn default_struct_substructure(
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 12:16:08 +03:00
cx: &ExtCtxt<'_>,
2019-02-04 21:49:54 +09:00
trait_span: Span,
substr: &Substructure<'_>,
summary: &StaticFields,
) -> BlockOrExpr {
let expr = match summary {
2024-02-13 23:31:06 +00:00
Unnamed(_, IsTuple::No) => cx.expr_ident(trait_span, substr.type_ident),
Unnamed(fields, IsTuple::Yes) => {
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
let exprs = fields.iter().map(|sp| default_call(cx, *sp)).collect();
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
}
Named(fields) => {
let default_fields = fields
.iter()
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
.map(|(ident, span, default_val)| {
let value = match default_val {
// We use `Default::default()`.
None => default_call(cx, *span),
// We use the field default const expression.
Some(val) => {
cx.expr(val.value.span, ast::ExprKind::ConstBlock(val.clone()))
}
};
cx.field_imm(*span, *ident, value)
})
.collect();
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
}
};
BlockOrExpr::new_expr(expr)
}
fn default_enum_substructure(
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 12:16:08 +03:00
cx: &ExtCtxt<'_>,
trait_span: Span,
enum_def: &EnumDef,
item_span: Span,
) -> BlockOrExpr {
let expr = match try {
let default_variant = extract_default_variant(cx, enum_def, trait_span, item_span)?;
validate_default_attribute(cx, default_variant)?;
default_variant
} {
Ok(default_variant) => {
// We now know there is exactly one unit variant with exactly one `#[default]` attribute.
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
match &default_variant.data {
VariantData::Unit(_) => cx.expr_path(cx.path(
default_variant.span,
vec![Ident::new(kw::SelfUpper, default_variant.span), default_variant.ident],
)),
VariantData::Struct { fields, .. } => {
// This only happens if `#![feature(default_field_values)]`. We have validated
// all fields have default values in the definition.
let default_fields = fields
.iter()
.map(|field| {
cx.field_imm(
field.span,
field.ident.unwrap(),
match &field.default {
// We use `Default::default()`.
None => default_call(cx, field.span),
// We use the field default const expression.
Some(val) => cx.expr(
val.value.span,
ast::ExprKind::ConstBlock(val.clone()),
2025-02-08 22:12:13 +00:00
),
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
},
)
})
.collect();
let path = cx.path(
default_variant.span,
vec![
Ident::new(kw::SelfUpper, default_variant.span),
default_variant.ident,
],
);
cx.expr_struct(default_variant.span, path, default_fields)
}
// Logic error in `extract_default_variant`.
VariantData::Tuple(..) => {
cx.dcx().bug("encountered tuple variant annotated with `#[default]`")
}
}
}
Err(guar) => DummyResult::raw_expr(trait_span, Some(guar)),
};
BlockOrExpr::new_expr(expr)
}
fn extract_default_variant<'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 12:16:08 +03:00
cx: &ExtCtxt<'_>,
enum_def: &'a EnumDef,
trait_span: Span,
item_span: Span,
) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
let default_variants: SmallVec<[_; 1]> = enum_def
.variants
.iter()
.filter(|variant| attr::contains_name(&variant.attrs, kw::Default))
.collect();
let variant = match default_variants.as_slice() {
[variant] => variant,
[] => {
let possible_defaults = enum_def
.variants
.iter()
.filter(|variant| matches!(variant.data, VariantData::Unit(..)))
.filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
let suggs = possible_defaults
.map(|v| errors::NoDefaultVariantSugg { span: v.span.shrink_to_lo() })
.collect();
let guar =
cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, item_span, suggs });
return Err(guar);
}
[first, rest @ ..] => {
let suggs = default_variants
.iter()
.filter_map(|variant| {
let keep = attr::find_by_name(&variant.attrs, kw::Default)?.span;
let spans: Vec<Span> = default_variants
.iter()
.flat_map(|v| {
attr::filter_by_name(&v.attrs, kw::Default)
.filter_map(|attr| (attr.span != keep).then_some(attr.span))
})
.collect();
(!spans.is_empty())
.then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
})
.collect();
let guar = cx.dcx().emit_err(errors::MultipleDefaults {
span: trait_span,
first: first.span,
additional: rest.iter().map(|v| v.span).collect(),
suggs,
});
return Err(guar);
}
};
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
if cx.ecfg.features.default_field_values()
&& let VariantData::Struct { fields, .. } = &variant.data
&& fields.iter().all(|f| f.default.is_some())
// Disallow `#[default] Variant {}`
&& !fields.is_empty()
Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
{
// Allowed
} else if !matches!(variant.data, VariantData::Unit(..)) {
let post = if cx.ecfg.features.default_field_values() {
" or variants where every field has a default value"
} else {
""
};
let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span, post });
return Err(guar);
}
if let Some(non_exhaustive_attr) = attr::find_by_name(&variant.attrs, sym::non_exhaustive) {
let guar = cx.dcx().emit_err(errors::NonExhaustiveDefault {
span: variant.ident.span,
non_exhaustive: non_exhaustive_attr.span,
});
return Err(guar);
}
Ok(variant)
}
fn validate_default_attribute(
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 12:16:08 +03:00
cx: &ExtCtxt<'_>,
default_variant: &rustc_ast::Variant,
) -> Result<(), ErrorGuaranteed> {
let attrs: SmallVec<[_; 1]> =
attr::filter_by_name(&default_variant.attrs, kw::Default).collect();
let attr = match attrs.as_slice() {
[attr] => attr,
[] => cx.dcx().bug(
"this method must only be called with a variant that has a `#[default]` attribute",
),
[first, rest @ ..] => {
let sugg = errors::MultipleDefaultAttrsSugg {
spans: rest.iter().map(|attr| attr.span).collect(),
};
let guar = cx.dcx().emit_err(errors::MultipleDefaultAttrs {
span: default_variant.ident.span,
first: first.span,
first_rest: rest[0].span,
rest: rest.iter().map(|attr| attr.span).collect::<Vec<_>>().into(),
only_one: rest.len() == 1,
sugg,
});
return Err(guar);
}
};
if !attr.is_word() {
let guar = cx.dcx().emit_err(errors::DefaultHasArg { span: attr.span });
return Err(guar);
}
Ok(())
}
struct DetectNonVariantDefaultAttr<'a, 'b> {
cx: &'a ExtCtxt<'b>,
}
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
if attr.has_name(kw::Default) {
let post = if self.cx.ecfg.features.default_field_values() {
" or variants where every field has a default value"
} else {
""
};
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span, post });
}
rustc_ast::visit::walk_attribute(self, attr);
}
fn visit_variant(&mut self, v: &'a rustc_ast::Variant) {
2024-10-24 10:41:44 -03:00
self.visit_ident(&v.ident);
self.visit_vis(&v.vis);
self.visit_variant_data(&v.data);
visit_opt!(self, visit_anon_const, &v.disr_expr);
for attr in &v.attrs {
rustc_ast::visit::walk_attribute(self, attr);
}
}
}
fn has_a_default_variant(item: &Annotatable) -> bool {
2024-02-24 02:52:59 -05:00
struct HasDefaultAttrOnVariant;
impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant {
2024-02-24 02:52:59 -05:00
type Result = ControlFlow<()>;
fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) -> ControlFlow<()> {
if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
2024-02-24 02:52:59 -05:00
ControlFlow::Break(())
} else {
// no need to walk the variant, we are only looking for top level variants
2024-02-24 02:52:59 -05:00
ControlFlow::Continue(())
}
}
}
2024-02-24 02:52:59 -05:00
item.visit_with(&mut HasDefaultAttrOnVariant).is_break()
}