Static Assertions Correctness and Stability via Cursed Code by - - PowerPoint PPT Presentation

static assertions
SMART_READER_LITE
LIVE PREVIEW

Static Assertions Correctness and Stability via Cursed Code by - - PowerPoint PPT Presentation

Static Assertions Correctness and Stability via Cursed Code by Nikolai Vazquez Who am I? Nikolai Vazquez , a.k.a. nvzqz 4th year Computer Science student at Boston University Open sourcerer since 2015 Programming and natural


slide-1
SLIDE 1

Static Assertions

Correctness and Stability via Cursed Code by Nikolai Vazquez

slide-2
SLIDE 2

@NikolaiVazquez

Who am I?

  • 4th year Computer Science

student at Boston University

  • Open sourcerer since 2015
  • Programming and natural

languages enthusiast

  • Cursed code connoisseur
  • Graphic designer, pianist, and

Oxford Comma evangelist

  • Working on Swift and Rust

playing nicely together

Nikolai Vazquez, a.k.a. nvzqz

slide-3
SLIDE 3

@NikolaiVazquez

What is “Static Assertions”?

  • A Rust library hosted at github.com/nvzqz/static-assertions-rs
  • Ensures at compile-time that:
  • Constant conditions are true
  • Types have the same size or alignment
  • All or any traits in a set are or are not implemented for a type
  • Traits support dynamic dispatch (object safety)
  • All in user code; no compiler hacks
slide-4
SLIDE 4

@NikolaiVazquez

How You'll Walk Away From This

Pictured: Michael Gattozzi reading through one of this crate's macro implementations

slide-5
SLIDE 5

@NikolaiVazquez

const_assert

slide-6
SLIDE 6

@NikolaiVazquez

const_assert

const VALUE: i32 = include!(concat!(env!("OUT_DIR"), "/value")); const_assert ); !(VALUE > 42

slide-7
SLIDE 7

@NikolaiVazquez

const_assert

const VALUE: i32 = include!(concat!(env!("OUT_DIR"), "/value")); && VALUE < 9000); const_assert!(VALUE > 42

slide-8
SLIDE 8

@NikolaiVazquez

const_assert

const_assert!(CONDITION); const CONDITION: bool = && VALUE < 9000 VALUE > 42 ; const VALUE: i32 = include!(concat!(env!("OUT_DIR"), "/value"));

slide-9
SLIDE 9

@NikolaiVazquez

const_assert

const_assert!(CONDITION);

error[E0080]: evaluation of constant value failed

  • -> talk/const_assert.rs:4:1

| 4 | const_assert!(CONDITION); | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow

slide-10
SLIDE 10

@NikolaiVazquez

macro_rules! { ($x:expr) => { const _: [ (); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize ] = []; }; } const_assert

const_assert

slide-11
SLIDE 11

@NikolaiVazquez

macro_rules! { ($x:expr) => { const _: [ (); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize ] = []; }; } const_assert

const_assert

slide-12
SLIDE 12

@NikolaiVazquez

macro_rules! { ($x:expr) => { const _: [ (); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize ] = []; }; } const_assert

const_assert

slide-13
SLIDE 13

@NikolaiVazquez

macro_rules! { ($x:expr) => { const _: [ (); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize ] = []; }; } const_assert

const_assert

slide-14
SLIDE 14

@NikolaiVazquez

const_assert

const CONDITION: bool = // ... const _: [(); 0 - !CONDITION as usize] = [];

slide-15
SLIDE 15

@NikolaiVazquez

#define STATIC_ASSERT(x) \ typedef int __assert[(!!(x)) ? 1 : -1];

const_assert

C++ Equivalent

slide-16
SLIDE 16

@NikolaiVazquez

assert_eq_size

slide-17
SLIDE 17

@NikolaiVazquez

assert_eq_size

assert_eq_size!(usize, *const u8);

slide-18
SLIDE 18

@NikolaiVazquez

assert_eq_size

assert_eq_size!(usize, *const u8 ); , u32

slide-19
SLIDE 19

@NikolaiVazquez

assert_eq_size

assert_eq_size!(usize, *const u8 ); , u32

error[E0512]: cannot transmute between types

  • f different sizes, or dependently-sized types
  • -> tests/eq_size.rs:2:1

| 2 | assert_eq_size!(usize, *const u8, u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: `usize` (64 bits) = note: target type: `u32` (32 bits)

slide-20
SLIDE 20

@NikolaiVazquez

assert_eq_size

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use std::mem::transmute; $(let _ = transmute::<$x, $xs>;)+ }; }; } assert_eq_size

