Skip to content

Commit

Permalink
Relax enum default case expansion rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Artem-Romanenia committed Jan 11, 2025
1 parent 36ffba2 commit 11738d4
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
12 changes: 4 additions & 8 deletions o2o-impl/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,10 @@ fn enum_init_block(input: &Enum, ctx: &ImplContext) -> TokenStream {
.flat_map(|x| &x.attr.ghost_data)
.map(VariantData::GhostData));

enum_init_block_inner(&mut fields.iter().peekable(), input, ctx)
enum_init_block_inner(&mut fields.iter().peekable(), ctx)
}

fn enum_init_block_inner(members: &mut Peekable<Iter<VariantData>>, input: &Enum, ctx: &ImplContext) -> TokenStream {
fn enum_init_block_inner(members: &mut Peekable<Iter<VariantData>>, ctx: &ImplContext) -> TokenStream {
let mut fragments: Vec<TokenStream> = vec![];

while let Some(member_data) = members.peek() {
Expand Down Expand Up @@ -443,12 +443,8 @@ fn enum_init_block_inner(members: &mut Peekable<Iter<VariantData>>, input: &Enum
}

if let Some(default_case) = &ctx.struct_attr.default_case {
if ctx.kind.is_from() && (input.variants.iter().any(|v| v.attrs.lit(&ctx.struct_attr.ty).is_some() || v.attrs.pat(&ctx.struct_attr.ty).is_some()) || input.attrs.ghosts_attr(&ctx.struct_attr.ty, &ctx.kind).is_some())
|| !ctx.kind.is_from() && input.variants.iter().any(|v| v.attrs.ghost(&ctx.struct_attr.ty, &ctx.kind).is_some())
{
let g = quote_action(default_case, None, ctx);
fragments.push(quote!(_ #g))
}
let g = quote_action(default_case, None, ctx);
fragments.push(quote!(_ #g))
}

quote!({#(#fragments)*})
Expand Down
1 change: 1 addition & 0 deletions o2o-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ anyhow = "1.0.86"
test-case = "3"

[features]
default = ["syn1"]
syn1 = ["o2o/syn1"]
syn2 = ["o2o/syn2"]
53 changes: 53 additions & 0 deletions o2o-tests/tests/48_enum_default_case_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use test_case::test_case;

#[derive(Debug, PartialEq, Clone)]
pub enum Enum {
Opt1,
Opt2,
Opt3
}

#[derive(Debug, PartialEq, o2o::o2o)]
#[map_owned(Enum| _ => todo!("unknown"))]
enum EnumDto {
Opt1,
Opt2,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Enum2 {
Opt1,
Opt2,
Opt3
}

#[derive(Debug, PartialEq, o2o::o2o)]
#[from_owned(Enum2| _ => EnumDto2::Opt1)]
enum EnumDto2 {
Opt1,
Opt2,
}

#[test_case(Enum::Opt1, EnumDto::Opt1)]
#[test_case(Enum::Opt2, EnumDto::Opt2)]
fn legit_options(l: Enum, r: EnumDto) {
let e: EnumDto = l.clone().into();
assert_eq!(r, e);

let e: Enum = r.into();
assert_eq!(l, e);
}

#[test]
#[should_panic(expected = "unknown")]
fn default_case() {
let _: EnumDto = Enum::Opt3.into();
}

#[test_case(Enum2::Opt1, EnumDto2::Opt1)]
#[test_case(Enum2::Opt2, EnumDto2::Opt2)]
#[test_case(Enum2::Opt3, EnumDto2::Opt1)]
fn legit_options_2(l: Enum2, r: EnumDto2) {
let e: EnumDto2 = l.clone().into();
assert_eq!(r, e);
}
53 changes: 53 additions & 0 deletions o2o-tests/tests/48_enum_default_case_tests_fallible.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use test_case::test_case;

#[derive(Debug, PartialEq, Clone)]
pub enum Enum {
Opt1,
Opt2,
Opt3
}

#[derive(Debug, PartialEq, o2o::o2o)]
#[try_map_owned(Enum, String| _ => todo!("unknown"))]
enum EnumDto {
Opt1,
Opt2,
}

#[derive(Debug, PartialEq, Clone)]
pub enum Enum2 {
Opt1,
Opt2,
Opt3
}

#[derive(Debug, PartialEq, o2o::o2o)]
#[try_from_owned(Enum2, String| _ => EnumDto2::Opt1)]
enum EnumDto2 {
Opt1,
Opt2,
}

#[test_case(Enum::Opt1, EnumDto::Opt1)]
#[test_case(Enum::Opt2, EnumDto::Opt2)]
fn legit_options(l: Enum, r: EnumDto) {
let e: EnumDto = l.clone().try_into().unwrap();
assert_eq!(r, e);

let e: Enum = r.try_into().unwrap();
assert_eq!(l, e);
}

#[test]
#[should_panic(expected = "unknown")]
fn default_case() {
let _: EnumDto = Enum::Opt3.try_into().unwrap();
}

#[test_case(Enum2::Opt1, EnumDto2::Opt1)]
#[test_case(Enum2::Opt2, EnumDto2::Opt2)]
#[test_case(Enum2::Opt3, EnumDto2::Opt1)]
fn legit_options_2(l: Enum2, r: EnumDto2) {
let e: EnumDto2 = l.clone().try_into().unwrap();
assert_eq!(r, e);
}
4 changes: 2 additions & 2 deletions tests.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cargo test -q -p o2o
cargo test -q -p o2o --no-default-features --features syn1
cargo test -q -p o2o --no-default-features --features syn2
cargo test -q -p o2o-tests --features syn1
cargo test -q -p o2o-tests --features syn2
cargo test -q -p o2o-tests --no-default-features --features syn1
cargo test -q -p o2o-tests --no-default-features --features syn2
cargo test -q -p o2o-impl --features syn
cargo test -q -p o2o-impl --features syn2

0 comments on commit 11738d4

Please sign in to comment.