Skip to content

Commit

Permalink
Add derive macro to get ImplicitClone implemented quicker
Browse files Browse the repository at this point in the history
  • Loading branch information
cecton committed Nov 9, 2023
1 parent 801ee5f commit a5d36aa
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["derive"]
map = ["indexmap"]
serde = ["dep:serde", "indexmap/serde"]
derive = ["implicit-clone-derive"]

[dependencies]
implicit-clone-derive = { version = "0.1", optional = true, path = "./implicit-clone-derive" }
indexmap = { version = ">= 1, <= 2", optional = true }
serde = { version = "1", optional = true }

[workspace]
members = ["implicit-clone-derive"]
26 changes: 26 additions & 0 deletions implicit-clone-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "implicit-clone-derive"
version = "0.1.0"
authors = ["Cecile Tonglet <[email protected]>"]
license = "MIT OR Apache-2.0"
edition = "2021"
description = "Immutable types and ImplicitClone trait similar to Copy"
repository = "https://github.com/yewstack/implicit-clone"
homepage = "https://github.com/yewstack/implicit-clone"
documentation = "https://docs.rs/implicit-clone"
readme = "README.md"
keywords = ["immutable", "cheap-clone", "copy", "rc"]
categories = ["rust-patterns"]
rust-version = "1.64"

[lib]
proc-macro = true

[dependencies]
quote = "1"
syn = { version = "2", features = ["full"] }

[dev-dependencies]
implicit-clone = { path = ".." }
trybuild = "1"
rustversion = "1"
10 changes: 10 additions & 0 deletions implicit-clone-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use quote::quote;

#[proc_macro_derive(ImplicitClone)]
pub fn derive_implicit_clone(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
let syn::ItemStruct { ident, .. } = syn::parse_macro_input!(item as syn::ItemStruct);
let res = quote! {
impl ::implicit_clone::ImplicitClone for #ident {}
};
res.into()
}
13 changes: 13 additions & 0 deletions implicit-clone-derive/tests/function_attr_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[allow(dead_code)]
#[test]
fn tests_pass() {
let t = trybuild::TestCases::new();
t.pass("tests/function_component_attr/*-pass.rs");
}

#[allow(dead_code)]
#[rustversion::attr(stable(1.64), test)]
fn tests_fail() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/function_component_attr/*-fail.rs");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use implicit_clone::ImplicitClone;

#[derive(ImplicitClone)]
pub struct NotClonableStruct;

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0277]: the trait bound `NotClonableStruct: Clone` is not satisfied
--> tests/function_component_attr/derive-fail.rs:3:10
|
3 | #[derive(ImplicitClone)]
| ^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NotClonableStruct`
|
note: required by a bound in `ImplicitClone`
--> $WORKSPACE/src/lib.rs
|
| pub trait ImplicitClone: Clone {
| ^^^^^ required by this bound in `ImplicitClone`
= note: this error originates in the derive macro `ImplicitClone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NotClonableStruct` with `#[derive(Clone)]`
|
4 | #[derive(Clone)]
|
44 changes: 44 additions & 0 deletions implicit-clone-derive/tests/function_component_attr/derive-pass.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![no_implicit_prelude]

// Shadow primitives
#[allow(non_camel_case_types)]
pub struct bool;
#[allow(non_camel_case_types)]
pub struct char;
#[allow(non_camel_case_types)]
pub struct f32;
#[allow(non_camel_case_types)]
pub struct f64;
#[allow(non_camel_case_types)]
pub struct i128;
#[allow(non_camel_case_types)]
pub struct i16;
#[allow(non_camel_case_types)]
pub struct i32;
#[allow(non_camel_case_types)]
pub struct i64;
#[allow(non_camel_case_types)]
pub struct i8;
#[allow(non_camel_case_types)]
pub struct isize;
#[allow(non_camel_case_types)]
pub struct str;
#[allow(non_camel_case_types)]
pub struct u128;
#[allow(non_camel_case_types)]
pub struct u16;
#[allow(non_camel_case_types)]
pub struct u32;
#[allow(non_camel_case_types)]
pub struct u64;
#[allow(non_camel_case_types)]
pub struct u8;
#[allow(non_camel_case_types)]
pub struct usize;

#[derive(Clone, ::implicit_clone::ImplicitClone)]
struct ExampleStruct;

fn main() {
let _ = ::implicit_clone::ImplicitClone::implicit_clone(&ExampleStruct);
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub mod sync;
/// Single-threaded version of immutable types.
pub mod unsync;

#[cfg(feature = "implicit-clone-derive")]
pub use implicit_clone_derive::*;

/// Marker trait for cheap-to-clone types that should be allowed to be cloned implicitly.
///
/// Enables host libraries to have the same syntax as [`Copy`] while calling the [`Clone`]
Expand Down

0 comments on commit a5d36aa

Please sign in to comment.