From 7dc78c2a6a8fe0d14065a4106db0d310bd9d8b16 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 19 Dec 2014 18:54:30 +0100 Subject: [PATCH 1/2] draft RFC for removing certain array elem moves. --- text/0000-no-array-elem-moves.md | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 text/0000-no-array-elem-moves.md diff --git a/text/0000-no-array-elem-moves.md b/text/0000-no-array-elem-moves.md new file mode 100644 index 00000000000..35d1b20b2b0 --- /dev/null +++ b/text/0000-no-array-elem-moves.md @@ -0,0 +1,84 @@ +- Start Date: 2014-12-19 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +In order to prepare for an expected future implementation of +[non-zeroing dynamic drop], remove support for: + +* moving individual elements into an *uninitialized* fixed-sized array, and + +* moving individual elements out of fixed-sized arrays `[T, ..n]`, + (copying and borrowing such elements is still permitted). + +[non-zeroing dynamic drop]: https://github.com/rust-lang/rfcs/pull/320 + +# Motivation + +If we want to continue supporting dynamic drop while also removing +automatic memory zeroing and drop-flags, then we need to either (1.) +adopt potential complex code generation strategies to support arrays +with only *some* elements initialized (as discussed in the [unresolved +questions for RFC PR 320], or we need to (2.) remove support for +constructing such arrays in safe code. + +[unresolved questions for RFC PR 320]: https://github.com/pnkfelix/rfcs/blob/6288739c584ee6830aa0f79f983c5e762269c562/active/0000-nonzeroing-dynamic-drop.md#how-to-handle-moves-out-of-arrayindex_expr + +This RFC is proposing the second tack. + +The expectation is that relatively few libraries need to support +moving out of fixed-sized arrays (and even fewer take advantage of +being able to initialize individual elements of an uninitialized +array, as supporting this was almost certainly not intentional in the +language design). Therefore removing the feature from the language +will present relatively little burden. + +# Detailed design + +If an expression `e` has type `[T, ..n]` and `T` does not implement +`Copy`, then it will be illegal to use `e[i]` in an r-value position. + +If an expression `e` has type `[T, ..n]` expression `e[i] = ` +will be made illegal at points in the control flow where `e` has not +yet been initialized. + +Note that it *remains* legal to overwrite an element in an initialized +array: `e[i] = `, as today. This will continue to drop the +overwritten element before moving the result of `` into place. + +A prototype implementation will be made available before this RFC is +accepted. + +# Drawbacks + +* Adopting this RFC is introducing a limitation on the language based + on a hypothetical optimization that has not yet been implemented + (though much of the ground work for its supporting analyses are + done). + +Also, as noted in the [comment thread from RFC PR 320] + +[comment thread from RFC PR 320]: https://github.com/rust-lang/rfcs/pull/320#issuecomment-59533551 + +* We support moving a single element out of an n-tuple, and "by + analogy" we should support moving out of `[T, ..n]` + +* It is "nice" to be able to write + ```rust + fn grab_random_from(actions: [Action, ..5]) -> Action { actions[rand_index()] } + ``` + to express this now, one would be forced to instead use clone() (or + pass in a `Vec` and do some element swapping). + + +# Alternatives + +We can just leave things as they are; there are hypothetical +code-generation strategies for supporting non-zeroing drop even with +this feature, as discussed in the [comment thread from RFC PR 320]. + +# Unresolved questions + +None + From 58ce407a3ffe61a63fed8d2d41acff24f718bd95 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Feb 2015 14:53:45 +0100 Subject: [PATCH 2/2] Update RFC. Add link to prototype implementation. Add note that destructuring bind is not affected by the change proposed here. Account for change in type syntax from `[E, ..k]` to `[E; k]`. --- text/0000-no-array-elem-moves.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/text/0000-no-array-elem-moves.md b/text/0000-no-array-elem-moves.md index 35d1b20b2b0..bca8a1f5978 100644 --- a/text/0000-no-array-elem-moves.md +++ b/text/0000-no-array-elem-moves.md @@ -9,7 +9,7 @@ In order to prepare for an expected future implementation of * moving individual elements into an *uninitialized* fixed-sized array, and -* moving individual elements out of fixed-sized arrays `[T, ..n]`, +* moving individual elements out of fixed-sized arrays `[T; n]`, (copying and borrowing such elements is still permitted). [non-zeroing dynamic drop]: https://github.com/rust-lang/rfcs/pull/320 @@ -36,10 +36,10 @@ will present relatively little burden. # Detailed design -If an expression `e` has type `[T, ..n]` and `T` does not implement +If an expression `e` has type `[T; n]` and `T` does not implement `Copy`, then it will be illegal to use `e[i]` in an r-value position. -If an expression `e` has type `[T, ..n]` expression `e[i] = ` +If an expression `e` has type `[T; n]` expression `e[i] = ` will be made illegal at points in the control flow where `e` has not yet been initialized. @@ -47,8 +47,13 @@ Note that it *remains* legal to overwrite an element in an initialized array: `e[i] = `, as today. This will continue to drop the overwritten element before moving the result of `` into place. -A prototype implementation will be made available before this RFC is -accepted. +Note also that the proposed change has no effect on the semantics of +destructuring bind; i.e. `fn([a, b, c]: [Elem; 3]) { ... }` will +continue to work as much as it does today. + +A prototype implementation has been posted at [Rust PR 21930]. + +[Rust PR 21930]: https://github.com/rust-lang/rust/pull/21930 # Drawbacks @@ -62,11 +67,13 @@ Also, as noted in the [comment thread from RFC PR 320] [comment thread from RFC PR 320]: https://github.com/rust-lang/rfcs/pull/320#issuecomment-59533551 * We support moving a single element out of an n-tuple, and "by - analogy" we should support moving out of `[T, ..n]` + analogy" we should support moving out of `[T; n]` + (Note that one can still move out of `[T; n]` in some cases + via destructuring bind.) * It is "nice" to be able to write ```rust - fn grab_random_from(actions: [Action, ..5]) -> Action { actions[rand_index()] } + fn grab_random_from(actions: [Action; 5]) -> Action { actions[rand_index()] } ``` to express this now, one would be forced to instead use clone() (or pass in a `Vec` and do some element swapping).