Skip to content

Commit ce28375

Browse files
committed
rewrite
1 parent 049c25a commit ce28375

File tree

1 file changed

+33
-28
lines changed

1 file changed

+33
-28
lines changed

text/3417-dropck-eyepatch-v3.md

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
# Summary
77
[summary]: #summary
88

9-
Cleanup the rules for implicit drops by splitting `#[may_dangle]` into two separate attributes:
10-
`#[only_dropped]` and `#[fully_ignored]`. Change `PhantomData` to get completely ignored
11-
by dropck as its current behavior is confusing and inconsistent.
9+
Cleanup the rules for implicit drops by adding an argument for `#[may_dangle]` on type
10+
parameters: `#[may_dangle(can_drop)]` and `#[may_dangle(must_not_use)]`. Change `PhantomData`
11+
to get completely ignored by dropck as its current behavior is confusing and inconsistent.
1212

1313
# Motivation
1414
[motivation]: #motivation
@@ -83,18 +83,20 @@ assumes that all generic parameters of the `Drop` impl are used:
8383
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e604bcaecb7b2b4cf7fd0440faf165ac).
8484

8585
In case a manual `Drop` impl does not access a generic parameter, you can add
86-
`#[fully_unused]` or `#[only_dropped]` to that parameter. This **unsafely** asserts
86+
`#[may_dangle]` to that parameter. This **unsafely** asserts
8787
that the parameter is either completely unused when dropping your type or only
88-
recursively dropped.
88+
recursively dropped. For type parameters, you have to declare whether you
89+
recursively drop instances of `T`. If so, you should use `#[may_dangle(droppable)]`.
90+
If not, you may use `#[may_dangle(must_not_use)]`.
8991

9092
```rust
91-
struct MyType<'s> {
92-
reference: &'s str,
93+
struct MyType<T> {
94+
generic: T,
9395
needs_drop: String,
9496
}
95-
// The impl has to be `unsafe` as the compiler does may not check
96-
// that `'s` is actually unused.
97-
unsafe impl<#[only_dropped] 's> Drop for MyType<'s> {
97+
// The impl has to be `unsafe` as the compiler may not check
98+
// that `T` is actually unused.
99+
unsafe impl<#[may_dangle(droppable)] T> Drop for MyType<T> {
98100
fn drop(&mut self) {
99101
// println!("{}", reference); // this would be unsound
100102
println!("{}", needs_drop);
@@ -111,13 +113,12 @@ fn can_drop_dead_reference() {
111113
}
112114
// We drop `_x` here even though `reference` is no longer live.
113115
//
114-
// This is accepted as `'s` is marked as `#[only_dropped]` in the
116+
// This is accepted as `T` is marked as `#[may_dangle(can_drop)]` in the
115117
// `Drop` impl of `MyType`.
116118
}
117119
```
118120

119-
The ability to differentiate between `#[fully_unused]` and `#[only_dropped]` is significant
120-
for type parameters:
121+
`Drop` impls for collections tend to require `#[may_dangle(droppable)]`:
121122

122123
```rust
123124
pub struct BTreeMap<K, V> {
@@ -134,7 +135,7 @@ unsafe impl<#[only_dropped] K, #[only_dropped] V> Drop for BTreeMap<K, V> {
134135
}
135136
```
136137

137-
A type where `#[fully_unused]` would be useful is a `Weak` pointer for a variant of `Rc`
138+
A type where `#[may_dangle(must_not_use)]` would be useful is a `Weak` pointer for a variant of `Rc`
138139
where the value is dropped when the last `Rc` goes out of scope. Dropping a `Weak` pointer
139140
would never access `T` in this case.
140141

