|
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