Rollup merge of #90066 - yaahc:thinbox, r=joshtriplett

Add new ThinBox type for 1 stack pointer wide heap allocated trait objects

**Zulip Thread**: https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/ThinBox

Based on b58d1d3cba/examples/thin.rs

Tracking Issue: https://github.com/rust-lang/rust/issues/92791

Usage Trial: https://github.com/yaahc/pgx/pull/1/files

## TODO

- [x] make sure to test with #[repr(align(1024))] structs etc
This commit is contained in:
Dylan DPC 2022-04-09 05:58:40 +02:00 committed by GitHub
commit ee8cea8ac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 388 additions and 2 deletions

View file

@ -0,0 +1,26 @@
#![feature(thin_box)]
// run-pass
use std::boxed::ThinBox;
use std::error::Error;
use std::ops::Deref;
use std::fmt;
fn main() {
let expected = "Foo error!";
let a: ThinBox<dyn Error> = ThinBox::new_unsize(Foo(expected));
let a = a.deref();
let msg = a.to_string();
assert_eq!(expected, msg);
}
#[derive(Debug)]
#[repr(align(1024))]
struct Foo(&'static str);
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for Foo {}

View file

@ -0,0 +1,37 @@
#![feature(thin_box)]
// run-pass
use std::boxed::ThinBox;
use std::error::Error;
use std::ops::Deref;
use std::fmt;
fn main() {
let expected = "Foo error!";
let mut dropped = false;
{
let foo = Foo(expected, &mut dropped);
let a: ThinBox<dyn Error> = ThinBox::new_unsize(foo);
let a = a.deref();
let msg = a.to_string();
assert_eq!(expected, msg);
}
assert!(dropped);
}
#[derive(Debug)]
#[repr(align(1024))]
struct Foo<'a>(&'static str, &'a mut bool);
impl Drop for Foo<'_> {
fn drop(&mut self) {
*self.1 = true;
}
}
impl fmt::Display for Foo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for Foo<'_> {}

View file

@ -0,0 +1,30 @@
#![feature(thin_box)]
// run-pass
use std::boxed::ThinBox;
use std::error::Error;
use std::{fmt, mem};
fn main() {
let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo);
assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error));
println!("{:?}", thin_error);
let thin = ThinBox::new(42i32);
assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin));
println!("{:?}", thin);
let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_slice));
println!("{:?}", thin_slice);
}
#[derive(Debug)]
struct Foo;
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "boooo!")
}
}
impl Error for Foo {}

View file

@ -0,0 +1,34 @@
#![feature(thin_box)]
// run-pass
use std::boxed::ThinBox;
use std::error::Error;
use std::{fmt, mem};
use std::ops::DerefMut;
const EXPECTED: &str = "boooo!";
fn main() {
let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo);
assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error));
let msg = thin_error.to_string();
assert_eq!(EXPECTED, msg);
let mut thin_concrete_error: ThinBox<Foo> = ThinBox::new(Foo);
assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_concrete_error));
let msg = thin_concrete_error.to_string();
assert_eq!(EXPECTED, msg);
let inner = thin_concrete_error.deref_mut();
let msg = inner.to_string();
assert_eq!(EXPECTED, msg);
}
#[derive(Debug)]
struct Foo;
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", EXPECTED)
}
}
impl Error for Foo {}

View file

@ -13,7 +13,7 @@ LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x
BorrowError
BorrowMutError
Box<T>
and 42 others
and 43 others
= note: required for the cast to the object type `dyn std::error::Error`
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
@ -31,7 +31,7 @@ LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
BorrowError
BorrowMutError
Box<T>
and 42 others
and 43 others
= note: required for the cast to the object type `(dyn std::error::Error + 'static)`
error: aborting due to 2 previous errors