Skip to content

Commit

Permalink
Merge pull request #20 from alecmocatta/update-docs
Browse files Browse the repository at this point in the history
Statically assert idents inferred to be variables aren't nameable types
  • Loading branch information
mergify[bot] authored Nov 5, 2019
2 parents 9450a9b + 06fbfb8 commit 05caba4
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 79 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[*]
tab_width = 4

[.*]
tab_width = 4
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "serde_closure"
version = "0.2.5"
version = "0.2.6"
license = "MIT OR Apache-2.0"
authors = ["Alec Mocatta <[email protected]>"]
categories = ["development-tools","encoding","rust-patterns","network-programming"]
Expand All @@ -14,7 +14,7 @@ This library provides macros that wrap closures to make them serializable and de
"""
repository = "https://github.com/alecmocatta/serde_closure"
homepage = "https://github.com/alecmocatta/serde_closure"
documentation = "https://docs.rs/serde_closure/0.2.5"
documentation = "https://docs.rs/serde_closure/0.2.6"
readme = "README.md"
edition = "2018"

Expand All @@ -23,7 +23,7 @@ azure-devops = { project = "alecmocatta/serde_closure", pipeline = "tests" }
maintenance = { status = "actively-developed" }

[dependencies]
serde_closure_derive = { version = "=0.2.5", path = "serde_closure_derive" }
serde_closure_derive = { version = "=0.2.6", path = "serde_closure_derive" }
serde = { version = "1.0", features = ["derive"] }
proc-macro-hack = "0.5"

Expand Down
76 changes: 40 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![MIT / Apache 2.0 licensed](https://img.shields.io/crates/l/serde_closure.svg?maxAge=2592000)](#License)
[![Build Status](https://dev.azure.com/alecmocatta/serde_closure/_apis/build/status/tests?branchName=master)](https://dev.azure.com/alecmocatta/serde_closure/_build/latest?branchName=master)

[Docs](https://docs.rs/serde_closure/0.2.5)
[Docs](https://docs.rs/serde_closure/0.2.6)

Serializable and debuggable closures.

Expand All @@ -30,9 +30,9 @@ requires nightly Rust for the `unboxed_closures` and `fn_traits` features (rust
issue [#29625](https://github.com/rust-lang/rust/issues/29625)).

* There are three macros,
[`FnOnce`](https://docs.rs/serde_closure/0.2.5/serde_closure/macro.FnOnce.html),
[`FnMut`](https://docs.rs/serde_closure/0.2.5/serde_closure/macro.FnMut.html)
and [`Fn`](https://docs.rs/serde_closure/0.2.5/serde_closure/macro.Fn.html),
[`FnOnce`](https://docs.rs/serde_closure/0.2.6/serde_closure/macro.FnOnce.html),
[`FnMut`](https://docs.rs/serde_closure/0.2.6/serde_closure/macro.FnMut.html)
and [`Fn`](https://docs.rs/serde_closure/0.2.6/serde_closure/macro.Fn.html),
corresponding to the three types of Rust closure.
* Wrap your closure with one of the macros and it will now implement `Copy`,
`Clone`, `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`, `Serialize`,
Expand Down Expand Up @@ -86,44 +86,45 @@ FnMut!(move |name| {

## Limitations
There are currently some minor limitations:
* Captured variables with an uppercase first letter need to be explicitly
captured. If you see a panic like the following, fix the case of the
variable.
```text
thread 'main' panicked at 'A variable with an upper case first letter was implicitly captured.
Unfortunately due to current limitations it must be captured explicitly.
Please refer to the README.', tests/test.rs:205:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```
* Functions called inside the closure might need to be disambiguated. This
also affects enum unit and tuple variants with a lowercase first letter.
If you see an error like either of the following, qualify `my_function`
as `self::my_function` and `my_enum_variant` as
`MyEnum::my_enum_variant`.

* Use of types that start with a lowercase letter need might need to be
disambiguated from variables. If you see an error like the following, fix the
case of the type, or append it with `my_struct::<>` to disambiguate.
```text
error[E0277]: the trait bound `fn(usize) -> std::option::Option<usize> {my_function::<usize>}: fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not satisfied
--> tests/test.rs:327:10
error[E0308]: mismatched types
--> tests/test.rs:450:4
|
449 | FnOnce!(move || {
| _____-
450 | | my_struct;
| | ^^^^^^^^^ expected struct `serde_closure::internal::a_variable`, found struct `my_struct`
451 | | });
| |______- in this macro invocation
|
314 | fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
| ------
315 | where
316 | F: Fn(&mut St) -> Option<A> + Serialize,
| --------- required by this bound in `fnref::unfold`
...
327 | let _ = unfold(0_usize, Fn!(|acc: &mut _| my_function(*acc)));
| ^^^^^^ the trait `fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not implemented for `fn(usize) -> std::option::Option<usize> {my_function::<usize>}`
= note: expected type `serde_closure::internal::a_variable`
found type `my_struct`
```

* Use of variables that start with an uppercase letter might need to be
disambiguated from types. If you see an error like the following, fix the
case of the variable, or wrap it with `(MyVariable)` to disambiguate.
```text
error[E0530]: function parameters cannot shadow tuple variants
--> tests/test.rs:173:47
error: imports cannot refer to local variables
--> tests/test.rs:422:3
|
417 | FnOnce!(move || {
| _____-
418 | | MyVariable;
| | ^^^^^^^^^^
419 | | });
| |______- in this macro invocation
|
173 | FnMut!(|acc: &mut _| my_enum_variant(*acc))
| ---------------------^^^^^^^^^^^^^^^-------
| | |
| | cannot be named the same as a tuple variant
| in this macro invocation
```

* Functions and closures called inside the closure might need to be
disambiguated. This can be done the same as above with `function::<>` for
functions and `(closure)` for closures.

## Serializing between processes

Closures created by this crate are unnameable – i.e. just like normal closures,
Expand All @@ -140,7 +141,10 @@ processes running the same binary.
For example, if you have multiple forks of a process, or the same binary running
on each of a cluster of machines,
[`serde_traitobject`](https://github.com/alecmocatta/serde_traitobject) would
help you to send serializable closures between them.
help you to send serializable closures between them. This can be done by
upcasting the closure to a `Box<dyn serde_traitobject::Fn()>`, which is
automatically serializable and deserializable with
[`serde`](https://github.com/serde-rs/serde).

## License
Licensed under either of
Expand Down
4 changes: 2 additions & 2 deletions serde_closure_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "serde_closure_derive"
version = "0.2.5"
version = "0.2.6"
license = "MIT OR Apache-2.0"
authors = ["Alec Mocatta <[email protected]>"]
categories = ["development-tools","encoding","rust-patterns","network-programming"]
Expand All @@ -14,7 +14,7 @@ See https://crates.io/crates/serde_closure for documentation.
"""
repository = "https://github.com/alecmocatta/serde_closure"
homepage = "https://github.com/alecmocatta/serde_closure"
documentation = "https://docs.rs/serde_closure/0.2.5"
documentation = "https://docs.rs/serde_closure/0.2.6"
edition = "2018"

