Coder Social home page Coder Social logo

smallbox's Introduction

smallbox

Build Status crates.io

Small Box optimization: store small item on stack and fallback to heap for large item. Requires Rust 1.56+.

Usage

First, add the following to your Cargo.toml:

[dependencies]
smallbox = "0.8"

Next, add this to your crate root:

extern crate smallbox;

If you want this crate to work with dynamic-sized type, you can request it via:

[dependencies]
smallbox = { version = "0.8", features = ["coerce"] }

Currently smallbox by default links to the standard library, but if you would instead like to use this crate in a #![no_std] situation or crate, you can request this via:

[dependencies.smallbox]
version = "0.8"
features = ["coerce"]
default-features = false

Feature Flags

This crate has the following cargo feature flags:

  • std

    • Optional, enabled by default
    • Use libstd
    • If std feature flag is opted out, alloc crate will be linked, which requires nightly rust.
  • coerce

    • Optional
    • Require nightly rust
    • Allow automatic coersion from sized SmallBox to unsized SmallBox.

Unsized Type

There are two ways to have an unsized SmallBox: Using smallbox!() macro or coercing from a sized SmallBox instance(requires nightly compiler).

Using the smallbox!() macro is the only option on stable rust. This macro will check the type of given value and the target type T. For any invalid type coersions, this macro will invoke a compile-time error.

Once the feature coerce is enabled, sized SmallBox<T> will be automatically coerced into SmallBox<T: ?Sized> if necessary.

Example

Eliminate heap alloction for small items by SmallBox:

use smallbox::SmallBox;
use smallbox::space::S4;

let small: SmallBox<_, S4> = SmallBox::new([0; 2]);
let large: SmallBox<_, S4> = SmallBox::new([0; 32]);

assert_eq!(small.len(), 2);
assert_eq!(large.len(), 32);

assert_eq!(*small, [0; 2]);
assert_eq!(*large, [0; 32]);

assert!(small.is_heap() == false);
assert!(large.is_heap() == true);

Unsized type

Construct with smallbox!() macro:

#[macro_use]
extern crate smallbox;

use smallbox::SmallBox;
use smallbox::space::*;

let array: SmallBox<[usize], S2> = smallbox!([0usize, 1]);

assert_eq!(array.len(), 2);
assert_eq!(*array, [0, 1]);

With coerce feature:

use smallbox::SmallBox;
use smallbox::space::*;
 
let array: SmallBox<[usize], S2> = SmallBox::new([0usize, 1]);

assert_eq!(array.len(), 2);
assert_eq!(*array, [0, 1]);

Any downcasting:

#[macro_use]
extern crate smallbox;

use std::any::Any;
use smallbox::SmallBox;
use smallbox::space::S2;

let num: SmallBox<Any, S2> = smallbox!(1234u32);

if let Some(num) = num.downcast_ref::<u32>() {
    assert_eq!(*num, 1234);
} else {
    unreachable!();
}

Capacity

The capacity is expressed by the size of type parameter Space, regardless of what actually the Space is.

The crate provides some spaces in module smallbox::space, from S1, S2, S4 to S64, representing "n * usize" spaces.

Anyway, you can defind your own space type such as byte array [u8; 64]. Please note that the space alignment is also important. If the alignment of the space is smaller than the alignment of the value, the value will be stored in the heap.

Benchmark

The test platform is Windows 10 on Intel E3 v1230 v3.

running 6 tests
test box_large_item                  ... bench:         104 ns/iter (+/- 14)
test box_small_item                  ... bench:          49 ns/iter (+/- 5)
test smallbox_large_item_large_space ... bench:          52 ns/iter (+/- 6)
test smallbox_large_item_small_space ... bench:         106 ns/iter (+/- 25)
test smallbox_small_item_large_space ... bench:          18 ns/iter (+/- 1)
test smallbox_small_item_small_space ... bench:           2 ns/iter (+/- 0)

test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out

Contribution

All kinds of contribution are welcome.

  • Issue Feel free to open an issue when you find typos, bugs, or have any question.
  • Pull requests. Better implementation, more tests, more documents and typo fixes are all welcome.

License

Licensed under either of

at your option.

smallbox's People

Contributors

andylokandy avatar atul9 avatar kamilaborowska avatar quininer avatar trtsl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

smallbox's Issues

Can `new_copy` be explained better?

Ideally, unsafe blocks should be minimized. In particular new_copy runs afoul of rust-lang/rfcs#2585 It's the write and transmute that requires unsafe?

