Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AUTO : Forward from derives_refactoring to alpha #1368

Merged
merged 49 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
afd97a3
derive_tools : rearrange tests
Wandalen Jun 1, 2024
3815eba
derive_tools : evolving derive new
Wandalen Jun 1, 2024
fd3ad59
derive_tools : evolving derive new
Wandalen Jun 1, 2024
58be910
macro_tools : iterators experiment
Wandalen Jun 1, 2024
ca82483
former : better description, avoiding confusing mentioning Former trait
Wandalen Jun 1, 2024
82cbf47
derive_tools : evolving derive new
Wandalen Jun 1, 2024
8754d78
former_types-v2.3.0
Wandalen Jun 1, 2024
bfd8197
macro_tools-v0.29.0
Wandalen Jun 1, 2024
f1e74ea
experimenting with deps
Wandalen Jun 1, 2024
0025f0b
former_types-v2.4.0
Wandalen Jun 1, 2024
11f61bc
macro_tools-v0.30.0
Wandalen Jun 1, 2024
277be76
publishing
Wandalen Jun 1, 2024
9d8ee00
publishing
Wandalen Jun 1, 2024
11ffe76
publishing
Wandalen Jun 1, 2024
9d1e4ed
Merge branch 'alpha' into derives_refactoring
Wandalen Jun 1, 2024
a7f8bfa
macro_tools : clonable iterator wip
Wandalen Jun 2, 2024
5727a73
macro_tools : clonable iterator wip
Wandalen Jun 2, 2024
e2001cf
clone_dyn : fixing it
Wandalen Jun 2, 2024
a7bf9fc
clone_dyn : fixing it
Wandalen Jun 3, 2024
fd262d4
clone_dyn : fixing it
Wandalen Jun 3, 2024
739b528
clone_dyn : fixing it
Wandalen Jun 3, 2024
a0d18cb
clone_dyn : fixing it
Wandalen Jun 3, 2024
2d0621f
clone_dyn : fixing it
Wandalen Jun 3, 2024
5aa4448
clone_dyn : fixing it
Wandalen Jun 3, 2024
1839054
clone_dyn : fixing it
Wandalen Jun 4, 2024
616808a
format_tools : experimenting with field iterator
Wandalen Jun 8, 2024
8c48ba4
format_tools : experimenting with field iterator
Wandalen Jun 8, 2024
0afd13e
format_tools : experimenting with field iterator
Wandalen Jun 9, 2024
1ffbc91
Merge branch 'alpha' into derives_refactoring
Wandalen Jun 9, 2024
e5df1cd
macro_tools : integrating clone_dyn
Wandalen Jun 9, 2024
a073873
clone_dyn_types : fix
Wandalen Jun 9, 2024
2fe8096
clone_dyn : cleaning
Wandalen Jun 9, 2024
2e958a3
clone_dyn : cleaning
Wandalen Jun 9, 2024
5286893
clone_dyn, derive_tools : cleaning
Wandalen Jun 9, 2024
e55a651
collection_tools-v0.9.0
Wandalen Jun 10, 2024
30faa10
former_types-v2.5.0
Wandalen Jun 10, 2024
0caac96
clone_dyn_types-v0.19.0
Wandalen Jun 10, 2024
c11d2d7
.
Wandalen Jun 10, 2024
df23ece
macro_tools-v0.31.0
Wandalen Jun 10, 2024
0d0be1d
iter_tools-v0.18.0
Wandalen Jun 10, 2024
5cb4fc6
former_meta-v2.4.0
Wandalen Jun 10, 2024
4f2778f
former-v2.4.0
Wandalen Jun 10, 2024
51e08c0
Merge branch 'format_tools' into derives_refactoring
Wandalen Jun 10, 2024
7c60f49
Merge branch 'alpha' into derives_refactoring
Wandalen Jun 10, 2024
57a08c1
clone_dyn and clone_dyn_types completed
Wandalen Jun 10, 2024
9d3c16c
clone_dyn_types-v0.20.0
Wandalen Jun 10, 2024
e873b0c
macro_tools-v0.32.0
Wandalen Jun 10, 2024
06d4324
clone_dyn_meta-v0.19.0
Wandalen Jun 10, 2024
23937cf
clone_dyn-v0.19.0
Wandalen Jun 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/target
/node_modules
/.module
/.data
/package-lock.json
/Cargo.lock
/.vscode
Expand Down
22 changes: 14 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ default-features = false
features = [ "enabled" ]

[workspace.dependencies.collection_tools]
version = "~0.8.0"
version = "~0.9.0"
path = "module/core/collection_tools"
default-features = false

Expand Down Expand Up @@ -159,16 +159,22 @@ default-features = false
features = [ "enabled" ]

[workspace.dependencies.clone_dyn]
version = "~0.18.0"
version = "~0.19.0"
path = "module/core/clone_dyn"
default-features = false
features = [ "enabled" ]

[workspace.dependencies.clone_dyn_meta]
version = "~0.18.0"
version = "~0.19.0"
path = "module/core/clone_dyn_meta"
features = [ "enabled" ]

