Skip to content
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

Make accessing Unsafe<T> fields unsafe #182

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions active/0000-unsafe-unsafe-access.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Start Date: 2014-07-23
RFC PR #: (intentionally left blank)
Rust Issue #: (intentionally left blank)

# Summary

Make it unsafe to access the value of an ```&Unsafe<T>```.

# Motivation

Allow shared references to ```Unsafe<T>``` to be made safe while maintaining
the ability to initialize the ```Unsafe<T>``` statically.

Additionally, ensure that undefined behaviour can't happen within safe code, even after potentially bad (but defined) actions by unsafe code, as in issue
rust-lang/rust/#15920


# Detailed Design

As discussed in the "static mut" issues (#177, etc.), being able to
access the value field of ```Unsafe<T>``` objects forbids having such objects
accessible by an ```&Unsafe<T>``` reference, which would be useful in e.g. statics.

Making the ```Unsafe<T>```, or the value field of ```Unsafe<T>```, private currently is
not a solution, because private fields can't be statically initialized (for
a good reason).

The problem here is that ```Unsafe<T>``` is safe to initialize (because
it has no invariants, and nothing can reference a fresh ```Unsafe<T>```), but
an existing ```&Unsafe<T>``` can be referenced mutably, and therefore can't
be safely accessed. Compile-Time Function Evaluation would allow making the
field properly private, but it is rather complex and not planned for 1.0.

This can be solved by making access to fields of the "unsafe" lang item
unsafe (in the effect-checking pass). Note that one needs to prevent not only
direct access but at least by-ref destructuring, to prevent code such as this:

```Rust
let x = Unsafe { value: 1u, marker1: InvariantType };
let mut_alias : &mut uint = unsafe { &mut *x.get() };
//...
// The behaviour up to here was completely defined.
// The unsafe introduced no undefined behaviour
// Now, lets introduce some UB
let Unsafe { value: ref alias, .. } = x;
// Here alias and mut_alias are aliases.
```

Reducing backwards compatability breakage when we introduce CTFE would
suggest forbidding by-value destructuring and access as well.

# Drawbacks

This change is somewhat ugly and adds some "magic" to Unsafe<T>.

# Alternatives

Compile-Time Function Evaluation would allow a simple solution by
making ```value``` private and providing an initializing function, but is
a rather large and complex extension and is not planned for Rust 1.0.

A general extension that allows for publicly-initializable-but-not-
publicly-accessible fields would also do the job, but it would be more
complicated, and it doesn't seem that it would be useful outside this
case.

# Unresolved Questions

Should we really prevent by-value/by-mut-ref destructuring and access?