From bf3285c6eeeb119fb145d84d2938e20f1179df5f Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 6 Apr 2014 15:11:12 -0400 Subject: [PATCH 1/3] Extend nullable pointer optimization to library types --- active/0000-unsafe-not-null.md | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 active/0000-unsafe-not-null.md diff --git a/active/0000-unsafe-not-null.md b/active/0000-unsafe-not-null.md new file mode 100644 index 00000000000..7e6fb7fb5bb --- /dev/null +++ b/active/0000-unsafe-not-null.md @@ -0,0 +1,65 @@ +- Start Date: 2014-04-05 +- RFC PR #: (leave this empty) +- Rust Issue #: (leave this empty) + +# Summary + +Add an `#[unsafe_not_null]` attribute to struct fields to enable the +nullable-pointer optimization for certain types containing raw pointers. + +# Motivation + +Currently, we do an optimization for certain enums where we know that the +valid representation of a type does not include null. For example: + +```rust +enum Option { + Some(T), + None +} +``` + +`Option<~T>` will not include an explicit discriminator, it will re-use "null" +instead, because `~T` can never be null. Unfortunately this optimization does +not extend beyond owning pointers and references. This hurts smart pointer +types such as `Rc`, which will never be null, but `Option>` still has +overhead from the descriminator. + +# Detailed design + +Motivating example: + +```rust +#[unsafe_not_null] +struct Rc { + inner: *RcBox +} +``` + +The `#[unsafe_not_null]` attribute, when applied to a `struct` which contains +only a single field whose type is an unsafe pointer, marks this structure as +eligible for the "nullable pointer" optimization. If the attribute is used +on a struct with more than one field, or whose only field is not a raw +pointer, the program will be rejected. + +# Alternatives + +One alternative that may seem appealing is to use some sort of marker type, +`NotNull`. This is unappealing because it will require a method to do the +dereferencing, and it cannot implement `Deref` or `DerefMut`. Why? Because +this is wrapping an unsafe pointer, and `Deref`/`DerefMut` are assumed to be +safe. Introducing another method call on all uses of smart pointers using +`NonNull` is going to put even more pressure on the already-strained LLVM +optimizers. Not that it cannot handle this; it will just be even slower. + +A different generalization would be adding some way to annotate that certain +values of a type's representation are not valid/used, and trans could use that +information to pack enum variants into that. This is very complex, and it is +not clear how to best implement this. One benefit this approach would have is +being able to have a wrapper around float types that uses a NaN for the None +in `Option`. + +# References + +- +- From 842e9f609096cf5c1809a29a21b85bef988d75fc Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 6 Apr 2014 15:28:00 -0400 Subject: [PATCH 2/3] Move the attribute from the struct to the field --- active/0000-unsafe-not-null.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/active/0000-unsafe-not-null.md b/active/0000-unsafe-not-null.md index 7e6fb7fb5bb..ce693d8066a 100644 --- a/active/0000-unsafe-not-null.md +++ b/active/0000-unsafe-not-null.md @@ -30,23 +30,36 @@ overhead from the descriminator. Motivating example: ```rust -#[unsafe_not_null] struct Rc { + #[unsafe_not_null] inner: *RcBox } ``` -The `#[unsafe_not_null]` attribute, when applied to a `struct` which contains -only a single field whose type is an unsafe pointer, marks this structure as -eligible for the "nullable pointer" optimization. If the attribute is used -on a struct with more than one field, or whose only field is not a raw -pointer, the program will be rejected. +The `#[unsafe_not_null]` attribute, when applied to a field of a struct, +signals that this field will never be null. It may only be applied to a single +field in a struct, and only once. With this knowledge, the nullable-pointer +pointer optimization can be extended to these types. Using `Option`, for +example, the `None` would be encoded as the `inner` field being null, rather +than an additional discriminant. By being applied to a field rather than the +struct as a whole, the optimization can be extended for more complex compound +types such as `Vec`: + +```rust +struct Vec { + data: *T, + len: uint, + cap: uint +} +``` + +Using `Option>` now has no additional overhead. # Alternatives -One alternative that may seem appealing is to use some sort of marker type, -`NotNull`. This is unappealing because it will require a method to do the -dereferencing, and it cannot implement `Deref` or `DerefMut`. Why? Because +One alternative that may seem appealing at first is to use some sort of marker +type, `NotNull`. This is undesirable because it will require a method to do +the dereferencing, and it cannot implement `Deref` or `DerefMut`. Why? Because this is wrapping an unsafe pointer, and `Deref`/`DerefMut` are assumed to be safe. Introducing another method call on all uses of smart pointers using `NonNull` is going to put even more pressure on the already-strained LLVM From f68a6b80cc483d833ca1acf423a7f3a153e10487 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 6 Apr 2014 15:54:20 -0400 Subject: [PATCH 3/3] Allow multiple non-nullable fields --- active/0000-unsafe-not-null.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/active/0000-unsafe-not-null.md b/active/0000-unsafe-not-null.md index ce693d8066a..ad106c9844b 100644 --- a/active/0000-unsafe-not-null.md +++ b/active/0000-unsafe-not-null.md @@ -37,13 +37,13 @@ struct Rc { ``` The `#[unsafe_not_null]` attribute, when applied to a field of a struct, -signals that this field will never be null. It may only be applied to a single -field in a struct, and only once. With this knowledge, the nullable-pointer -pointer optimization can be extended to these types. Using `Option`, for -example, the `None` would be encoded as the `inner` field being null, rather -than an additional discriminant. By being applied to a field rather than the -struct as a whole, the optimization can be extended for more complex compound -types such as `Vec`: +signals that this field will never be null. It may only be applied to unsafe +pointer fields. With this knowledge, the nullable-pointer pointer optimization +can be extended to these types. Using `Option`, for example, the `None` would +be encoded as the `inner` field being null, rather than an additional +discriminant. By being applied to a field rather than the struct as a whole, +the optimization can be extended for more complex compound types such as +`Vec`: ```rust struct Vec { @@ -53,7 +53,10 @@ struct Vec { } ``` -Using `Option>` now has no additional overhead. +Using `Option>` now has no additional overhead. The attribute is +allowed on multiple fields to provide more information. Each field adds +another bit of information that the compiler can use to encode more variants +in the same space. # Alternatives