summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-09-15 18:16:19 +0530
committerGitHub <noreply@github.com>2016-09-15 18:16:19 +0530
commit726850170d3ec4606246ad90fcb08d1eee913c76 (patch)
treefdffde4c348f7388797f45de4501e5a0ca91ba43 /src/libsyntax
parent16ff9e22cdb552fd10e6cee2eb22f0c5da6d7e79 (diff)
parent62cb7510ac6285c93ec691198a92f910582d31a2 (diff)
downloadrust-726850170d3ec4606246ad90fcb08d1eee913c76.tar.gz
rust-726850170d3ec4606246ad90fcb08d1eee913c76.zip
Rollup merge of #36384 - petrochenkov:derclone, r=alexcrichton
Improve shallow `Clone` deriving

`Copy` unions now support `#[derive(Clone)]`.
Less code is generated for `#[derive(Clone, Copy)]`.
+
Unions now support `#[derive(Eq)]`.
Less code is generated for `#[derive(Eq)]`.

---
Example of code reduction:
```
enum E {
	A { a: u8, b: u16 },
	B { c: [u8; 100] },
}
```
Before:
```
fn clone(&self) -> E {
    match (&*self,) {
        (&E::A { a: ref __self_0, b: ref __self_1 },) => {
            ::std::clone::assert_receiver_is_clone(&(*__self_0));
            ::std::clone::assert_receiver_is_clone(&(*__self_1));
            *self
        }
        (&E::B { c: ref __self_0 },) => {
            ::std::clone::assert_receiver_is_clone(&(*__self_0));
            *self
        }
    }
}
```
After:
```
fn clone(&self) -> E {
    {
        let _: ::std::clone::AssertParamIsClone<u8>;
        let _: ::std::clone::AssertParamIsClone<u16>;
        let _: ::std::clone::AssertParamIsClone<[u8; 100]>;
        *self
    }
}
```

All the matches are removed, bound assertions are more lightweight.
`let _: Checker<CheckMe>;`, unlike `checker(&check_me);`, doesn't have to be translated by rustc_trans and then inlined by LLVM, it doesn't even exist in MIR, this means faster compilation.

---
Union impls are generated like this:
```
union U {
	a: u8,
	b: u16,
	c: [u8; 100],
}
```
```
fn clone(&self) -> U {
    {
        let _: ::std::clone::AssertParamIsCopy<Self>;
        *self
    }
}
```

Fixes https://github.com/rust-lang/rust/issues/36043
cc @durka
r? @alexcrichton
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/build.rs18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 3dcdbc89096..b81d95a6998 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -97,6 +97,7 @@ pub trait AstBuilder {
                       typ: P<ast::Ty>,
                       ex: P<ast::Expr>)
                       -> P<ast::Stmt>;
+    fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt;
     fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt;
 
     // blocks
@@ -577,6 +578,23 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         })
     }
 
+    // Generate `let _: Type;`, usually used for type assertions.
+    fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
+        let local = P(ast::Local {
+            pat: self.pat_wild(span),
+            ty: Some(ty),
+            init: None,
+            id: ast::DUMMY_NODE_ID,
+            span: span,
+            attrs: ast::ThinVec::new(),
+        });
+        ast::Stmt {
+            id: ast::DUMMY_NODE_ID,
+            node: ast::StmtKind::Local(local),
+            span: span,
+        }
+    }
+
     fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,