-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How box
should work
#413
Comments
It has to clean up allocated resources if |
|
see also alternative design (needs RFC) with prototype at Rust PR 18233: rust-lang/rust/pull/18233 |
(in particular, any design needs to ensure that it handles failure of the (ah, apologies to @thestinger who said much the same thing a few comments up.) |
Something like: trait AllocHole<'a, out T> {
// associated field. const associated fields can't be assigned to,
// but writing to an &out associated field destroys its owner (this
// doesn't work with trait objects).
const internals: &'a out T
}
// fundep version. replace out parameters with associated types for
trait Allocator<'a, T, PLACE, out HOLE> where HOLE : AllocHole<'a, T>, PLACE: Copy {
fn alloc(&'a out self, p: PLACE) -> HOLE;
}
// We may need some hacks to convince typeck
// that Box<#[generic j]> impls Allocator<#[generic j], (), ...>
impl<'a, T> Allocator<T, (), BoxHole<'a, T>> for Box<T>
fn alloc(&'a out self, p: ()) -> BoxHole<'a, T> {
unsafe {
let ptr = malloc::<T>();
*self = Box(ptr);
BoxHole(transmute(ptr))
}
}
}
struct BoxHole<'a, T>(&'a out T);
impl<'a, T> Drop for BoxHole<'a, T> {
fn drop(&mut self) {
unsafe { free::<T>(transmute(self.0)); }
}
}
// box(PLACE) EXPR should translate to
// {
// let mut result;
// let mut hole = (&out result).alloc(PLACE);
// *hole = EXPR;
// result
// } We would need some kind of linear types and constant linear associated types, but it could work. I don't think my proposal requires typeck hacks/HKT/whatever, because the following code, trait MyTrait<T, P> {
fn work(&mut self, p: P, t: T);
}
impl<T> MyTrait<T, ()> for Option<T> {
fn work(&mut self, _: (), _: T) {}
}
fn main() {
let mut o = None;
o.work((), 0u);
println!("{}", o);
} Of course, to be generic over allocators, one still needs HKT, Π₂TB, or Π₁TB + Associated Types. |
i have an idea for how it should work: not |
We need to come up with a final design for how the
box
operator should work.Here is what I personally think would be ideal; unfortunately it involves features which are not yet part of the language.
The
box
operator would desugar to a call tomake_box
(see below). If a value-level argument is required to specify where the box should be allocated, such as for arenas (i.e.box(here) val
syntax), its type is specified by theWhere
associated type. Most of the time this defaults to()
.MakeBox
itself is a higher-kinded trait, implemented for the generic box type itself. (So if you haveimpl MakeBox for SomeBox
,val: T
, then e.g.box val: SomeBox<T>
.)make_box
relies on&out
references such as described by RFC PR 98 (see also the comments), which is a reference type which points to an uninitialized value and represents the obligation to initialize it.make_box
takes as argument the obligation to initialize a box, e.g. aSomeBox<T>
, allocates the box itself, and returns to the caller the obligation to initialize the contained value.We would have
impl
s such as:Given an expression:
from_string()
).SomeBox<Foo>
, wherefoo: Foo
,SomeBox: MakeBox
, andhere: <SomeBox as MakeBox>::Where
.here
is omitted, it defaults to()
, sobox foo
becomesbox(()) foo
.Box
.let rc_foo: Rc<_> = box foo;
. When we gain general type ascription syntax, it could instead bebox foo: Rc<_>
. (In each case the result type isRc<Foo>
.)This latter point is why it is important for the trait to be higher-kinded. If the trait is higher-kinded, it is sufficient to annotate the outer type (the box type), and the type argument can be inferred, because it is the same as the type of the value being
box
ed. IfMakeBox
were formulated using an associated type instead, as e.g.Deref
, then the type ascription would be required to specify the full type, including the type of the contained value.Finally, given the above expression:
This would desugar to:
The second line initializes
the_box
usingmake_box
, and then initializes the contained value withfoo
. (foo
here is an arbitrary expression, not necessarily a variable.)The text was updated successfully, but these errors were encountered: