From 98ee92c1ccdba228f41b2c2ea19d754097ce0a2c Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Thu, 9 Nov 2017 17:17:12 -0500 Subject: [PATCH] Update static assertions post to reflect change Reflects https://github.com/nvzqz/static-assertions-rs/pull/5. --- _posts/2017-11-02-rust-static-assertions.md | 46 ++++++++------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/_posts/2017-11-02-rust-static-assertions.md b/_posts/2017-11-02-rust-static-assertions.md index 56950ad9dc50..4e2e05f190fc 100644 --- a/_posts/2017-11-02-rust-static-assertions.md +++ b/_posts/2017-11-02-rust-static-assertions.md @@ -468,26 +468,27 @@ error: aborting due to previous error Can we use this to our advantage in a general and ergonomic way? Of course! -To go about this we'll need to import the following from `std::mem`: +This is Rust, we shouldn't have to be `unsafe` to get what we want. As it turns +out, getting the function pointer will emit the same error. -- [`transmute`][transmute] --- What will enable our compile errors - -- [`uninitialized`] --- For instantiating our types +```rust +let f = transmute::; +``` -- [`forget`] --- To discard our instances without dropping them +You may have noticed the odd `::<>` after `transmute`. This is unofficially +referred to as [turbofish] syntax. It tells the compiler what generic parameters +to use for `transmute`, which takes an input and output type. ### The Macro With these tools we can write our basic macro: ```rust -use std::mem::{forget, transmute, uninitialized}; +use std::mem::transmute; macro_rules! assert_eq_size { ($x:ty, $y:ty) => { - unsafe { - forget(transmute::<$x, $y>(uninitialized())); - } + let _ = transmute::<$x, $y>; } } ``` @@ -495,13 +496,6 @@ macro_rules! assert_eq_size { Here `$x` and `$y` are annotated with `:ty`, which means that we can accept **any** type. Yes, Rust's macros are this powerful. -You may have noticed the odd `::<>` after `transmute`. This is unofficially -referred to as [turbofish] syntax. It tells the compiler what generic parameters -to use for `transmute`, which takes an input and output type. - -Because of type inference, Rust knows that `uninitialized` creates a value of -type `$x`. - Let's try this out: ```rust @@ -510,16 +504,16 @@ assert_eq_size!(u16, u32); ``` error[E0512]: transmute called with types of different sizes - --> src/main.rs:6:20 + --> src/main.rs:5:17 | -6 | forget(transmute::<$x, $y>(uninitialized())); - | ^^^^^^^^^^^^^^^^^^^ +5 | let _ = transmute::<$x, $y>; + | ^^^^^^^^^^^^^^^^^^^ ... -12 | assert_eq_size!(u32, u16); +10 | assert_eq_size!(u16, u32); | -------------------------- in this macro invocation | - = note: source type: u32 (32 bits) - = note: target type: u16 (16 bits) + = note: source type: u16 (16 bits) + = note: target type: u32 (32 bits) error: aborting due to previous error ``` @@ -535,9 +529,7 @@ here! ```rust macro_rules! assert_eq_size { ($x:ty, $y:ty) => { - unsafe { - forget(transmute::<$x, $y>(uninitialized())); - } + let _ = transmute::<$x, $y>; }; // <-- Notice the semicolon! ($label:ident; $x:ty, $y:ty) => { #[allow(non_snake_case)] // Allows any naming convention @@ -572,9 +564,7 @@ very much possible. ```rust macro_rules! assert_eq_size { ($x:ty, $($xs:ty),+ $(,)*) => { - unsafe { - $(forget(transmute::<$x, $xs>(uninitialized()));)+ - } + $(let _ = transmute::<$x, $xs>;)+ }; ($label:ident; $($rest:tt)+) => { #[allow(dead_code, non_snake_case)]