Skip to content

Commit 214113a

Browse files
committed
syntax: Make #[derive(Copy)] imply #[derive(Clone)]
1 parent 02c5ff7 commit 214113a

File tree

10 files changed

+141
-9
lines changed

10 files changed

+141
-9
lines changed

src/libcore/fmt/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
1616
use char::CharExt;
17+
#[cfg(stage0)]
1718
use clone::Clone;
1819
use iter::Iterator;
1920
use marker::{Copy, PhantomData, Sized};
@@ -141,6 +142,7 @@ pub struct ArgumentV1<'a> {
141142
formatter: fn(&Void, &mut Formatter) -> Result,
142143
}
143144

145+
#[cfg(stage0)]
144146
impl<'a> Clone for ArgumentV1<'a> {
145147
fn clone(&self) -> ArgumentV1<'a> {
146148
*self

src/liblibc/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,7 @@ pub mod types {
20912091
pub __ss_align: i64,
20922092
pub __ss_pad2: [u8; 112],
20932093
}
2094+
#[cfg(stage0)]
20942095
impl ::core::clone::Clone for sockaddr_storage {
20952096
fn clone(&self) -> sockaddr_storage { *self }
20962097
}
@@ -2154,6 +2155,7 @@ pub mod types {
21542155
pub sun_family: sa_family_t,
21552156
pub sun_path: [c_char; 104]
21562157
}
2158+
#[cfg(stage0)]
21572159
impl ::core::clone::Clone for sockaddr_un {
21582160
fn clone(&self) -> sockaddr_un { *self }
21592161
}
@@ -2369,6 +2371,7 @@ pub mod types {
23692371
pub __sig: c_long,
23702372
pub __opaque: [c_char; 56]
23712373
}
2374+
#[cfg(stage0)]
23722375
impl ::core::clone::Clone for pthread_attr_t {
23732376
fn clone(&self) -> pthread_attr_t { *self }
23742377
}

src/librand/isaac.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl IsaacRng {
187187
}
188188

189189
// Cannot be derived because [u32; 256] does not implement Clone
190+
#[cfg(stage0)]
190191
impl Clone for IsaacRng {
191192
fn clone(&self) -> IsaacRng {
192193
*self
@@ -432,6 +433,7 @@ impl Isaac64Rng {
432433
}
433434

434435
// Cannot be derived because [u32; 256] does not implement Clone
436+
#[cfg(stage0)]
435437
impl Clone for Isaac64Rng {
436438
fn clone(&self) -> Isaac64Rng {
437439
*self

src/librustc/middle/liveness.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ impl LiveNode {
153153
fn get(&self) -> usize { let LiveNode(v) = *self; v }
154154
}
155155

156+
#[cfg(stage0)]
156157
impl Clone for LiveNode {
157158
fn clone(&self) -> LiveNode {
158159
LiveNode(self.get())

src/librustc_borrowck/borrowck/move_data.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ impl MovePathIndex {
8484
}
8585
}
8686

87+
#[cfg(stage0)]
8788
impl Clone for MovePathIndex {
8889
fn clone(&self) -> MovePathIndex {
8990
MovePathIndex(self.get())

src/libstd/net/addr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,13 @@ impl fmt::Debug for SocketAddrV6 {
206206
}
207207
}
208208

209+
#[cfg(stage0)]
209210
#[stable(feature = "rust1", since = "1.0.0")]
210211
impl Clone for SocketAddrV4 {
211212
fn clone(&self) -> SocketAddrV4 { *self }
212213
}
214+
215+
#[cfg(stage0)]
213216
#[stable(feature = "rust1", since = "1.0.0")]
214217
impl Clone for SocketAddrV6 {
215218
fn clone(&self) -> SocketAddrV6 { *self }

src/libstd/net/ip.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl fmt::Debug for Ipv4Addr {
174174
}
175175
}
176176

177+
#[cfg(stage0)]
177178
#[stable(feature = "rust1", since = "1.0.0")]
178179
impl Clone for Ipv4Addr {
179180
fn clone(&self) -> Ipv4Addr { *self }
@@ -417,6 +418,7 @@ impl fmt::Debug for Ipv6Addr {
417418
}
418419
}
419420

421+
#[cfg(stage0)]
420422
#[stable(feature = "rust1", since = "1.0.0")]
421423
impl Clone for Ipv6Addr {
422424
fn clone(&self) -> Ipv6Addr { *self }

src/libsyntax/ast_map/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ enum MapEntry<'ast> {
148148
RootInlinedParent(&'ast InlinedParent)
149149
}
150150

151+
#[cfg(stage0)]
151152
impl<'ast> Clone for MapEntry<'ast> {
152153
fn clone(&self) -> MapEntry<'ast> {
153154
*self

src/libsyntax/ext/deriving/bounds.rs

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ast::{MetaItem, Item};
12-
use codemap::Span;
11+
use abi;
12+
use ast::{self, MetaItem, Item};
13+
use codemap::{Span, respan};
1314
use ext::base::ExtCtxt;
15+
use ext::build::AstBuilder;
1416
use ext::deriving::generic::*;
1517
use ext::deriving::generic::ty::*;
18+
use owned_slice::OwnedSlice;
19+
use parse::token::{InternedString, special_idents};
1620
use ptr::P;
1721

22+
use super::clone;
23+
1824
pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
1925
span: Span,
2026
_: &MetaItem,
@@ -30,21 +36,114 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
3036
item: &Item,
3137
push: &mut FnMut(P<Item>))
3238
{
33-
let path = Path::new(vec![
34-
if cx.use_std { "std" } else { "core" },
35-
"marker",
36-
"Copy",
37-
]);
38-
3939
let trait_def = TraitDef {
4040
span: span,
4141
attributes: Vec::new(),
42-
path: path,
42+
path: path_std!(cx, core::marker::Copy),
4343
additional_bounds: Vec::new(),
4444
generics: LifetimeBounds::empty(),
4545
methods: Vec::new(),
4646
associated_types: Vec::new(),
4747
};
4848

4949
trait_def.expand(cx, mitem, item, push);
50+
51+
expand_deriving_clone_when_copy(cx, span, mitem, item, push)
52+
}
53+
54+
fn expand_deriving_clone_when_copy(cx: &mut ExtCtxt,
55+
span: Span,
56+
mitem: &MetaItem,
57+
item: &Item,
58+
push: &mut FnMut(P<Item>))
59+
{
60+
// For generic types we need to destructure our value in order to recursively call clone.
61+
// However, as an optimization for non-generic types, we can just generate:
62+
//
63+
// impl<...> Clone for $ty {
64+
// fn clone(&self) -> Self { *self }
65+
// }
66+
//
67+
// But the generic deriving helpers do not support generating such a simple method. So we'll
68+
// build this method by hand. However, we want to take advantage of generic deriving generating
69+
// the `Generics` for us. So we'll generate an empty impl, then later on add our method. It's
70+
// not pretty, but it works until we get a more general purpose ast builder.
71+
match item.node {
72+
ast::ItemStruct(_, ref generics) | ast::ItemEnum(_, ref generics) => {
73+
if generics.is_type_parameterized() {
74+
clone::expand_deriving_clone(cx, span, mitem, item, push);
75+
return;
76+
}
77+
}
78+
_ => {
79+
cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");
80+
return;
81+
}
82+
}
83+
84+
let trait_def = TraitDef {
85+
span: span,
86+
attributes: Vec::new(),
87+
path: path_std!(cx, core::clone::Clone),
88+
additional_bounds: Vec::new(),
89+
generics: LifetimeBounds::empty(),
90+
methods: Vec::new(),
91+
associated_types: Vec::new(),
92+
};
93+
94+
// We want to use the `cx` to build our ast, but it's passed by `&mut` to the expand method. So
95+
// we'll extract out the generated item by way of an option.
96+
let mut expanded_item = None;
97+
98+
trait_def.expand(cx, mitem, item, &mut |item: P<ast::Item>| {
99+
expanded_item = Some(item);
100+
});
101+
102+
let expanded_item = expanded_item.unwrap().map(|mut item| {
103+
match item.node {
104+
ast::ItemImpl(_, _, _, _, ref ty, ref mut impl_items) => {
105+
let self_arg = ast::Arg::new_self(span, ast::MutImmutable, special_idents::self_);
106+
let decl = cx.fn_decl(vec![self_arg], ty.clone());
107+
108+
let sig = ast::MethodSig {
109+
unsafety: ast::Unsafety::Normal,
110+
abi: abi::Rust,
111+
decl: decl.clone(),
112+
generics: ast::Generics {
113+
lifetimes: Vec::new(),
114+
ty_params: OwnedSlice::empty(),
115+
where_clause: ast::WhereClause {
116+
id: ast::DUMMY_NODE_ID,
117+
predicates: Vec::new(),
118+
}
119+
},
120+
explicit_self: respan(
121+
span,
122+
ast::SelfRegion(None, ast::MutImmutable, cx.ident_of("self")),
123+
),
124+
};
125+
126+
let block = cx.block_expr(cx.expr_deref(span, cx.expr_self(span)));
127+
128+
let inline = cx.meta_word(span, InternedString::new("inline"));
129+
let attrs = vec!(cx.attribute(span, inline));
130+
131+
impl_items.push(P(ast::ImplItem {
132+
id: ast::DUMMY_NODE_ID,
133+
ident: cx.ident_of("clone"),
134+
vis: ast::Visibility::Inherited,
135+
attrs: attrs,
136+
node: ast::ImplItem_::MethodImplItem(sig, block),
137+
span: span,
138+
}));
139+
}
140+
_ => {
141+
cx.span_bug(span, "we should have gotten an impl")
142+
}
143+
};
144+
145+
item
146+
});
147+
148+
push(expanded_item)
50149
}

src/libsyntax/ext/deriving/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ fn expand_derive(cx: &mut ExtCtxt,
9292
cx.span_warn(mitem.span, "empty trait list in `derive`");
9393
}
9494

95+
// FIXME: This can be removed after a snapshot
96+
let mut seen_copy = false;
97+
98+
for titem in traits.iter() {
99+
match titem.node {
100+
MetaWord(ref tname) => {
101+
match &**tname {
102+
"Copy" => { seen_copy = true; }
103+
_ => { }
104+
}
105+
}
106+
_ => { }
107+
}
108+
}
109+
95110
for titem in traits.iter().rev() {
96111
let tname = match titem.node {
97112
MetaWord(ref tname) => tname,
@@ -109,6 +124,9 @@ fn expand_derive(cx: &mut ExtCtxt,
109124
continue;
110125
}
111126

127+
// FIXME: This can be removed after a snapshot
128+
if seen_copy && &**tname == "Clone" { continue; }
129+
112130
// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
113131
item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
114132
intern_and_get_ident(&format!("derive_{}", tname)))));

0 commit comments

Comments
 (0)