Improve test for unwrapped nullable tag union bindgen

This commit is contained in:
Richard Feldman 2022-05-13 21:40:13 -04:00
parent d687c2397b
commit b2b5f8cf93
No known key found for this signature in database
GPG Key ID: 7E4127D1E4241798
2 changed files with 64 additions and 204 deletions

View File

@ -41,8 +41,13 @@ pub fn write_types(types: &Types, buf: &mut String) -> fmt::Result {
RocTagUnion::NullableWrapped { .. } => {
todo!();
}
RocTagUnion::NullableUnwrapped { .. } => {
todo!();
RocTagUnion::NullableUnwrapped {
name,
null_tag,
non_null_tag,
non_null_payload,
} => {
todo!("Write nullable unwrapped tag union.")
}
RocTagUnion::NonNullableUnwrapped { .. } => {
todo!();

View File

@ -526,234 +526,89 @@ fn cons_list_of_strings() {
r#"
#[derive(Clone, PartialEq, PartialOrd, Copy, Eq, Ord, Hash, Debug)]
#[repr(u8)]
pub enum tag_MyTagUnion {
Bar = 0,
Baz = 1,
Blah = 2,
Foo = 3,
pub enum tag_StrConsList {
Cons = 0,
Nil = 1,
}
#[repr(C)]
pub union union_MyTagUnion {
Bar: u128,
Blah: i32,
Foo: core::mem::ManuallyDrop<roc_std::RocStr>,
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StrConsList {
pointer: *mut core::mem::ManuallyDrop<roc_std::RocStr>,
}
#[repr(C)]
pub struct MyTagUnion {
variant: union_MyTagUnion,
tag: tag_MyTagUnion,
}
impl MyTagUnion {
pub fn tag(&self) -> tag_MyTagUnion {
self.tag
}
/// Construct a tag named Bar, with the appropriate payload
pub fn Bar(payload: u128) -> Self {
Self {
tag: tag_MyTagUnion::Bar,
variant: union_MyTagUnion {
Bar: payload
},
impl StrConsList {
pub fn tag(&self) -> tag_StrConsList {
if self.pointer.is_null() {
tag_StrConsList::Nil
} else {
tag_StrConsList::Cons
}
}
/// Unsafely assume the given MyTagUnion has a .tag() of Bar and convert it to Bar's payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn into_Bar(self) -> u128 {
self.variant.Bar
}
/// Construct a tag named Cons, with the appropriate payload
pub fn Cons(payload: roc_std::RocStr) -> Self {
let size = core::mem::size_of::<roc_std::RocStr>();
let align = core::mem::align_of::<roc_std::RocStr>();
/// Unsafely assume the given MyTagUnion has a .tag() of Bar and return its payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn as_Bar(&self) -> u128 {
self.variant.Bar
}
unsafe {
let pointer =
roc_alloc(size, align as u32) as *mut core::mem::ManuallyDrop<roc_std::RocStr>;
/// Construct a tag named Baz
pub fn Baz() -> Self {
Self {
tag: tag_MyTagUnion::Baz,
variant: unsafe {
core::mem::transmute::<
core::mem::MaybeUninit<union_MyTagUnion>,
union_MyTagUnion,
>(core::mem::MaybeUninit::uninit())
},
*pointer = core::mem::ManuallyDrop::new(payload);
Self { pointer }
}
}
/// Other `into_` methods return a payload, but since the Baz tag
/// Unsafely assume the given StrConsList has a .tag() of Cons and convert it to Cons's payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn into_Cons(self) -> roc_std::RocStr {
let payload = core::mem::ManuallyDrop::take(&mut *self.pointer);
let align = core::mem::align_of::<roc_std::RocStr>() as u32;
roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
payload
}
/// Unsafely assume the given StrConsList has a .tag() of Cons and return its payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn as_Cons(&self) -> &roc_std::RocStr {
&*self.pointer
}
/// Construct a tag named Nil
pub fn Nil() -> Self {
Self {
pointer: core::ptr::null_mut(),
}
}
/// Other `into_` methods return a payload, but since the Nil tag
/// has no payload, this does nothing and is only here for completeness.
pub fn into_Baz(self) -> () {
pub fn into_Nil(self) -> () {
()
}
/// Other `as` methods return a payload, but since the Baz tag
/// Other `as` methods return a payload, but since the Nil tag
/// has no payload, this does nothing and is only here for completeness.
pub unsafe fn as_Baz(&self) -> () {
pub unsafe fn as_Nil(&self) -> () {
()
}
/// Construct a tag named Blah, with the appropriate payload
pub fn Blah(payload: i32) -> Self {
Self {
tag: tag_MyTagUnion::Blah,
variant: union_MyTagUnion {
Blah: payload
},
}
}
/// Unsafely assume the given MyTagUnion has a .tag() of Blah and convert it to Blah's payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn into_Blah(self) -> i32 {
self.variant.Blah
}
/// Unsafely assume the given MyTagUnion has a .tag() of Blah and return its payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn as_Blah(&self) -> i32 {
self.variant.Blah
}
/// Construct a tag named Foo, with the appropriate payload
pub fn Foo(payload: roc_std::RocStr) -> Self {
Self {
tag: tag_MyTagUnion::Foo,
variant: union_MyTagUnion {
Foo: core::mem::ManuallyDrop::new(payload)
},
}
}
/// Unsafely assume the given MyTagUnion has a .tag() of Foo and convert it to Foo's payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn into_Foo(mut self) -> roc_std::RocStr {
core::mem::ManuallyDrop::take(&mut self.variant.Foo)
}
/// Unsafely assume the given MyTagUnion has a .tag() of Foo and return its payload.
/// (always examine .tag() first to make sure this is the correct variant!)
pub unsafe fn as_Foo(&self) -> &roc_std::RocStr {
&self.variant.Foo
}
}
impl Drop for MyTagUnion {
impl Drop for StrConsList {
fn drop(&mut self) {
match self.tag {
tag_MyTagUnion::Bar => {}
tag_MyTagUnion::Baz => {}
tag_MyTagUnion::Blah => {}
tag_MyTagUnion::Foo => unsafe { core::mem::ManuallyDrop::drop(&mut self.variant.Foo) },
}
}
}
if !self.pointer.is_null() {
let payload = unsafe { &*self.pointer };
let align = core::mem::align_of::<roc_std::RocStr>() as u32;
impl PartialEq for MyTagUnion {
fn eq(&self, other: &Self) -> bool {
if self.tag != other.tag {
return false;
}
unsafe {
match self.tag {
tag_MyTagUnion::Bar => self.variant.Bar == other.variant.Bar,
tag_MyTagUnion::Baz => true,
tag_MyTagUnion::Blah => self.variant.Blah == other.variant.Blah,
tag_MyTagUnion::Foo => self.variant.Foo == other.variant.Foo,
unsafe {
roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
}
}
}
}
impl Eq for MyTagUnion {}
impl PartialOrd for MyTagUnion {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
match self.tag.partial_cmp(&other.tag) {
Some(core::cmp::Ordering::Equal) => {}
not_eq => return not_eq,
}
unsafe {
match self.tag {
tag_MyTagUnion::Bar => self.variant.Bar.partial_cmp(&other.variant.Bar),
tag_MyTagUnion::Baz => Some(core::cmp::Ordering::Equal),
tag_MyTagUnion::Blah => self.variant.Blah.partial_cmp(&other.variant.Blah),
tag_MyTagUnion::Foo => self.variant.Foo.partial_cmp(&other.variant.Foo),
}
}
}
}
impl Ord for MyTagUnion {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
match self.tag.cmp(&other.tag) {
core::cmp::Ordering::Equal => {}
not_eq => return not_eq,
}
unsafe {
match self.tag {
tag_MyTagUnion::Bar => self.variant.Bar.cmp(&other.variant.Bar),
tag_MyTagUnion::Baz => core::cmp::Ordering::Equal,
tag_MyTagUnion::Blah => self.variant.Blah.cmp(&other.variant.Blah),
tag_MyTagUnion::Foo => self.variant.Foo.cmp(&other.variant.Foo),
}
}
}
}
impl Clone for MyTagUnion {
fn clone(&self) -> Self {
match self.tag {
tag_MyTagUnion::Bar => Self {
variant: union_MyTagUnion {
Bar: unsafe { self.variant.Bar.clone() },
},
tag: tag_MyTagUnion::Bar,
},
tag_MyTagUnion::Baz => Self {
variant: unsafe {
core::mem::transmute::<
core::mem::MaybeUninit<union_MyTagUnion>,
union_MyTagUnion,
>(core::mem::MaybeUninit::uninit())
},
tag: tag_MyTagUnion::Baz,
},
tag_MyTagUnion::Blah => Self {
variant: union_MyTagUnion {
Blah: unsafe { self.variant.Blah.clone() },
},
tag: tag_MyTagUnion::Blah,
},
tag_MyTagUnion::Foo => Self {
variant: union_MyTagUnion {
Foo: unsafe { self.variant.Foo.clone() },
},
tag: tag_MyTagUnion::Foo,
},
}
}
}
impl core::fmt::Debug for MyTagUnion {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("MyTagUnion::")?;
unsafe {
match self.tag {
tag_MyTagUnion::Bar => f.debug_tuple("Bar").field(&self.variant.Bar).finish(),
tag_MyTagUnion::Baz => f.write_str("Baz"),
tag_MyTagUnion::Blah => f.debug_tuple("Blah").field(&self.variant.Blah).finish(),
tag_MyTagUnion::Foo => f.debug_tuple("Foo").field(&self.variant.Foo).finish(),
}
drop(payload);
}
}
}