Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
fb569d3
Rework the way sealed items are handled
May 6, 2021
689b6cc
Implement snake case
May 6, 2021
eccd386
Add generic handling
May 6, 2021
9818f80
Update the dependencies
May 6, 2021
4ea39fb
Update the demo
May 6, 2021
8e20eed
Update the examples
May 6, 2021
5822901
Remove debug info
May 6, 2021
639f677
Update examples
May 6, 2021
52cc65d
Update tests
May 6, 2021
ec7f5f4
Add support for generics
May 6, 2021
55ee9e8
Add tests and examples for generics
May 6, 2021
e4560e3
Remove old comment
May 6, 2021
9d3f271
Bump version
May 6, 2021
713517c
Add tests for multiple traits
May 6, 2021
bb8969c
Update README
May 6, 2021
5e10596
Format
May 6, 2021
c322e7e
More format
May 6, 2021
0ec94e8
Fix version
May 6, 2021
68e8107
Use split_for_impl to avoid problems with where clauses
May 6, 2021
9ace5a6
Replace the macro with a function
May 6, 2021
568b426
Remove the heck dep
May 6, 2021
5c00a61
Remove comment
May 7, 2021
6c41596
Replace Display with fully qualified name
May 7, 2021
46e9472
Replace proc_macro2::TokenStream with TokenStream2
May 7, 2021
5569092
Bump versions
May 7, 2021
f336c99
Revert back to heck
May 7, 2021
170df32
Address raw idents
May 7, 2021
7e51a1c
Format Cargo.toml
May 7, 2021
ec25165
Address clippy::unnecessary-wraps
May 7, 2021
99c5141
Update examples comments
May 7, 2021
07900bd
Remove bound usage since it can break #seal
May 7, 2021
1c787dd
Add automatically_derived attribute
May 7, 2021
18f88cc
Typo fix
May 7, 2021
9b53b0d
Change resolver to v2
May 7, 2021
a158e38
Address raw idents
May 7, 2021
a9076a4
Make parse_sealed_impl return early
May 7, 2021
d8c1cd0
Shorten the seal
May 7, 2021
71f715c
Format
May 7, 2021
6330912
Update mini-docs
May 7, 2021
61c1af1
Apply clippy pedantic suggestions
May 7, 2021
ee0e196
Format tests
May 7, 2021
ed37d2a
Bring back the where clauses
May 10, 2021
f8e73fc
Add example
May 11, 2021
cb3eec6
Update example
May 11, 2021
b329e32
WIP - start implementing the erase arg
May 11, 2021
b82aa9a
Fix bug in erase
May 12, 2021
02dc84c
Update examples
May 12, 2021
81b845c
Add tests
May 12, 2021
234d893
Update library
May 12, 2021
7924217
Update README
May 12, 2021
d563403
Bump version
May 12, 2021
0609d80
Remove example with nightly features
May 12, 2021
32a1507
Remove feature
May 14, 2021
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
14 changes: 6 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sealed"
version = "0.1.3"
version = "0.2.0-rc3"
authors = ["José Duarte <jmg.duarte@campus.fct.unl.pt>"]
license = "MIT OR Apache-2.0"
description = "Macro for sealing traits and structures"
Expand All @@ -10,14 +10,11 @@ categories = ["development-tools", "rust-patterns"]
keywords = ["proc_macro", "sealed", "future-proofing"]
readme = "README.md"
edition = "2018"
exclude = [
"images/*"
]
exclude = ["images/*"]
resolver = "2"

[workspace]
members = [
"demo"
]
members = ["demo"]

