Skip to content

Commit

Permalink
Use const fn for Constructor and IsVariant derives (#218, #131)
Browse files Browse the repository at this point in the history
Co-authored-by: Kai Ren <[email protected]>
  • Loading branch information
fmiguelgarcia and tyranron authored Jan 31, 2023
1 parent 9014b18 commit 273b947
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 17 deletions.
8 changes: 3 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ matrix.msrv }}
- run: rustup default ${{ matrix.msrv }}
toolchain: nightly
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: nightly
toolchain: ${{ matrix.msrv }}

- name: Install minimal dependencies versions
run: cargo +nightly update -Z minimal-versions

- run: cargo test --workspace --features full,testing-helpers
-- --skip compile_fail

no_std:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -111,7 +111,6 @@ jobs:
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
- run: rustup default ${{ matrix.toolchain }}

- run: cargo test --workspace --features testing-helpers

Expand All @@ -123,7 +122,6 @@ jobs:
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: nightly
- run: rustup default nightly

- name: Install tomljson
run: |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `FromStr` derive support for enums that contain variants without fields.
If you pass the name of the variant to `from_str` it will create the matching
variant.
- Use `const fn` in `Constructor` and `IsVariant` derives.

### Improvements

Expand Down
4 changes: 2 additions & 2 deletions impl/doc/constructor.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Code like this will be generated:
```rust
# struct MyInts(i32, i32);
impl MyInts {
pub fn new(__0: i32, __1: i32) -> MyInts {
pub const fn new(__0: i32, __1: i32) -> MyInts {
MyInts(__0, __1)
}
}
Expand Down Expand Up @@ -60,7 +60,7 @@ Code like this will be generated:
# y: i32,
# }
impl Point2D {
pub fn new(x: i32, y: i32) -> Point2D {
pub const fn new(x: i32, y: i32) -> Point2D {
Point2D { x: x, y: y }
}
}
Expand Down
4 changes: 2 additions & 2 deletions impl/doc/is_variant.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ The derive in the above example code generates the following code:
# Nothing
# }
impl <T> Maybe<T>{
pub fn is_just(&self) -> bool {
pub const fn is_just(&self) -> bool {
match self {Self::Just(..) => true, _ => false}
}
pub fn is_nothing(&self) -> bool {
pub const fn is_nothing(&self) -> bool {
match self {Self::Nothing => true, _ => false}
}
}
Expand Down
2 changes: 1 addition & 1 deletion impl/src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn expand(input: &DeriveInput, _: &str) -> TokenStream {
#[automatically_derived]
impl #impl_generics #input_type #ty_generics #where_clause {
#[inline]
pub fn new(#(#vars: #original_types),*) -> #input_type #ty_generics {
pub const fn new(#(#vars: #original_types),*) -> #input_type #ty_generics {
#body
}
}
Expand Down
2 changes: 1 addition & 1 deletion impl/src/is_variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
#[doc = "Returns `true` if this value is of type `"]
#[doc = #variant_name]
#[doc = "`. Returns `false` otherwise"]
pub fn #fn_name(&self) -> bool {
pub const fn #fn_name(&self) -> bool {
match self {
#enum_name ::#variant_ident #data_pattern => true,
_ => false
Expand Down
2 changes: 1 addition & 1 deletion impl/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ fn identifier(input: &str) -> Option<(LeftToParse<'_>, Identifier<'_>)> {
/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
fn integer(input: &str) -> Option<(LeftToParse<'_>, usize)> {
and_then(
take_while1(check_char(|c| matches!(c, '0'..='9'))),
take_while1(check_char(|c| c.is_ascii_digit())),
|(i, int)| int.parse().ok().map(|int| (i, int)),
)(input)
}
Expand Down
10 changes: 10 additions & 0 deletions tests/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,27 @@ use derive_more::Constructor;
#[derive(Constructor)]
struct EmptyTuple();

const EMPTY_TUPLE: EmptyTuple = EmptyTuple::new();

#[derive(Constructor)]
struct EmptyStruct {}

const EMPTY_STRUCT: EmptyStruct = EmptyStruct::new();

#[derive(Constructor)]
struct EmptyUnit;

const EMPTY_UNIT: EmptyUnit = EmptyUnit::new();

#[derive(Constructor)]
struct MyInts(i32, i32);

const MY_INTS: MyInts = MyInts::new(1, 2);

#[derive(Constructor)]
struct Point2D {
x: i32,
y: i32,
}

const POINT_2D: Point2D = Point2D::new(-4, 7);
116 changes: 111 additions & 5 deletions tests/is_variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,59 @@ enum Either<TLeft, TRight> {
Right(TRight),
}

const _: () = {
let either: Either<u8, i16> = Either::Right(7);
assert!(either.is_right());
assert!(!either.is_left());

let either: Either<u8, i16> = Either::Left(7);
assert!(!either.is_right());
assert!(either.is_left());
};

#[derive(IsVariant)]
enum Maybe<T> {
Nothing,
Just(T),
}

const _: () = {
let maybe: Maybe<u8> = Maybe::Just(7);
assert!(maybe.is_just());
assert!(!maybe.is_nothing());

let maybe: Maybe<u8> = Maybe::Nothing;
assert!(!maybe.is_just());
assert!(maybe.is_nothing());
};

#[test]
pub fn test_is_variant() {
assert!(Maybe::<()>::Nothing.is_nothing());
assert!(!Maybe::<()>::Nothing.is_just());
}

#[derive(IsVariant)]
enum Color {
RGB(u8, u8, u8),
CMYK { c: u8, m: u8, y: u8, k: u8 },
}

const _: () = {
let color = Color::RGB(0, 0, 0);
assert!(color.is_rgb());
assert!(!color.is_cmyk());

let color = Color::CMYK {
c: 0,
m: 0,
y: 0,
k: 0,
};
assert!(!color.is_rgb());
assert!(color.is_cmyk());
};

#[derive(IsVariant)]
enum Nonsense<'a, T> {
Ref(&'a T),
Expand All @@ -28,6 +69,16 @@ enum Nonsense<'a, T> {
NoRefIgnored,
}

const _: () = {
let nonsense: Nonsense<u8> = Nonsense::Ref(&7);
assert!(nonsense.is_ref());
assert!(!nonsense.is_no_ref());

let nonsense: Nonsense<u8> = Nonsense::NoRef;
assert!(!nonsense.is_ref());
assert!(nonsense.is_no_ref());
};

#[derive(IsVariant)]
enum WithConstraints<T>
where
Expand All @@ -36,6 +87,17 @@ where
One(T),
Two,
}

const _: () = {
let wc: WithConstraints<u8> = WithConstraints::One(1);
assert!(wc.is_one());
assert!(!wc.is_two());

let wc: WithConstraints<u8> = WithConstraints::Two;
assert!(!wc.is_one());
assert!(wc.is_two());
};

#[derive(IsVariant)]
enum KitchenSink<'a, 'b, T1: Copy, T2: Clone>
where
Expand All @@ -49,8 +111,52 @@ where
NothingToSeeHere {},
}

