-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amend #1440: allow const
items to contain drop types.
#1817
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,27 +6,27 @@ | |
# Summary | ||
[summary]: #summary | ||
|
||
Allow types with destructors to be used in `static` items and in `const` functions, as long as the destructor never needs to run in const context. | ||
Allow types with destructors to be used in `static` items, `const` items, and `const` functions. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Some of the collection types do not allocate any memory when constructed empty (most notably `Vec`). With the change to make leaking safe, the restriction on `static` items with destructors | ||
is no longer required to be a hard error (as it is safe and accepted that these destructors may never run). | ||
|
||
Allowing types with destructors to be directly used in `const` functions and stored in `static`s will remove the need to have | ||
Allowing types with destructors to be directly used in `const` functions and stored in `static`s or `const`s will remove the need to have | ||
runtime-initialisation for global variables. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
- Lift the restriction on types with destructors being used in statics. | ||
- Lift the restriction on types with destructors being used in `static` or `const` items. | ||
- `static`s containing Drop-types will not run the destructor upon program/thread exit. | ||
- `const`s containing Drop-types _will_ run the destructor at the appropriate point in the program. | ||
- (Optionally adding a lint that warn about the possibility of resource leak) | ||
- Alloc instantiating structures with destructors in constant expressions, | ||
- Continue to prevent `const` items from holding types with destructors. | ||
- Allow `const fn` to return types with destructors. | ||
- Disallow constant expressions which would result in the destructor being called (if the code were run at runtime). | ||
- Disallow constant expressions resulting in destructors being called at runtime (i.e: a `drop(foo)` in a `const fn`). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't the change proposed here explicitly allow for constant expressions that result in destructors being called at runtime? Or do I misunderstand how the term "constant expression" or "runtime" is being used in this context? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, right, I prefer the original phrasing because it emphasizes that this is not about code ran at runtime, but rather some compile-time constant evaluation context. I'm not even sure we check this correctly with the feature flag enabled, it's a bit tricky if you can't rely on a full ban of drop types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
## Examples | ||
Assuming that `RwLock` and `Vec` have `const fn new` methods, the following example is possible and avoids runtime validity checks. | ||
|
@@ -38,12 +38,14 @@ trait LogHandler: Send + Sync { | |
} | ||
/// List of registered logging handlers | ||
static S_LOGGERS: RwLock<Vec< Box<LogHandler> >> = RwLock::new( Vec::new() ); | ||
|
||
/// Just an empty byte vector. | ||
const EMPTY_BYTE_VEC: Vec<u8> = Vec::new(); | ||
``` | ||
|
||
Disallowed code | ||
```rust | ||
static VAL: usize = (Vec::<u8>::new(), 0).1; // The `Vec` would be dropped | ||
const EMPTY_BYTE_VEC: Vec<u8> = Vec::new(); // `const` items can't have destructors | ||
|
||
const fn sample(_v: Vec<u8>) -> usize { | ||
0 // Discards the input vector, dropping it | ||
|
@@ -55,6 +57,8 @@ const fn sample(_v: Vec<u8>) -> usize { | |
|
||
Destructors do not run on `static` items (by design), so this can lead to unexpected behavior when a type's destructor has effects outside the program (e.g. a RAII temporary folder handle, which deletes the folder on drop). However, this can already happen using the `lazy_static` crate. | ||
|
||
Destructors _will_ run on `const` items at runtime, which can lead to unexpected behavior when a type's destructor has effects outside the program. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what this means. My mental model for a constant is that it is an "rvalue" -- in other words, each point where it is used, it is (roughly) "as if" you typed the expression in that place. Therefore, if we permit drop types there, I'd expect that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You've precisely identified the intent of the comment. I'll reword it. |
||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should be more specific about what "the appropriate point" is. Probably by adding a subsection to allow us to elaborate. But when I started thinking about what to write I encountered a question. I'll post it on the main thread though.