@@ -151,43 +152,47 @@ When implicitly dropping a variable of type `T`, liveness requirements are compu
151152
- If `T` does not have any drop glue, do not add any requirements.
152153
- If `T` is a trait object, `T` has to be live.
153154
- If `T` has an explicit `Drop` impl, require all generic argument to be live, unless
154-
- they are marked with `#[fully_unused]`, in which case they are ignored,
155-
- or they are marked with `#[only_dropped]`, in which case recurse into the generic argument.
155+
- they marked with `#[may_dangle]`:
156+
- arguments for lifetime parameters marked `#[may_dangle]` and type parameters
157+
marked `#[may_dangle(must_not_use)]` are ignored,
158+
- we recurse into arguments for type parameters marked `#[may_dangle(droppable)]`.
156159
- Regardless of whether `T` implements `Drop`, recurse into all types *owned* by `T`:
157160
- references, raw pointers, function pointers, function items and scalars do not own
158161
anything. They can be trivially dropped.
159162
- tuples and arrays consider their element types to be owned.
160163
- all fields (of all variants) of ADTs are considered owned. We consider all variants
161-
for enums. The only exception here is `ManuallyDrop<U>` which is not considered to own `U`. `PhantomData<U>` does not have any fields and therefore also does not consider
164+
for enums. The only exception here is `ManuallyDrop<U>` which is not considered to own `U`.
165+
`PhantomData<U>` does not have any fields and therefore also does not consider
162166
`U` to be owned.
163167
- closures and generators own their captured upvars.
164168

165169
Checking drop impls may error for generic parameters which are known to be incorrectly marked:
166-
- `#[fully_unused]` parameters which are recursively owned
167-
- `#[only_dropped]` parameters which are required to be live by a recursively owned type
170+
- `#[may_dangle(must_not_use)]` parameters which are recursively owned
171+
- `#[may_dangle(droppable)]` parameters which are required to be live by a recursively owned type
168172

169173
This cannot catch all misuses, as the parameters can be incorrectly used by the `Drop` impl itself.
170174
We therefore require the impl to be marked as `unsafe`.
171175

172176
## How this differs from the status quo
173177

174-
Instead of `#[fully_unused]` and `#[only_dropped]`,there is only the `#[may_dangle]` attribute which
175-
skips the generic parameter. This is equivalent to the behavior of `#[fully_unused]` and relies on the recursion
176-
into types owned by `T` to figure out the correct constraints.
178+
Right now there is only the `#[may_dangle]` attribute which skips the generic parameter.
179+
This is equivalent to the behavior of `#[may_dangle(must_not_use)]` and relies on the recursion
180+
into types owned by `T` to figure out the correct constraints. This is now explicitly annotated
181+
using `#[may_dangle(droppable)]`.
177182

178183
`PhantomData<U>` currently considers `U` to be owned while not having drop glue itself. This means
179184
that `(PhantomData<PrintOnDrop<'s>>, String)` requires `'s` to be live while
180185
`(PhantomData<PrintOnDrop<'s>>, u32)` does not. This is required for get the
181-
behavior of `#[only_dropped]` for parameters otherwise not owned by adding `PhantomData` as a field.
182-
One can easily forget this, which caused the [unsound](https://github.com/rust-lang/rust/issues/76367)
186+
behavior of `#[may_dangle(droppable)]` for parameters otherwise not owned by adding `PhantomData`
187+
as a field. One can easily forget this, which caused the
188+
[unsound](https://github.com/rust-lang/rust/issues/76367)
183189
[issues](https://github.com/rust-lang/rust/issues/99408) mentioned above.
184190

185191
# Drawbacks
186192
[drawbacks]: #drawbacks
187193

188-
It requires an additional attribute when compared with `#[may_dangle]` and also proposes checks that the
189-
attributes are correctly used. This adds a small amount of implementation complexity to the compiler.
190-
These new attributes are still not fully checked by the compiler and require `unsafe`.
194+
This adds a small amount of implementation complexity to the compiler while not not being
195+
fully checked and therefore requiring `unsafe`.
191196

192197
This RFC does not explicitly exclude stabilizing these two attributes, as they are clearer and far less
193198
dangerous to use when compared with `#[may_dangle]`. Stabilizing these attributes will make it harder to
@@ -205,7 +210,7 @@ A more general extension to deal with partially invalid types is far from trivia
205210
assume types to always be well-formed and any approach which generalizes `#[may_dangle]` will
206211
have major consequences for how well-formedness is handled. This impacts many - often implicit -
207212
interactions and assumptions. It is highly unlikely that we will have the capacity for any such change
208-
in the near future. The benefits from such are change are likely to be fairly limited while
213+
in the near future. The benefits from such are change are also likely to be fairly limited while
209214
adding significant complexity.
210215

211216
# Prior art

0 commit comments

Comments
 (0)