[lib]
proc-macro = true
Expand All @@ -29,4 +26,5 @@ syn = { version = "1.0", features = ["extra-traits"] }
[dependencies]
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
proc-macro2 = "1.0"
proc-macro2 = "1.0"
heck = "0.3"
73 changes: 57 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ as described in the Rust API Guidelines [[1](https://rust-lang.github.io/api-gui

```toml
[dependencies]
sealed = "0.1"
sealed = "0.2.0-rc3"
```

## Example

In the following code structs `A` and `B` implement the sealed trait `T`,
the `C` struct, which is not sealed, will error during compilation.

You can see a demo in [`demo/`](demo/).
Examples are available in [`examples/`](examples/), you can also see a demo in [`demo/`](demo/).

```rust
use sealed::sealed;

#[sealed]
trait T {}

#[sealed]
pub struct A;

#[sealed]
impl T for A {}

#[sealed]
pub struct B;

#[sealed]
impl T for B {}

pub struct C;
Expand All @@ -45,25 +45,66 @@ fn main() {
}
```

## Attributes

This is the list of attributes that can be used along `#[sealed]`:
- `#[sealed]`: the main attribute macro, without attribute parameters.
- `#[sealed(erase)]`: this option turns on bound erasure. This is useful when using the `#[sealed]` macro inside a function.
For an example, see [`bound-erasure-fn`](tests/pass/08-bound-erasure-fn.rs).

## Details

The macro generates a `private` module when attached to a `trait`
(this raises the limitation that the `#[sealed]` macro can only be added to a single trait per module),
when attached to a `struct` the generated code simply implements the sealed trait for the respective structure.
The `#[sealed]` attribute can be attached to either a `trait` or an `impl`.
It supports:
- Several traits per module
- Generic parameters
- Foreign types
- Blanket `impl`s


## Expansion

### Expansion
### Input

```rust
// #[sealed]
// trait T {}
trait T: private::Sealed {}
mod private {
trait Sealed {}
use sealed::sealed;

#[sealed]
pub trait T {}

pub struct A;
pub struct B(i32);

#[sealed]
impl T for A {}
#[sealed]
impl T for B {}

fn main() {
return;
}
```

### Expanded

```rust
use sealed::sealed;

pub(crate) mod __seal_t {
pub trait Sealed {}
}
pub trait T: __seal_t::Sealed {}

// #[sealed]
// pub struct A;
pub struct A;
impl private::Sealed for A {}
pub struct B(i32);

impl __seal_t::Sealed for A {}
impl T for A {}

impl __seal_t::Sealed for B {}
impl T for B {}

fn main() {
return;
}
```
6 changes: 3 additions & 3 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ where
state: PhantomData<State>,
}

#[sealed]
pub struct Idle;
#[sealed]
impl DroneState for Idle {}

#[sealed]
pub struct Hovering;
#[sealed]
impl DroneState for Hovering {}

#[sealed]
pub struct Flying;
#[sealed]
impl DroneState for Flying {}

impl Drone<Idle> {
Expand Down
14 changes: 14 additions & 0 deletions examples/bound-erasure-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use sealed::sealed;

fn main() {
trait Foo {}
trait Bar {}

#[sealed(erase)]
trait Trait<T: ?Sized + Foo> {}

struct Implementor {}

#[sealed(erase)]
impl<T: ?Sized> Trait<T> for Implementor where T: Foo + Bar {}
}
5 changes: 5 additions & 0 deletions examples/bound-erasure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use sealed::sealed;
trait Foo {}
#[sealed(erase)]
trait Trait<T: ?Sized + Foo> {}
fn main() {}
15 changes: 15 additions & 0 deletions examples/generics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Test provided in #4
// https://github.com/jmg-duarte/sealed-rs/issues/4

use sealed::sealed;

#[sealed]
pub trait Set<V> {}

#[sealed]
impl<T> Set<Option<T>> for T {}

#[sealed]
impl<T> Set<Option<T>> for Option<T> {}

fn main() {}
27 changes: 27 additions & 0 deletions examples/nesting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use sealed::sealed;

mod lets {
pub mod attempt {
pub mod some {
pub mod nesting {
use sealed::sealed;
#[sealed]
pub trait LongerSnakeCaseType {}
}
}
}
}

pub struct A;

pub struct B(i32);

#[sealed]
impl lets::attempt::some::nesting::LongerSnakeCaseType for A {}

#[sealed]
impl lets::attempt::some::nesting::LongerSnakeCaseType for B {}

fn main() {
return;
}
12 changes: 12 additions & 0 deletions examples/raw-ident.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use sealed::sealed;

#[sealed]
pub trait r#Pub<V> {}

#[sealed]
impl<T> r#Pub<Option<T>> for T {}

#[sealed]
impl<T> r#Pub<Option<T>> for Option<T> {}

fn main() {}
16 changes: 16 additions & 0 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use sealed::sealed;

#[sealed]
pub trait T {}

pub struct A;
pub struct B(i32);

#[sealed]
impl T for A {}
#[sealed]
impl T for B {}

fn main() {
return;
}
44 changes: 44 additions & 0 deletions examples/syn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Example provided in #4
// https://github.com/jmg-duarte/sealed-rs/issues/4

use proc_macro2::*;
use sealed::sealed;
use syn::spanned::Spanned;

#[sealed]
pub trait AsSpan {
fn as_span(&self) -> Span;
}
// expands to:
// pub trait AsSpan: __seal_as_span::Sealed {
// fn as_span(&self) -> Span;
// }
// mod __seal_as_span {
// pub trait Sealed {}
// }

#[sealed]
impl AsSpan for Span {
fn as_span(&self) -> Self {
*self
}
}
// expands to:
// impl AsSpan for Span { // foreign type, cannot place #[sealed]
// fn as_span(&self) -> Self { *self }
// }
// impl __seal_as_span::Sealed for Span {}

#[sealed]
impl<T: Spanned> AsSpan for &T {
fn as_span(&self) -> Span {
self.span()
}
}
// expands to:
// impl<T: Spanned> AsSpan for &T {
// fn as_span(&self) -> Span { self.span() }
// }
// impl<T: Spanned> __seal_as_span::Sealed for &T {}

fn main() {}
Loading