From b00c54fef8ced3aebb06c5ce91792e2eb8695c66 Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Sat, 1 Aug 2015 16:49:30 -0700 Subject: [PATCH 1/4] leaky-boxes-dynamic-statics --- text/0000-leaky-boxes-dynamic-statics.md | 50 ++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 text/0000-leaky-boxes-dynamic-statics.md diff --git a/text/0000-leaky-boxes-dynamic-statics.md b/text/0000-leaky-boxes-dynamic-statics.md new file mode 100644 index 00000000000..2596efbd559 --- /dev/null +++ b/text/0000-leaky-boxes-dynamic-statics.md @@ -0,0 +1,50 @@ +- Feature Name: leaky-boxes-dynamic-statics +- Start Date: (fill me in with today's date, YYY-MM-DD) +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Add a safe static method `Box::leak` which leaks a Box into a `&'static mut T`, preventing its destructor from being run, and allowing the data stored within it to be accessed for the remainder of the lifetime of the program. + +# Motivation + +As `mem::forget` is safe, it is legal to not call the destructor of a type in safe rust. Dynamically allocating static lifetime values is currently not possible in safe rust, but is safe. + +There are times when you would want to safely leak a resource, yet maintain access to the resource (unlike `mem::forget` which leaks the resource but prevents references to it). There are potential programs which this could increase the ease of design, due to program-lifetime structs which would otherwise have to have lifetime propagation, but can instead be leaked to `'static` to simplify code, among other things. + +# Detailed design + +This method would be a static method on `Box` named `leak`. + +Example Implementation: +```rust +impl Box { + pub fn leak<'a>(b: Self) -> &'a mut T { + unsafe { mem::transmute(b) } + } +} +``` + +# Drawbacks + +This adds a new function to the rust standard library which is not technically necessary, as the functionality of `Box::leak` can already be fairly easily implemented in rust, and is not necessarially a pattern which we want to encourage or enable. + +# Alternatives + +We could also implement this with a `'static` bound on the function, always producing a `&'static mut T`. This has the advantage of making the type signature more explicit, but loses some of the generality of the `leak` method to also support leaking types with arbitrary lifetime parameters. + +Example implementation: +```rust +impl Box { + pub fn leak(b: Self) -> &'static mut T { + unsafe { mem::transmute(b) } + } +} +``` + +If we don't implement `Box::leak`, the safe action of leaking a `Box` into a `&'static mut T` will not be possible without using unsafe rust, although it will be very easy for crates to implement this functionality themselves. + +# Unresolved questions + +Should the method include a `'static` bound on it's type parameter `T`, and always produce a `&'static mut T`, rather than a `&'a mut T` for any lifetime `'a`? From 522a213706f57e72f44811ef8e21e33cf0199233 Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Sat, 1 Aug 2015 22:54:07 -0700 Subject: [PATCH 2/4] Add a `where T: 'a` bound to the leak method for correctness. --- text/0000-leaky-boxes-dynamic-statics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-leaky-boxes-dynamic-statics.md b/text/0000-leaky-boxes-dynamic-statics.md index 2596efbd559..43af6b8cb40 100644 --- a/text/0000-leaky-boxes-dynamic-statics.md +++ b/text/0000-leaky-boxes-dynamic-statics.md @@ -20,7 +20,7 @@ This method would be a static method on `Box` named `leak`. Example Implementation: ```rust impl Box { - pub fn leak<'a>(b: Self) -> &'a mut T { + pub fn leak<'a>(b: Self) -> &'a mut T where T: 'a { unsafe { mem::transmute(b) } } } From 8db6e40517b03a738949373f03e6a839b93f29a6 Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Mon, 3 Aug 2015 09:59:12 -0700 Subject: [PATCH 3/4] Mention possibility of Leakable trait --- text/0000-leaky-boxes-dynamic-statics.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-leaky-boxes-dynamic-statics.md b/text/0000-leaky-boxes-dynamic-statics.md index 43af6b8cb40..8f0e710e1e3 100644 --- a/text/0000-leaky-boxes-dynamic-statics.md +++ b/text/0000-leaky-boxes-dynamic-statics.md @@ -45,6 +45,8 @@ impl Box { If we don't implement `Box::leak`, the safe action of leaking a `Box` into a `&'static mut T` will not be possible without using unsafe rust, although it will be very easy for crates to implement this functionality themselves. +This method could also be potentially useful on structs like `Vec` and `String` in the future to make it easier to leak them into `&'static mut [T]` and `&'static mut str` respectively. This potentially suggests a pattern, and the possibility of `leak` being a method on a `Leakable` trait. However, it may just be easier to implement other `leak` methods seperately, as being generic over `Leakable` is unlikely to be a common or useful use case. + # Unresolved questions Should the method include a `'static` bound on it's type parameter `T`, and always produce a `&'static mut T`, rather than a `&'a mut T` for any lifetime `'a`? From 55dcfeaf7fac329fd3515f6e2d8fd61a88de9eaf Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Wed, 5 Aug 2015 16:20:47 -0700 Subject: [PATCH 4/4] Also implement leak on String and Vec --- text/0000-leaky-boxes-dynamic-statics.md | 61 ++++++++++++++++++++---- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/text/0000-leaky-boxes-dynamic-statics.md b/text/0000-leaky-boxes-dynamic-statics.md index 8f0e710e1e3..7ce0b529db8 100644 --- a/text/0000-leaky-boxes-dynamic-statics.md +++ b/text/0000-leaky-boxes-dynamic-statics.md @@ -5,13 +5,24 @@ # Summary -Add a safe static method `Box::leak` which leaks a Box into a `&'static mut T`, preventing its destructor from being run, and allowing the data stored within it to be accessed for the remainder of the lifetime of the program. +Add safe static methods `Box::leak`, `String::leak` and `Vec::leak` which leak +into a `&'static mut T`, `&'static mut str`, and `&'static mut [T]` +respectively, preventing its destructor from being run, and allowing the data +stored within it to be accessed for the remainder of the lifetime of the +program. # Motivation -As `mem::forget` is safe, it is legal to not call the destructor of a type in safe rust. Dynamically allocating static lifetime values is currently not possible in safe rust, but is safe. +As `mem::forget` is safe, it is legal to not call the destructor of a type in +safe rust. Dynamically allocating static lifetime values is currently not +possible in safe rust, but is safe. -There are times when you would want to safely leak a resource, yet maintain access to the resource (unlike `mem::forget` which leaks the resource but prevents references to it). There are potential programs which this could increase the ease of design, due to program-lifetime structs which would otherwise have to have lifetime propagation, but can instead be leaked to `'static` to simplify code, among other things. +There are times when you would want to safely leak a resource, yet maintain +access to the resource (unlike `mem::forget` which leaks the resource but +prevents references to it). There are potential programs which this could +increase the ease of design, due to program-lifetime structs which would +otherwise have to have lifetime propagation, but can instead be leaked to +`'static` to simplify code, among other things. # Detailed design @@ -24,15 +35,37 @@ impl Box { unsafe { mem::transmute(b) } } } + +impl String { + pub fn leak<'a>(mut b: Self) -> &'a mut str { + let r: *mut str = &mut b[..]; + mem::forget(b); + unsafe { &mut *r }; + } +} + +impl Vec { + pub fn leak<'a>(mut b: Self) -> &'a mut [T] where T: 'a { + let r: *mut [T] = &mut b[..]; + mem::forget(b); + unsafe { &mut *r } + } +} ``` # Drawbacks -This adds a new function to the rust standard library which is not technically necessary, as the functionality of `Box::leak` can already be fairly easily implemented in rust, and is not necessarially a pattern which we want to encourage or enable. +This adds a new function to the rust standard library which is not technically +necessary, as the functionality of `leak` can already be fairly easily +implemented in rust, and is not necessarially a pattern which we want to +encourage or enable. # Alternatives -We could also implement this with a `'static` bound on the function, always producing a `&'static mut T`. This has the advantage of making the type signature more explicit, but loses some of the generality of the `leak` method to also support leaking types with arbitrary lifetime parameters. +We could also implement this with a `'static` bound on the function, always +producing a `&'static mut T`. This has the advantage of making the type +signature more explicit, but loses some of the generality of the `leak` method +to also support leaking types with arbitrary lifetime parameters. Example implementation: ```rust @@ -43,10 +76,22 @@ impl Box { } ``` -If we don't implement `Box::leak`, the safe action of leaking a `Box` into a `&'static mut T` will not be possible without using unsafe rust, although it will be very easy for crates to implement this functionality themselves. +If we don't implement `Box::leak`, the safe action of leaking a `Box` into a +`&'static mut T` will not be possible without using unsafe rust, although it +will be very easy for crates to implement this functionality themselves. -This method could also be potentially useful on structs like `Vec` and `String` in the future to make it easier to leak them into `&'static mut [T]` and `&'static mut str` respectively. This potentially suggests a pattern, and the possibility of `leak` being a method on a `Leakable` trait. However, it may just be easier to implement other `leak` methods seperately, as being generic over `Leakable` is unlikely to be a common or useful use case. +This method could also be potentially useful on structs like `Vec` and `String` +in the future to make it easier to leak them into `&'static mut [T]` and +`&'static mut str` respectively. This potentially suggests a pattern, and the +possibility of `leak` being a method on a `Leakable` trait. However, it may just +be easier to implement other `leak` methods seperately, as being generic over +`Leakable` is unlikely to be a common or useful use case. # Unresolved questions -Should the method include a `'static` bound on it's type parameter `T`, and always produce a `&'static mut T`, rather than a `&'a mut T` for any lifetime `'a`? +Should the method include a `'static` bound on it's type parameter `T`, and +always produce a `&'static mut T`, rather than a `&'a mut T` for any lifetime +`'a`? + +Should `String` and `Vec` also have implementations of `leak`, or should it be +limited to `Box`