ir: Handle NonZero and simplify Option<NonZero> like we simplify Option<NonNull>.

Fixes 
This commit is contained in:
Emilio Cobos Álvarez 2021-01-14 21:45:31 +01:00
parent f922f68531
commit c47ee1516b
12 changed files with 541 additions and 1 deletions

@ -517,6 +517,23 @@ impl Type {
}
}
pub fn make_zeroable(&self) -> Option<Self> {
let (kind, signed) = match *self {
Type::Primitive(PrimitiveType::Integer {
zeroable: false,
kind,
signed,
}) => (kind, signed),
_ => return None,
};
Some(Type::Primitive(PrimitiveType::Integer {
kind,
signed,
zeroable: true,
}))
}
pub fn make_nullable(&self) -> Option<Self> {
match *self {
Type::Ptr {
@ -543,12 +560,52 @@ impl Type {
}
}
fn nonzero_to_primitive(&self) -> Option<Self> {
let path = match *self {
Type::Path(ref p) => p,
_ => return None,
};
if !path.generics().is_empty() {
return None;
}
let name = path.name();
if !name.starts_with("NonZero") {
return None;
}
let (kind, signed) = match path.name() {
"NonZeroU8" => (IntKind::B8, false),
"NonZeroU16" => (IntKind::B16, false),
"NonZeroU32" => (IntKind::B32, false),
"NonZeroU64" => (IntKind::B64, false),
"NonZeroUSize" => (IntKind::Size, false),
"NonZeroI8" => (IntKind::B8, true),
"NonZeroI16" => (IntKind::B16, true),
"NonZeroI32" => (IntKind::B32, true),
"NonZeroI64" => (IntKind::B64, true),
"NonZeroISize" => (IntKind::Size, true),
_ => return None,
};
Some(Type::Primitive(PrimitiveType::Integer {
zeroable: false,
signed,
kind,
}))
}
fn simplified_type(&self, config: &Config) -> Option<Self> {
let path = match *self {
Type::Path(ref p) => p,
_ => return None,
};
if path.generics().is_empty() {
return self.nonzero_to_primitive();
}
if path.generics().len() != 1 {
return None;
}
@ -559,7 +616,15 @@ impl Type {
None => Cow::Borrowed(unsimplified_generic),
};
match path.name() {
"Option" => generic.make_nullable(),
"Option" => {
if let Some(nullable) = generic.make_nullable() {
return Some(nullable);
}
if let Some(zeroable) = generic.make_zeroable() {
return Some(zeroable);
}
None
}
"NonNull" => Some(Type::Ptr {
ty: Box::new(generic.into_owned()),
is_const: false,

@ -0,0 +1,44 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;
typedef struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
} NonZeroTest;
void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);

@ -0,0 +1,52 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;
typedef struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
} NonZeroTest;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -0,0 +1,44 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;
typedef struct {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
} NonZeroTest;
void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);

@ -0,0 +1,52 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Option_Option_NonZeroI64 Option_Option_NonZeroI64;
typedef struct {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
} NonZeroTest;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -0,0 +1,50 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
template<typename T = void>
struct Option;
struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option<Option<NonZeroI64>> *j;
};
extern "C" {
void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option<Option<NonZeroI64>> *j);
} // extern "C"

@ -0,0 +1,47 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list
cdef extern from *:
ctypedef struct Option_Option_NonZeroI64:
pass
ctypedef struct NonZeroTest:
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);

@ -0,0 +1,44 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Option_Option_NonZeroI64;
struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
};
void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);

@ -0,0 +1,52 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Option_Option_NonZeroI64;
struct NonZeroTest {
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const struct Option_Option_NonZeroI64 *j;
};
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(struct NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const struct Option_Option_NonZeroI64 *j);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -0,0 +1,47 @@
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list
cdef extern from *:
cdef struct Option_Option_NonZeroI64:
pass
cdef struct NonZeroTest:
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
int8_t e;
int16_t f;
int32_t g;
int64_t h;
int64_t i;
const Option_Option_NonZeroI64 *j;
void root(NonZeroTest test,
uint8_t a,
uint16_t b,
uint32_t c,
uint64_t d,
int8_t e,
int16_t f,
int32_t g,
int64_t h,
int64_t i,
const Option_Option_NonZeroI64 *j);

30
tests/rust/nonzero.rs Normal file

@ -0,0 +1,30 @@
use std::num::*;
#[repr(C)]
pub struct NonZeroTest {
pub a: NonZeroU8,
pub b: NonZeroU16,
pub c: NonZeroU32,
pub d: NonZeroU64,
pub e: NonZeroI8,
pub f: NonZeroI16,
pub g: NonZeroI32,
pub h: NonZeroI64,
pub i: Option<NonZeroI64>,
pub j: *const Option<Option<NonZeroI64>>,
}
#[no_mangle]
pub extern "C" fn root(
test: NonZeroTest,
a: NonZeroU8,
b: NonZeroU16,
c: NonZeroU32,
d: NonZeroU64,
e: NonZeroI8,
f: NonZeroI16,
g: NonZeroI32,
h: NonZeroI64,
i: Option<NonZeroI64>,
j: *const Option<Option<NonZeroI64>>,
) {}

13
tests/rust/nonzero.toml Normal file

@ -0,0 +1,13 @@
header = """
#if 0
''' '
#endif
#ifdef __cplusplus
struct NonZeroI64;
#endif
#if 0
' '''
#endif
"""