about summary refs log tree commit diff
path: root/src/doc
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-03-21 13:12:08 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-03-24 22:27:23 +0100
commit5b2e8693e42dee545d336c0364773b3fbded93a5 (patch)
tree7506fd891d4f5ec60bed07cccd7c3c6a33b1d927 /src/doc
parent290c8de0a6f233b1d30c8a97cb41614fce989d30 (diff)
downloadrust-5b2e8693e42dee545d336c0364773b3fbded93a5.tar.gz
rust-5b2e8693e42dee545d336c0364773b3fbded93a5.zip
Reject specialized Drop impls.
See Issue 8142 for discussion.

This makes it illegal for a Drop impl to be more specialized than the
original item.

So for example, all of the following are now rejected (when they would
have been blindly accepted before):

```rust
struct S<A> { ... };
impl Drop for S<i8> { ... } // error: specialized to concrete type

struct T<'a> { ... };
impl Drop for T<'static> { ... } // error: specialized to concrete region

struct U<A> { ... };
impl<A:Clone> Drop for U<A> { ... } // error: added extra type requirement

struct V<'a,'b>;
impl<'a,'b:a> Drop for V<'a,'b> { ... } // error: added extra region requirement
```

Due to examples like the above, this is a [breaking-change].

(The fix is to either remove the specialization from the `Drop` impl,
or to transcribe the requirements into the struct/enum definition;
examples of both are shown in the PR's fixed to `libstd`.)

----

This is likely to be the last thing blocking the removal of the
`#[unsafe_destructor]` attribute.

Includes two new error codes for the new dropck check.

Update run-pass tests to accommodate new dropck pass.

Update tests and docs to reflect new destructor restriction.

----

Implementation notes:

We identify Drop impl specialization by not being as parametric as the
struct/enum definition via unification.

More specifically:

 1. Attempt unification of a skolemized instance of the struct/enum
    with an instance of the Drop impl's type expression where all of
    the impl's generics (i.e. the free variables of the type
    expression) have been replaced with unification variables.

 2. If unification fails, then reject Drop impl as specialized.

 3. If unification succeeds, check if any of the skolemized
    variables "leaked" into the constraint set for the inference
    context; if so, then reject Drop impl as specialized.

 4. Otherwise, unification succeeded without leaking skolemized
    variables: accept the Drop impl.

We identify whether a Drop impl is injecting new predicates by simply
looking whether the predicate, after an appropriate substitution,
appears on the struct/enum definition.
Diffstat (limited to 'src/doc')
-rw-r--r--src/doc/trpl/unsafe.md17
1 files changed, 9 insertions, 8 deletions
diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md
index 2116976d55a..dbf0cae6f4b 100644
--- a/src/doc/trpl/unsafe.md
+++ b/src/doc/trpl/unsafe.md
@@ -197,15 +197,16 @@ use std::ptr;
 
 // Define a wrapper around the handle returned by the foreign code.
 // Unique<T> has the same semantics as Box<T>
-pub struct Unique<T> {
+//
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction).
+pub struct Unique<T: Send> {
     // It contains a single raw, mutable pointer to the object in question.
     ptr: *mut T
 }
 
 // Implement methods for creating and using the values in the box.
 
-// NB: For simplicity and correctness, we require that T has kind Send
-// (owned boxes relax this restriction).
 impl<T: Send> Unique<T> {
     pub fn new(value: T) -> Unique<T> {
         unsafe {
@@ -239,11 +240,11 @@ impl<T: Send> Unique<T> {
 // Unique<T>, making the struct manage the raw pointer: when the
 // struct goes out of scope, it will automatically free the raw pointer.
 //
-// NB: This is an unsafe destructor, because rustc will not normally
-// allow destructors to be associated with parameterized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.) Note that the `#[unsafe_destructor]`
-// feature gate is required to use unsafe destructors.
+// NB: This is an unsafe destructor; rustc will not normally allow
+// destructors to be associated with parameterized types (due to
+// historically failing to check them soundly).  Note that the
+// `#[unsafe_destructor]` feature gate is currently required to use
+// unsafe destructors.
 #[unsafe_destructor]
 impl<T: Send> Drop for Unique<T> {
     fn drop(&mut self) {