From 44fae7026e73ce738c7db7ef4a619fe18e19b359 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Fri, 23 Jan 2015 00:10:30 +0200 Subject: [PATCH 1/4] Added RFC: truly unsized types --- text/0000-truly-unsized-types.md | 85 ++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 text/0000-truly-unsized-types.md diff --git a/text/0000-truly-unsized-types.md b/text/0000-truly-unsized-types.md new file mode 100644 index 00000000000..2adde8d60a9 --- /dev/null +++ b/text/0000-truly-unsized-types.md @@ -0,0 +1,85 @@ +- Start Date: 2015-01-22 +- RFC PR: +- Rust Issue: + +# Summary + +Further subdivide unsized types into dynamically-sized types, implementing +an intrinsic trait `DynamicSize`, and types of indeterminate size. References +for the latter kind will be thin, while allocating slots or copying values +of such types is not possible outside unsafe code. + +# Motivation + +There are cases where borrowed references provide a view to a larger object +in memory than the nominal sized type being referenced. Of interest are: + +- Token types for references to data structures whose size is not available as + a stored value, but determined by parsing the content, such as + null-terminated C strings. An example is `CStr`, a + [proposed](https://github.com/rust-lang/rfcs/pull/592) 'thin' dereference + type for `CString`. +- References to structs as public views into larger contiguously allocated + objects, the size and layout of which is hidden from the client. + +When only immutable references are available on such types, it's possible +to prevent copying out the nominal sized value in safe code, but there is +still potential for unintentional misuse due to values under reference having +a bogus size. +If mutable references are available, there is added trouble with +`std::mem::swap` and similar operations. + +# Detailed design + +The types that do not implement `Sized` are further subdivided into DSTs +and types of indeterminate size. + +## Truly unsized types + +Any type with sized contents can be opted out of `Sized` by including +a marker `NotSized`, which also implies `NoCopy`: +```rust +struct CStr { + head: libc::c_char, // Contains at least one character... + rest: std::marker::NotSized // ...but there can be more +} +``` + +This makes references to values of such types unusable for copying +the value out, `size_of`, `std::mem::swap`, being the source in +`transmute_copy`, etc. + +## Dynamically sized types + +Plain old (ahem) dynamically sized types will intrinsically implement +a newly introduced trait, `DynamicSize`. Only references to `DynamicSize` +types will be fat. + +# Fallout + +There may be cases where `!Sized` is taken to mean DSTs. These will have to +switch to using the `DynamicSize` bound. + +Specifically, there are generic items where the `Sized` bound is not +lifted only to ensure that a reference is thin so it can be coerced or +transmuted to a raw pointer. These will be unable to use truly unsized types, +and should relax the type bound to `?Sized` and a negative bound (#586) +on `DynamicSize`. + +# Drawbacks + +Adding further complexity to the type system. + +# Alternatives + +Keep to the current practice of Irrelevantly Sized Types, learning to avoid +trouble by coding discipline, documentation, and best practices. The problem +of mutable references can be resolved on a case-by-case basis by providing +an accessor facade for fields that can be safely mutated, and disallowing +direct mutable references to the pseudo-sized type. This feels at odds +with the overall philosophy of Rust, though. + +# Unresolved questions + +For convenience, there could be an intrinsically implemented positive trait +to complement `DynamicSize`. From ffe327b77cf2ccc93d53450107f27bbbfba4b340 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Fri, 23 Jan 2015 00:46:01 +0200 Subject: [PATCH 2/4] Properly link to the negative bounds RFC PR --- text/0000-truly-unsized-types.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0000-truly-unsized-types.md b/text/0000-truly-unsized-types.md index 2adde8d60a9..3d0e0b8438c 100644 --- a/text/0000-truly-unsized-types.md +++ b/text/0000-truly-unsized-types.md @@ -63,7 +63,8 @@ switch to using the `DynamicSize` bound. Specifically, there are generic items where the `Sized` bound is not lifted only to ensure that a reference is thin so it can be coerced or transmuted to a raw pointer. These will be unable to use truly unsized types, -and should relax the type bound to `?Sized` and a negative bound (#586) +and should get the type bound relaxed to `?Sized` and a +[negative bound](https://github.com/rust-lang/rfcs/pull/586) on `DynamicSize`. # Drawbacks From 9ed6176adf5676bb210c8b88f8ab9ba22bf53312 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Fri, 23 Jan 2015 09:33:59 +0200 Subject: [PATCH 3/4] Editorial --- text/0000-truly-unsized-types.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/text/0000-truly-unsized-types.md b/text/0000-truly-unsized-types.md index 3d0e0b8438c..46ef48e1067 100644 --- a/text/0000-truly-unsized-types.md +++ b/text/0000-truly-unsized-types.md @@ -46,8 +46,9 @@ struct CStr { ``` This makes references to values of such types unusable for copying -the value out, `size_of`, `std::mem::swap`, being the source in -`transmute_copy`, etc. +the value out, `std::mem::swap`, being the source in +`transmute_copy`, etc. Unsized types can't be used as the +type parameter of `size_of`. ## Dynamically sized types @@ -61,7 +62,7 @@ There may be cases where `!Sized` is taken to mean DSTs. These will have to switch to using the `DynamicSize` bound. Specifically, there are generic items where the `Sized` bound is not -lifted only to ensure that a reference is thin so it can be coerced or +lifted only to ensure that a reference is thin, so as to be coerced or transmuted to a raw pointer. These will be unable to use truly unsized types, and should get the type bound relaxed to `?Sized` and a [negative bound](https://github.com/rust-lang/rfcs/pull/586) @@ -82,5 +83,5 @@ with the overall philosophy of Rust, though. # Unresolved questions -For convenience, there could be an intrinsically implemented positive trait -to complement `DynamicSize`. +For convenience, there could be an intrinsically implemented trait +that is a negation of `DynamicSize`. From 053821448cc3d184661e3df47dc80ab8cb8bcd8f Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Fri, 23 Jan 2015 09:47:48 +0200 Subject: [PATCH 4/4] More editorial --- text/0000-truly-unsized-types.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-truly-unsized-types.md b/text/0000-truly-unsized-types.md index 46ef48e1067..0c4b169d08d 100644 --- a/text/0000-truly-unsized-types.md +++ b/text/0000-truly-unsized-types.md @@ -63,19 +63,19 @@ switch to using the `DynamicSize` bound. Specifically, there are generic items where the `Sized` bound is not lifted only to ensure that a reference is thin, so as to be coerced or -transmuted to a raw pointer. These will be unable to use truly unsized types, -and should get the type bound relaxed to `?Sized` and a +transmuted to a raw pointer. These will not be usable with truly unsized +types, and should get the type bound relaxed to `?Sized` and a [negative bound](https://github.com/rust-lang/rfcs/pull/586) on `DynamicSize`. # Drawbacks -Adding further complexity to the type system. +This is adding further complexity to the type system. # Alternatives Keep to the current practice of Irrelevantly Sized Types, learning to avoid -trouble by coding discipline, documentation, and best practices. The problem +trouble by design discipline, documentation, and best practices. The problem of mutable references can be resolved on a case-by-case basis by providing an accessor facade for fields that can be safely mutated, and disallowing direct mutable references to the pseudo-sized type. This feels at odds