|
1 | 1 | use crate::deriving::generic::ty::*;
|
2 | 2 | use crate::deriving::generic::*;
|
3 | 3 | use crate::deriving::path_std;
|
| 4 | +use crate::errors; |
4 | 5 | use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
|
5 | 6 | use rustc_data_structures::fx::FxHashSet;
|
6 | 7 | use rustc_expand::base::{Annotatable, ExtCtxt};
|
@@ -32,42 +33,52 @@ pub fn expand_deriving_clone(
|
32 | 33 | let bounds;
|
33 | 34 | let substructure;
|
34 | 35 | let is_simple;
|
35 |
| - match item { |
36 |
| - Annotatable::Item(annitem) => match &annitem.kind { |
37 |
| - ItemKind::Struct(_, Generics { params, .. }) |
38 |
| - | ItemKind::Enum(_, Generics { params, .. }) => { |
39 |
| - let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); |
40 |
| - let has_derive_copy = cx.resolver.has_derive_copy(container_id); |
41 |
| - if has_derive_copy |
42 |
| - && !params |
43 |
| - .iter() |
44 |
| - .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) |
45 |
| - { |
46 |
| - bounds = vec![]; |
47 |
| - is_simple = true; |
48 |
| - substructure = combine_substructure(Box::new(|c, s, sub| { |
49 |
| - cs_clone_simple("Clone", c, s, sub, false) |
50 |
| - })); |
51 |
| - } else { |
52 |
| - bounds = vec![]; |
53 |
| - is_simple = false; |
54 |
| - substructure = |
55 |
| - combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); |
56 |
| - } |
57 |
| - } |
58 |
| - ItemKind::Union(..) => { |
59 |
| - bounds = vec![Path(path_std!(marker::Copy))]; |
| 36 | + let Annotatable::Item(annitem) = item else { |
| 37 | + cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item") |
| 38 | + }; |
| 39 | + let has_unnamed = if let ItemKind::Struct(VariantData::Struct { fields, .. }, _) = &annitem.kind |
| 40 | + { |
| 41 | + fields.iter().any(|f| f.ident.is_some_and(|i| i.name == kw::Underscore)) |
| 42 | + } else { |
| 43 | + false |
| 44 | + }; |
| 45 | + match &annitem.kind { |
| 46 | + ItemKind::Struct(_, Generics { params, .. }) |
| 47 | + | ItemKind::Enum(_, Generics { params, .. }) => { |
| 48 | + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); |
| 49 | + let has_derive_copy = cx.resolver.has_derive_copy(container_id); |
| 50 | + if has_derive_copy |
| 51 | + && !params |
| 52 | + .iter() |
| 53 | + .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) |
| 54 | + { |
| 55 | + bounds = vec![]; |
60 | 56 | is_simple = true;
|
61 | 57 | substructure = combine_substructure(Box::new(|c, s, sub| {
|
62 |
| - cs_clone_simple("Clone", c, s, sub, true) |
| 58 | + cs_clone_simple("Clone", c, s, sub, false) |
63 | 59 | }));
|
| 60 | + } else { |
| 61 | + bounds = vec![]; |
| 62 | + is_simple = false; |
| 63 | + substructure = |
| 64 | + combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); |
64 | 65 | }
|
65 |
| - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), |
66 |
| - }, |
67 |
| - |
68 |
| - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"), |
| 66 | + } |
| 67 | + ItemKind::Union(..) => { |
| 68 | + bounds = vec![Path(path_std!(marker::Copy))]; |
| 69 | + is_simple = true; |
| 70 | + substructure = combine_substructure(Box::new(|c, s, sub| { |
| 71 | + cs_clone_simple("Clone", c, s, sub, true) |
| 72 | + })); |
| 73 | + } |
| 74 | + _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), |
69 | 75 | }
|
70 | 76 |
|
| 77 | + if !is_simple && has_unnamed { |
| 78 | + cx.dcx().emit_err(errors::UnnamedFieldDeriveClone { span }); |
| 79 | + return; |
| 80 | + }; |
| 81 | + |
71 | 82 | let trait_def = TraitDef {
|
72 | 83 | span,
|
73 | 84 | path: path_std!(clone::Clone),
|
|
0 commit comments