[workspace.dependencies.clone_dyn_types]
version = "~0.20.0"
path = "module/core/clone_dyn_types"
default-features = false
features = [ "enabled" ]


## mem

Expand All @@ -189,7 +195,7 @@ default-features = false
## iter

[workspace.dependencies.iter_tools]
version = "~0.17.0"
version = "~0.18.0"
path = "module/core/iter_tools"
default-features = false

Expand All @@ -207,7 +213,7 @@ path = "module/core/for_each"
default-features = false

[workspace.dependencies.former]
version = "~2.3.0"
version = "~2.4.0"
path = "module/core/former"
default-features = false

Expand All @@ -217,12 +223,12 @@ default-features = false
# default-features = false

[workspace.dependencies.former_meta]
version = "~2.3.0"
version = "~2.4.0"
path = "module/core/former_meta"
default-features = false

[workspace.dependencies.former_types]
version = "~2.4.0"
version = "~2.5.0"
path = "module/core/former_types"
default-features = false

Expand Down Expand Up @@ -267,7 +273,7 @@ default-features = false
## macro tools

[workspace.dependencies.macro_tools]
version = "~0.30.0"
version = "~0.32.0"
path = "module/core/macro_tools"
default-features = false

Expand Down
18 changes: 10 additions & 8 deletions module/core/clone_dyn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clone_dyn"
version = "0.18.0"
version = "0.19.0"
edition = "2021"
authors = [
"Kostiantyn Wandalen <[email protected]>",
Expand All @@ -23,18 +23,20 @@ workspace = true
[package.metadata.docs.rs]
features = [ "full" ]
all-features = false
# exclude = [ "/tests", "/examples", "-*" ]

[features]

default = [ "enabled" ]
full = [ "enabled" ]
no_std = []
use_alloc = [ "no_std" ]
enabled = [ "clone_dyn_meta/enabled" ]
default = [ "enabled", "clone_dyn_types", "clone_dyn_meta" ]
full = [ "enabled", "clone_dyn_types", "clone_dyn_meta" ]
enabled = []

clone_dyn_types = [ "dep:clone_dyn_types", "clone_dyn_types/enabled" ]
clone_dyn_meta = [ "dep:clone_dyn_meta", "clone_dyn_meta/enabled", "clone_dyn_types" ]

[dependencies]
clone_dyn_meta = { workspace = true }
clone_dyn_meta = { workspace = true, optional = true }
clone_dyn_types = { workspace = true, optional = true }

[dev-dependencies]
test_tools = { workspace = true }
inspect_type = { workspace = true, features = [ "full" ] }
197 changes: 188 additions & 9 deletions module/core/clone_dyn/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,207 @@ By default, Rust does not support cloning for trait objects due to the `Clone` t

### Alternative

There are few alternatives [dyn-clone](https://github.com/dtolnay/dyn-clone), [dyn-clonable](https://github.com/kardeiz/objekt-clonable). Unlike other options, this solution is more concise and demands less effort to use, all without compromising the quality of the outcome. Also, you can ask an inquiry and get answers, which is problematic in the case of alternatives.
There are few alternatives [dyn-clone](https://github.com/dtolnay/dyn-clone), [dyn-clonable](https://github.com/kardeiz/objekt-clonable). Unlike other options, this solution is more concise and demands less effort to use, all without compromising the quality of the outcome.

### Basic use-case
## Basic use-case

Demonstrates the usage of `clone_dyn` to enable cloning for trait objects.

By default, Rust does not support cloning for trait objects due to the `Clone` trait
requiring compile-time knowledge of the type's size. The `clone_dyn` crate addresses
this limitation through procedural macros, allowing for cloning collections of trait objects.

##### Overview

This example shows how to use the `clone_dyn` crate to enable cloning for trait objects,
specifically for iterators. It defines a custom trait, `IterTrait`, that encapsulates
an iterator with specific characteristics and demonstrates how to use `CloneDyn` to
overcome the object safety constraints of the `Clone` trait.

##### The `IterTrait` Trait

The `IterTrait` trait is designed to represent iterators that yield references to items (`&'a T`).
These iterators must also implement the `ExactSizeIterator` and `DoubleEndedIterator` traits.
Additionally, the iterator must implement the `CloneDyn` trait, which allows cloning of trait objects.

The trait is implemented for any type that meets the specified requirements.

##### Cloning Trait Objects

Rust's type system does not allow trait objects to implement the `Clone` trait directly due to object safety constraints.
Specifically, the `Clone` trait requires knowledge of the concrete type at compile time, which is not available for trait objects.

The `CloneDyn` trait from the `clone_dyn` crate provides a workaround for this limitation by allowing trait objects to be cloned.
Procedural macros generates the necessary code for cloning trait objects, making it possible to clone collections of trait objects.

The example demonstrates how to implement `Clone` for boxed `IterTrait` trait objects.

##### `get_iter` Function

The `get_iter` function returns a boxed iterator that implements the `IterTrait` trait.
If the input is `Some`, it returns an iterator over the vector.
If the input is `None`, it returns an empty iterator.

It's not possible to use `impl Iterator` here because the code returns iterators of two different types:
- `std::slice::Iter` when the input is `Some`.
- `std::iter::Empty` when the input is `None`.

To handle this, the function returns a trait object ( `Box< dyn IterTrait >` ).
However, Rust's `Clone` trait cannot be implemented for trait objects due to object safety constraints.
The `CloneDyn` trait addresses this problem by enabling cloning of trait objects.

##### `use_iter` Function

The `use_iter` function demonstrates the use of the `CloneDyn` trait by cloning the iterator.
It then iterates over the cloned iterator and prints each element.

##### Main Function

The main function demonstrates the overall usage by creating a vector, obtaining an iterator, and using the iterator to print elements.

<!-- begin {{# generate.module( "example/clone_dyn_trivail.rs" ) #}} -->

```rust
# #[ cfg( all( feature = "enabled", any( not( feature = "no_std" ), feature = "use_alloc" ) ) ) ]
# #[ cfg( not( feature = "enabled" ) ) ]
# fn main() {}
# #[ cfg( feature = "enabled" ) ]
# fn main()
# {
use clone_dyn::clone_dyn;

use clone_dyn::{ clone_dyn, CloneDyn };

/// Trait that encapsulates an iterator with specific characteristics, tailored for your needs.
#[ clone_dyn ]
trait Trait1
pub trait IterTrait< 'a, T >
where
T : 'a,
Self : Iterator< Item = T > + ExactSizeIterator< Item = T > + DoubleEndedIterator,
// Self : CloneDyn,
// no need to explicitly to define this bound, because macro will do it for you anyway
{
}

impl< 'a, T, I > IterTrait< 'a, T > for I
where
T : 'a,
Self : Iterator< Item = T > + ExactSizeIterator< Item = T > + DoubleEndedIterator,
Self : CloneDyn,
{
}

///
/// Function to get an iterator over a vector of integers.
///
/// This function returns a boxed iterator that implements the `IterTrait` trait.
/// If the input is `Some`, it returns an iterator over the vector.
/// If the input is `None`, it returns an empty iterator.
///
/// Rust's type system does not allow trait objects to implement the `Clone` trait directly due to object safety constraints.
/// Specifically, the `Clone` trait requires knowledge of the concrete type at compile time, which is not available for trait objects.
///
/// In this example, we need to return an iterator that can be cloned. Since we are returning a trait object ( `Box< dyn IterTrait >` ),
/// we cannot directly implement `Clone` for this trait object. This is where the `CloneDyn` trait from the `clone_dyn` crate comes in handy.
///
/// The `CloneDyn` trait provides a workaround for this limitation by allowing trait objects to be cloned.
/// It uses procedural macros to generate the necessary code for cloning trait objects, making it possible to clone collections of trait objects.
///
/// It's not possible to use `impl Iterator` here because the code returns iterators of two different types:
/// - `std::slice::Iter` when the input is `Some`.
/// - `std::iter::Empty` when the input is `None`.
///
/// To handle this, the function returns a trait object (`Box<dyn IterTrait>`).
/// However, Rust's `Clone` trait cannot be implemented for trait objects due to object safety constraints.
/// The `CloneDyn` trait addresses this problem by enabling cloning of trait objects.

pub fn get_iter< 'a >( src : Option< &'a Vec< i32 > > ) -> Box< dyn IterTrait< 'a, &'a i32 > + 'a >
{
match &src
{
Some( src ) => Box::new( src.iter() ),
_ => Box::new( core::iter::empty() ),
}
}

let vec = Vec::< Box< dyn Trait1 > >::new();
let vec2 = vec.clone(); /* <- it does not work without `clone_dyn` */
/// Function to use an iterator and print its elements.
///
/// This function demonstrates the use of the `CloneDyn` trait by cloning the iterator.
/// It then iterates over the cloned iterator and prints each element.
pub fn use_iter< 'a >( iter : Box< dyn IterTrait< 'a, &'a i32 > + 'a > )
{
// Clone would not be available if CloneDyn is not implemented for the iterator.
// And being an object-safe trait, it can't implement Clone.
// Nevertheless, thanks to CloneDyn, the object is clonable.
//
// This line demonstrates cloning the iterator and iterating over the cloned iterator.
iter.clone().for_each( | e | println!( "{e}" ) );

// Iterate over the original iterator and print each element.
iter.for_each( | e | println!( "{e}" ) );
}

// Create a vector of integers.
let data = vec![ 1, 2, 3 ];
// Get an iterator over the vector.
let iter = get_iter( Some( &data ) );
// Use the iterator to print its elements.
use_iter( iter );

# }
```

<!-- end -->
<details>
<summary>If you use multithreading or asynchronous paradigms implement trait `Clone` also for `Send` and `Sync`</summary>

```rust, ignore

#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn::clone_into_box( &**self )
}
}

#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Send + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn::clone_into_box( &**self )
}
}

#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Sync + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn::clone_into_box( &**self )
}
}

#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Send + Sync + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn::clone_into_box( &**self )
}
}

```

</details>

<br/>

Try out `cargo run --example clone_dyn_trivial`.
<br/>
[See code](./examples/clone_dyn_trivial.rs).

### To add to your project

Expand Down
Loading
Loading