[badges]
Expand Down
11 changes: 7 additions & 4 deletions serde_closure_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! See [`serde_closure`](https://docs.rs/serde_closure/) for
//! documentation.
#![doc(html_root_url = "https://docs.rs/serde_closure_derive/0.2.5")]
#![doc(html_root_url = "https://docs.rs/serde_closure_derive/0.2.6")]
#![feature(proc_macro_diagnostic)]
#![allow(non_snake_case)] // due to proc-macro-hack can't apply this directly

Expand Down Expand Up @@ -404,6 +404,10 @@ fn impl_fn_once(closure: Closure, kind: Kind) -> Result<TokenStream, Error> {
#fn_impl
}

{
#(let #env_variables = ::serde_closure::internal::a_variable;)*
}

let mut #ret_name = #impls_name::#name::new(#env_capture);
let #env_types_name = ::serde_closure::internal::to_phantom(&#ret_name);

Expand Down Expand Up @@ -716,11 +720,10 @@ impl<'a> State<'a> {
expr: Box::new(a),
});
} else {
let mut path_segment: PathSegment = (*path_segment).clone();
path_segment.arguments = PathArguments::None;
let ident = (*ident).clone();
*expr = parse2(quote_spanned! { expr.span() =>
({
use #path_segment;
use #ident;
fn eq<T>(a: T, b: T) -> T { a }
eq(#expr, #expr)
})
Expand Down
79 changes: 45 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,44 +104,45 @@
//!
//! # Limitations
//! There are currently some minor limitations:
//! * Captured variables with an uppercase first letter need to be explicitly
//! captured. If you see a panic like the following, fix the case of the
//! variable.
//! ```text
//! thread 'main' panicked at 'A variable with an upper case first letter was implicitly captured.
//! Unfortunately due to current limitations it must be captured explicitly.
//! Please refer to the README.', tests/test.rs:205:10
//! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
//! ```
//! * Functions called inside the closure might need to be disambiguated. This
//! also affects enum unit and tuple variants with a lowercase first letter.
//! If you see an error like either of the following, qualify `my_function`
//! as `self::my_function` and `my_enum_variant` as
//! `MyEnum::my_enum_variant`.
//!
//! * Use of types that start with a lowercase letter need might need to be
//! disambiguated from variables. If you see an error like the following, fix
//! the case of the type, or append it with `my_struct::<>` to disambiguate.
//! ```text
//! error[E0277]: the trait bound `fn(usize) -> std::option::Option<usize> {my_function::<usize>}: fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not satisfied
//! --> tests/test.rs:327:10
//! error[E0308]: mismatched types
//! --> tests/test.rs:450:4
//! |
//! 449 | FnOnce!(move || {
//! | _____-
//! 450 | | my_struct;
//! | | ^^^^^^^^^ expected struct `serde_closure::internal::a_variable`, found struct `my_struct`
//! 451 | | });
//! | |______- in this macro invocation
//! |
//! 314 | fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
//! | ------
//! 315 | where
//! 316 | F: Fn(&mut St) -> Option<A> + Serialize,
//! | --------- required by this bound in `fnref::unfold`
//! ...
//! 327 | let _ = unfold(0_usize, Fn!(|acc: &mut _| my_function(*acc)));
//! | ^^^^^^ the trait `fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not implemented for `fn(usize) -> std::option::Option<usize> {my_function::<usize>}`
//! = note: expected type `serde_closure::internal::a_variable`
//! found type `my_struct`
//! ```
//!
//! * Use of variables that start with an uppercase letter might need to be
//! disambiguated from types. If you see an error like the following, fix the
//! case of the variable, or wrap it with `(MyVariable)` to disambiguate.
//! ```text
//! error[E0530]: function parameters cannot shadow tuple variants
//! --> tests/test.rs:173:47
//! error: imports cannot refer to local variables
//! --> tests/test.rs:422:3
//! |
//! 417 | FnOnce!(move || {
//! | _____-
//! 418 | | MyVariable;
//! | | ^^^^^^^^^^
//! 419 | | });
//! | |______- in this macro invocation
//! |
//! 173 | FnMut!(|acc: &mut _| my_enum_variant(*acc))
//! | ---------------------^^^^^^^^^^^^^^^-------
//! | | |
//! | | cannot be named the same as a tuple variant
//! | in this macro invocation
//! ```
//!
//! * Functions and closures called inside the closure might need to be
//! disambiguated. This can be done the same as above with `function::<>` for
//! functions and `(closure)` for closures.
//!
//! # Serializing between processes
//!
//! Closures created by this crate are unnameable – i.e. just like normal
Expand All @@ -158,9 +159,12 @@
//! For example, if you have multiple forks of a process, or the same binary
//! running on each of a cluster of machines,
//! [`serde_traitobject`](https://github.com/alecmocatta/serde_traitobject)
//! would help you to send serializable closures between them.
//! would help you to send serializable closures between them. This can be done
//! by upcasting the closure to a `Box<dyn serde_traitobject::Fn()>`, which is
//! automatically serializable and deserializable with
//! [`serde`](https://github.com/serde-rs/serde).
#![doc(html_root_url = "https://docs.rs/serde_closure/0.2.5")]
#![doc(html_root_url = "https://docs.rs/serde_closure/0.2.6")]
#![feature(unboxed_closures, fn_traits)]
#![warn(
missing_copy_implementations,
Expand Down Expand Up @@ -233,12 +237,19 @@ pub mod internal {

#[allow(missing_copy_implementations, missing_debug_implementations)]
pub struct ZeroSizedAssertion;

#[allow(
missing_copy_implementations,
missing_debug_implementations,
non_camel_case_types
)]
pub struct a_variable;
}

pub mod structs {
//! Structs representing a serializable closure, created by the
//! [`FnOnce`](macro@FnOnce), [`FnMut`](macro@FnMut) and [`Fn`](macro@Fn)
//! macros. They Implement [`std::ops::FnOnce`], [`std::ops::FnMut`] and
//! macros. They implement [`std::ops::FnOnce`], [`std::ops::FnMut`] and
//! [`std::ops::Fn`] respectively, as well as [`Debug`](std::fmt::Debug),
//! [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize),
//! and various convenience traits.
Expand Down

0 comments on commit 05caba4

Please sign in to comment.