I suppose your lines like ptr_ptr.write(ptr_addr as usize); could document that they overwrite the pointer but retain any extra data inside the fat pointer.

I found the double arguments to new_copy and new_unchecked confusing, but some explanation comes with the smallbox! macro. We've a type argument T of SmallBox<T, Space> giving the unsized trait object or slice, but you also provide a sized argument U that provides a underlying sized type, such as a fixed length array. Ain't so idiomatic to pass around multiple references though, but I suppose this hack supports unsized types on stable without the CoerceUnsized nightly feature.

Why use std::alloc::{alloc.Layout} directly when seemingly Box methods suffice?

Design: Implement to_box() method

Implementing this feature will increase 1 byte of StackBox<T> to store the length of T. Anyway, if we have already stored the length, we could opt out SmallBox<T>'s enum tag by refactoring it to untagged_union, and produce a pattern-matchable enum by some method(unpack()?).

Problem with building for STM32

Hello.
I can't build this library for STM32.

error[E0405]: cannot find trait `Ord` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:442:30
    |
442 | impl<T: ?Sized + Ord, Space> Ord for SmallBox<T, Space> {
    |                              ^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::cmp::Ord;
    |

error[E0405]: cannot find trait `Sized` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:442:10
    |
442 | impl<T: ?Sized + Ord, Space> Ord for SmallBox<T, Space> {
    |          ^^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sized;
    |

error[E0405]: cannot find trait `Ord` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:442:18
    |
442 | impl<T: ?Sized + Ord, Space> Ord for SmallBox<T, Space> {
    |                  ^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::cmp::Ord;
    |

error[E0433]: failed to resolve: use of undeclared type `Ord`
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:444:9
    |
444 |         Ord::cmp(&**self, &**other)
    |         ^^^ use of undeclared type `Ord`
    |
help: consider importing this trait
    |
1   + use core::cmp::Ord;
    |

error[E0405]: cannot find trait `Eq` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:448:29
    |
448 | impl<T: ?Sized + Eq, Space> Eq for SmallBox<T, Space> {}
    |                             ^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::cmp::Eq;
    |

error[E0405]: cannot find trait `Sized` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:448:10
    |
448 | impl<T: ?Sized + Eq, Space> Eq for SmallBox<T, Space> {}
    |          ^^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sized;
    |

error[E0405]: cannot find trait `Eq` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:448:18
    |
448 | impl<T: ?Sized + Eq, Space> Eq for SmallBox<T, Space> {}
    |                  ^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::cmp::Eq;
    |

error[E0405]: cannot find trait `Sized` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:450:10
    |
450 | impl<T: ?Sized + Hash, Space> Hash for SmallBox<T, Space> {
    |          ^^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sized;
    |

error[E0405]: cannot find trait `Send` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:456:38
    |
456 | unsafe impl<T: ?Sized + Send, Space> Send for SmallBox<T, Space> {}
    |                                      ^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Send;
    |

error[E0405]: cannot find trait `Sized` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:456:17
    |
456 | unsafe impl<T: ?Sized + Send, Space> Send for SmallBox<T, Space> {}
    |                 ^^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sized;
    |

error[E0405]: cannot find trait `Send` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:456:25
    |
456 | unsafe impl<T: ?Sized + Send, Space> Send for SmallBox<T, Space> {}
    |                         ^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Send;
    |

error[E0405]: cannot find trait `Sync` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:457:38
    |
457 | unsafe impl<T: ?Sized + Sync, Space> Sync for SmallBox<T, Space> {}
    |                                      ^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sync;
    |

error[E0405]: cannot find trait `Sized` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:457:17
    |
457 | unsafe impl<T: ?Sized + Sync, Space> Sync for SmallBox<T, Space> {}
    |                 ^^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sized;
    |

error[E0405]: cannot find trait `Sync` in this scope
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/smallbox.rs:457:25
    |
457 | unsafe impl<T: ?Sized + Sync, Space> Sync for SmallBox<T, Space> {}
    |                         ^^^^ not found in this scope
    |
help: consider importing this trait
    |
1   + use core::marker::Sync;
    |

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/lib.rs:152:33
    |
152 | #![cfg_attr(feature = "coerce", feature(unsize, coerce_unsized))]
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/lib.rs:153:35
    |
153 | #![cfg_attr(not(feature = "std"), feature(cfg_doctest))]
    |                                   ^^^^^^^^^^^^^^^^^^^^ help: remove the attribute
    |
    = help: the feature `cfg_doctest` has been stable since `1.40.0` and no longer requires an attribute to enable

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/lib.rs:152:41
    |
152 | #![cfg_attr(feature = "coerce", feature(unsize, coerce_unsized))]
    |                                         ^^^^^^

error[E0554]: `#![feature]` may not be used on the stable release channel
   --> /home/mhanusek/.cargo/registry/src/index.crates.io-6f17d22bba15001f/smallbox-0.8.1/src/lib.rs:152:49
    |
152 | #![cfg_attr(feature = "coerce", feature(unsize, coerce_unsized))]
    |                                                 ^^^^^^^^^^^^^^
 

I Added this:

[dependencies.smallbox]
version = "0.8"
features = ["coerce"]
default-features = false

Tests fail when run with miri

error[E0080]: constant evaluation error: no item to reborrow for Unique from tag 93741 found in borrow stack
   --> src/smallbox.rs:319:18
    |
319 |         unsafe { &mut *(self.as_ptr() as *const _ as *mut _) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item to reborrow for Unique from tag 93741 found in borrow stack
    |
note: inside call to `<smallbox::SmallBox<usize, space::S1> as std::ops::DerefMut>::deref_mut` at src/smallbox.rs:327:42
   --> src/smallbox.rs:327:42
    |
327 |             ptr::drop_in_place::<T>(&mut **self);
    |                                          ^^^^^^
    = note: inside call to `<smallbox::SmallBox<usize, space::S1> as std::ops::Drop>::drop` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/ptr.rs:193:1
note: inside call to `std::ptr::real_drop_in_place::<smallbox::SmallBox<usize, space::S1>> - shim(Some(smallbox::SmallBox<usize, space::S1>))` at src/smallbox.rs:423:5
   --> src/smallbox.rs:423:5
    |
423 |     }
    |     ^
note: inside call to `smallbox::tests::test_basic` at src/smallbox.rs:417:5
   --> src/smallbox.rs:417:5
    |
417 | /     fn test_basic() {
418 | |         let stacked: SmallBox<usize, S1> = SmallBox::new(1234usize);
419 | |         assert!(*stacked == 1234);
420 | |
421 | |         let heaped: SmallBox<(usize, usize), S1> = SmallBox::new((0, 1));
422 | |         assert!(*heaped == (0, 1));
423 | |     }
    | |_____^
    = note: inside call to closure at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/ops/function.rs:231:5
    = note: inside call to `<[closure@src/smallbox.rs:417:5: 423:6] as std::ops::FnOnce<()>>::call_once - shim` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/ops/function.rs:231:5
    = note: inside call to `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1522:5
    = note: inside call to `test::__rust_begin_short_backtrace::<fn()>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1513:30
    = note: inside call to closure at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/ops/function.rs:231:5
    = note: inside call to `<[closure@DefId(9/1:109 ~ test[b0fc]::run_test[0]::{{closure}}[3]) 0:fn()] as std::ops::FnOnce<()>>::call_once - shim` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libcore/ops/function.rs:231:5
    = note: inside call to `<[closure@DefId(9/1:109 ~ test[b0fc]::run_test[0]::{{closure}}[3]) 0:fn()] as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/liballoc/boxed.rs:704:9
    = note: inside call to `<std::boxed::Box<dyn std::boxed::FnBox<(), Output = ()> + std::marker::Send> as std::ops::FnOnce<()>>::call_once` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panic.rs:309:9
    = note: inside call to `<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::boxed::FnBox<(), Output = ()> + std::marker::Send>> as std::ops::FnOnce<()>>::call_once` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panicking.rs:293:40
    = note: inside call to `std::panicking::try::do_call::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::boxed::FnBox<(), Output = ()> + std::marker::Send>>, ()>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panicking.rs:289:5
    = note: inside call to `std::panicking::try::<(), std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::boxed::FnBox<(), Output = ()> + std::marker::Send>>>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panic.rs:388:9
    = note: inside call to `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::boxed::FnBox<(), Output = ()> + std::marker::Send>>, ()>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1468:26
    = note: inside call to closure at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1490:13
    = note: inside call to `test::run_test::run_test_inner` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1509:28
    = note: inside call to `test::run_test` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:1167:13
    = note: inside call to `test::run_tests::<[closure@DefId(9/1:80 ~ test[b0fc]::run_tests_console[0]::{{closure}}[2]) 0:&mut test::ConsoleTestState, 1:&mut std::boxed::Box<dyn test::formatters::OutputFormatter>]>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:972:5
    = note: inside call to `test::run_tests_console` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:293:15
    = note: inside call to `test::test_main` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libtest/lib.rs:327:5
    = note: inside call to `test::test_main_static`
    = note: inside call to `main` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/rt.rs:64:34
    = note: inside call to closure at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/rt.rs:52:53
    = note: inside call to closure at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panicking.rs:293:40
    = note: inside call to `std::panicking::try::do_call::<[closure@DefId(1/1:1835 ~ std[797b]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panicking.rs:289:5
    = note: inside call to `std::panicking::try::<i32, [closure@DefId(1/1:1835 ~ std[797b]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/panic.rs:388:9
    = note: inside call to `std::panic::catch_unwind::<[closure@DefId(1/1:1835 ~ std[797b]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/rt.rs:52:25
    = note: inside call to `std::rt::lang_start_internal` at /Users/jrmuizel/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/rt.rs:64:5
    = note: inside call to `std::rt::lang_start::<()>`

SmallBox pin

I think it would be useful to include a pin function analogous to Box::pin. Would that be safe? It could help with async traits.

Consider using macro for support of unsized values on stable Rust

Even though Unsize and CoerceUnsized traits are not available on stable Rust, the code casting between compatible sized/unsized variants is still valid and compilable, just can't be expressed via the type system and generics.

This makes me wonder: would it make sense to add top-level macro for stackbox and smallbox? They would basically contain same code as new currently has (most importantly - casts between &T and &U, everything else can be still hidden into methods), and when expanded, these casts would be validated even by stable Rust, allowing to create unsized SmallBoxes.

Use `MaybeUninit` directly in the struct in place of `ManuallyDrop`

While the latest "Migrate to Rust 1.36" commit does make an attempt to use MaybeUninit, the way it's used is still UB because assume_init is called on uninitialized values: ManuallyDrop::new(mem::MaybeUninit::<Space>::uninit().assume_init()).

It should be possible to avoid this by replacing ManuallyDrop with MaybeUninit directly in the struct.

Missing alignment checks

StackBox and SmallBox currently expect any data to be aligned to usize but in reality type can have arbitrarily large alignment, and putting it into usize-aligned stack storage can cause all sorts of platform-specific issues.

While there is currently no way to allocate on stack with custom alignment, constructors of these types should at least check that alignment of type not any larger than the expected one, similarly to how they already check type sizes.

Tests fails under miri

It seems as miri test is broken. Could you please investigate it ?

Undefined Behavior: dereferencing pointer failed: 0x1fee70[noalloc] is a dangling pointer (it has no provenance)
   --> src\smallbox.rs:362:18
    |
362 |         unsafe { &*self.as_ptr() }
    |                  ^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x1fee70[noalloc] is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `<smallbox::SmallBox<usize, space::S1> as std::ops::Deref>::deref` at src\smallbox.rs:362:18: 362:33
note: inside `smallbox::tests::test_basic`
   --> src\smallbox.rs:468:17
    |
468 |         assert!(*stacked == 1234);
    |                 ^^^^^^^^
note: inside closure
   --> src\smallbox.rs:466:21
    |
465 |     #[test]
    |     ------- in this procedural macro expansion
466 |     fn test_basic() {
    |                     ^
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error

test smallbox::tests::test_basic ... error: test failed, to rerun pass `--lib`

Caused by:
  process didn't exit successfully: `C:\Users\zpgaa\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\bin\cargo-miri.exe runner D:\work\3rdparty\smallbox\target\miri\x86_64-pc-windows-msvc\debug\deps\smallbox-932a3225d7a60a4d.exe` (exit code: 1)

smallbox on ๎‚  master is ๐Ÿ“ฆ v0.8.1 via ๐Ÿฆ€ v1.69.0-nightly took 2s

Cannot put sized data into a StackBox / SmallBox with `unsize` feature

Difference in definitions of new depending on a feature flag makes it impossible to create a simple sized box when needed. For example, the following code:

struct S { data: usize, }
let m = StackBox::<S, S1>::new(S { data: 10 }).unwrap();

compiles fine with default features, but fails with unsize with

the trait std::marker::Unsize<stackbox::tests::test_as_ptr::S> is not implemented for stackbox::tests::test_as_ptr::S

I'd suggest exposing same basic interface for sized values via new and create a separate feature-controlled new_unsized for when it's needed, so that compiler can distinguish and correctly resolve types in both cases.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.