#[test]
pub fn test_is_variant() {
assert!(Maybe::<()>::Nothing.is_nothing());
assert!(!Maybe::<()>::Nothing.is_just());
}
const _: () = {
let ks: KitchenSink<u16, u8> = KitchenSink::Left(&1);
assert!(ks.is_left());
assert!(!ks.is_right());
assert!(!ks.is_own_both());
assert!(!ks.is_empty());
assert!(!ks.is_never_mind());
assert!(!ks.is_nothing_to_see_here());

let ks: KitchenSink<u16, u8> = KitchenSink::Right(&1);
assert!(!ks.is_left());
assert!(ks.is_right());
assert!(!ks.is_own_both());
assert!(!ks.is_empty());
assert!(!ks.is_never_mind());
assert!(!ks.is_nothing_to_see_here());

let ks: KitchenSink<u16, u8> = KitchenSink::OwnBoth { left: 1, right: 2 };
assert!(!ks.is_left());
assert!(!ks.is_right());
assert!(ks.is_own_both());
assert!(!ks.is_empty());
assert!(!ks.is_never_mind());
assert!(!ks.is_nothing_to_see_here());

let ks: KitchenSink<u16, u8> = KitchenSink::Empty;
assert!(!ks.is_left());
assert!(!ks.is_right());
assert!(!ks.is_own_both());
assert!(ks.is_empty());
assert!(!ks.is_never_mind());
assert!(!ks.is_nothing_to_see_here());

let ks: KitchenSink<u16, u8> = KitchenSink::NeverMind();
assert!(!ks.is_left());
assert!(!ks.is_right());
assert!(!ks.is_own_both());
assert!(!ks.is_empty());
assert!(ks.is_never_mind());
assert!(!ks.is_nothing_to_see_here());

let ks: KitchenSink<u16, u8> = KitchenSink::NothingToSeeHere {};
assert!(!ks.is_left());
assert!(!ks.is_right());
assert!(!ks.is_own_both());
assert!(!ks.is_empty());
assert!(!ks.is_never_mind());
assert!(ks.is_nothing_to_see_here());
};

0 comments on commit 273b947

Please sign in to comment.