slide-21
SLIDE 21

@NikolaiVazquez

assert_eq_size

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use std::mem::transmute; $(let _ = transmute::<$x, $xs>;)+ }; }; } assert_eq_size

slide-22
SLIDE 22

@NikolaiVazquez

assert_eq_size

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use std::mem::transmute; $(let _ = transmute::<$x, $xs>;)+ }; }; } assert_eq_size

slide-23
SLIDE 23

@NikolaiVazquez

assert_eq_size

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use std::mem::transmute; $(let _ = transmute::<$x, $xs>;)+ }; }; } assert_eq_size

slide-24
SLIDE 24

@NikolaiVazquez

assert_eq_align

slide-25
SLIDE 25

@NikolaiVazquez

assert_eq_align

!(usize, *const u8 ); , u32 assert_eq_align

slide-26
SLIDE 26

@NikolaiVazquez

assert_eq_align

!(usize, *const u8 ); , u32

error[E0308]: mismatched types

  • -> tests/eq_size.rs:2:1

| 2 | assert_eq_align!(usize, *const u8, u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | expected an array with a fixed size of 8 elements, | found one with 4 elements | = note: expected type `[(); 8]` found type `[(); 4]`

assert_eq_align

slide-27
SLIDE 27

@NikolaiVazquez

assert_eq_align

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use $crate::_core::mem::align_of; $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ }; }; } assert_eq_align

slide-28
SLIDE 28

@NikolaiVazquez

assert_eq_align

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use $crate::_core::mem::align_of; $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ }; }; } assert_eq_align

slide-29
SLIDE 29

@NikolaiVazquez

assert_eq_align

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use $crate::_core::mem::align_of; $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ }; }; } assert_eq_align

slide-30
SLIDE 30

@NikolaiVazquez

assert_eq_align

macro_rules! { ($x:ty, $($xs:ty),+) => { const _: fn() = || { use $crate::_core::mem::align_of; $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ }; }; } assert_eq_align

slide-31
SLIDE 31

@NikolaiVazquez

assert_not_impl_all

slide-32
SLIDE 32

@NikolaiVazquez

struct Foo; trait Bar {} trait Baz {} impl Bar for Foo {} impl Baz for Foo {}

assert_not_impl_all

!(Foo: Bar, Baz); assert_not_impl_all

slide-33
SLIDE 33

@NikolaiVazquez

!(Foo: Bar, Baz);

error[E0282]: type annotations needed for `fn() {<Foo as _::{{closure}}#0::AmbiguousIfImpl<_>>::some_item}`

  • -> talk/not_impl_all.rs:10:1

| 10 | assert_not_impl_any!(Foo: Bar, Baz); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | cannot infer type | consider giving this pattern the explicit type | `fn() {<Foo as _::{{closure}}#0::AmbiguousIfImpl<_>>::some_item}`, | with the type parameters specified

assert_not_impl_all

assert_not_impl_all

slide-34
SLIDE 34

@NikolaiVazquez

macro_rules! { ($x:ty: $($t:path),+) => { const _: fn() = || { struct Invalid; trait AmbiguousIfImpl<A> { fn some_item() {} } impl<T: ?Sized> AmbiguousIfImpl<()> for T {} impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; }

assert_not_impl_all

assert_not_impl_all

slide-35
SLIDE 35

@NikolaiVazquez

assert_not_impl_all

macro_rules! { ($x:ty: $($t:path),+) => { const _: fn() = || { struct Invalid; trait AmbiguousIfImpl<A> { fn some_item() {} } impl<T: ?Sized> AmbiguousIfImpl<()> for T {} impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; } assert_not_impl_all

slide-36
SLIDE 36

@NikolaiVazquez

macro_rules! assert_not_impl_all { ($x:ty: $($t:path),+) => { const _: fn() = || { struct Invalid; trait AmbiguousIfImpl<A> { fn some_item() {} } impl<T: ?Sized> AmbiguousIfImpl<()> for T {} impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; } assert_not_impl_all

assert_not_impl_all

slide-37
SLIDE 37

@NikolaiVazquez

macro_rules! assert_not_impl_all { ($x:ty: $($t:path),+) => { const _: fn() = || { struct Invalid; trait AmbiguousIfImpl<A> { fn some_item() {} } impl<T: ?Sized> AmbiguousIfImpl<()> for T {} impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; }

assert_not_impl_all

slide-38
SLIDE 38

@NikolaiVazquez

Fin