Skip to content

Commit

Permalink
Split may_dangle
Browse files Browse the repository at this point in the history
  • Loading branch information
SoniEx2 committed Apr 14, 2023
1 parent c0a2cef commit 96d1330
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions text/3414-split-maydangle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
- Feature Name: `split_maydangle`
- Start Date: 2023-02-13
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

# Summary
[summary]: #summary

Add `#[needs_drop]`, ignore `PhantomData` for outlives requirements.

# Motivation
[motivation]: #motivation

This fails to compile:

```rust
use core::marker::PhantomData;

struct PrintOnDrop<'s>(&'s str);
impl<'s> Drop for PrintOnDrop<'s> {
fn drop(&mut self) {
println!("{}", self.0);
}
}

fn to_pd<T>(_: T) -> PhantomData<T> {
PhantomData
}

pub fn foo() {
let mut x;
{
let s = String::from("temporary");
let p = PrintOnDrop(&s);
x = (to_pd(p), String::new());
}
}
```

And yet, this compiles:

```rust
use core::marker::PhantomData;

struct PrintOnDrop<'s>(&'s str);
impl<'s> Drop for PrintOnDrop<'s> {
fn drop(&mut self) {
println!("{}", self.0);
}
}

fn to_pd<T>(_: T) -> PhantomData<T> {
PhantomData
}

pub fn foo() {
let mut x;
{
let s = String::from("temporary");
let p = PrintOnDrop(&s);
x = (to_pd(p), ());
}
}
```

Since the values in the tuple are unrelated, they should not affect each other.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

A type marked `#[needs_drop]` gets checked for liveness at drop. This is
necessary for `Vec`:

```rust
struct Vec<T> {
...
}

unsafe impl<#[needs_drop] #[may_dangle] T> Drop for Vec<T> {
fn drop(&mut self) {
...
}
}
```

So that this compiles:

```rust
fn main() {
let mut v = vec![];
{
v.push(&String::from("temporary"));
}
}
```

But this cannot compile, as it would be unsound:

```rust
struct PrintOnDrop<'s>(&'s str);
impl<'s> Drop for PrintOnDrop<'s> {
fn drop(&mut self) {
println!("{}", self.0);
}
}

fn main() {
let mut v = vec![];
{
v.push(PrintOnDrop(&*String::from("temporary")));
}
}
```

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

This RFC removes the dropck/outlives constraints from `PhantomData` and moves
them into the relevant `Drop` impls instead.

# Drawbacks
[drawbacks]: #drawbacks

Requires mild churn to update things to the new way. Failing to update wouldn't
break existing code, but would allow unsound code to compile.

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

A type which doesn't need drop should never have dropck/outlives contraints,
but due to the rushed way in which `may_dangle` was implemented, `PhantomData`
ended up having this unfortunate behaviour. This RFC removes this behaviour and
allows strictly more code to compile.

# Prior art
[prior-art]: #prior-art

- Compiler MCP 563: It is the exact same thing as this RFC, but a full RFC
seemed appropriate due to observable changes on stable, even if they are
fairly obscure.
- Unsound dropck elaboration for `BTreeMap`: <https://github.com/rust-lang/rust/pull/99413>
- `may_dangle`: RFC 1238, RFC 1327
- This is effectively split from RFC PR 3390 and is not intended for
stabilization.

# Unresolved questions
[unresolved-questions]: #unresolved-questions

N/A

# Future possibilities
[future-possibilities]: #future-possibilities

The full RFC 3390, and stabilization.

0 comments on commit 96d1330

Please sign in to comment.