You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Misleading error with Drop and lifetime parameters #17858
$ rustc -v
rustc 0.12.0-nightly (b5ba2f551 2014-10-06 20:27:14 +0000)
$ rustc dtor.rs
dtor.rs:5:1: 7:2 error: cannot implement a destructor on a structure with type parameters [E0141]
dtor.rs:5 impl<'a> Drop for S<'a> {
dtor.rs:6 fn drop(&mut self) {}
dtor.rs:7 }
dtor.rs:5:1: 7:2 note: use "#[unsafe_destructor]" on the implementation to force the compiler to allow this
dtor.rs:5 impl<'a> Drop for S<'a> {
dtor.rs:6 fn drop(&mut self) {}
dtor.rs:7 }
error: aborting due to previous error
It's not clear to me why this program gets rejected.
Right now the compiler's handling of lifetimes and destructors aren't quite sound in all cases. For example, in your example, it should be required that the destructor of S run before the destructor to T (otherwise S may see uninitialized memory).
Whereas, in this example (which compiles today), the destructor for T runs first:
#![feature(unsafe_destructor)]structS<'a>(&'aT);structT;impl<'a>S<'a>{fnfoo(&self){}}#[unsafe_destructor]impl<'a>DropforS<'a>{fndrop(&mutself){println!("dropping S");}}implDropforT{fndrop(&mutself){println!("dropping T");}}fnmain(){{println!("before!");let t = T;S(&t).foo()};println!("after!");}
$ rustc -v
rustc 0.12.0-nightly (b5ba2f551 2014-10-06 20:27:14 +0000)
$ rustc foo.rs
$ ./foo
before!
dropping T
dropping S
after!
changed the title [-]impl Drop disallowed with E0141 for types with lifetimes[/-][+]Misleading error with Drop and lifetime parameters[/+]on Oct 8, 2014
There is something I don't understand about the example though: We explicitly specify that the lifetime of the &T must match the one of the S instance which contains it, and as Rust assures that, the destructor should be safe. After all, we specified that the reference to T needs to live at least as long as S. It seems the actual problem is that we didn't actually express that instance of T shall outlive instance of S - as far as Rust is concerned, it only knows T must live as long as S, which might make the destructor a special case, as technically, an instance of S is about to decease.
After all, it appears there might be a problem with either expressiveness of lifetimes, or with the way destructors are handled, which is exactly what you said :) : "Right now the compiler's handling of lifetimes and destructors aren't quite sound in all cases.". Good I arrived at the same conclusion.
Another concern of mine is also stated in #11406/#8861: there may be an inflationary use of #![feature(unsafe_destructor)] of people who don't really understand the implications (which includes me, usually). Therefore I hope this will be fixed until 1.0 is released to prevent unsafe_destructors to pop up everywhere.
@Byron this is exactly the topic of rust-lang/rfcs#769 , which has a prototype implementation (see #21972) essentially ready to land (and should land for 1.0), and that should remove the unsoundness discussed here.
I suspect this issue can be closed. Error E0141 is no longer in the code base, and the example code now produces this error:
E0141.rs:10:16: 10:17 error: borrowed value does not live long enough
E0141.rs:10 let _ = S(&T);
^
E0141.rs:10:5: 10:19 note: reference must be valid for the destruction scope surrounding statement at 10:4...
E0141.rs:10 let _ = S(&T);
^~~~~~~~~~~~~~
E0141.rs:10:5: 10:19 note: ...but borrowed value is only valid for the statement at 10:4
E0141.rs:10 let _ = S(&T);
^~~~~~~~~~~~~~
E0141.rs:10:5: 10:19 help: consider using a `let` binding to increase its lifetime
E0141.rs:10 let _ = S(&T);
^~~~~~~~~~~~~~
error: aborting due to previous error
Activity
alexcrichton commentedon Oct 7, 2014
I think the error message may just be a little misleading, if you opt into
unsafe_destructorit should compile thoughbnoordhuis commentedon Oct 7, 2014
It does but I don't quite understand why the compiler rejects the program. Does the presence of the lifetime make it unsound?
alexcrichton commentedon Oct 7, 2014
Right now the compiler's handling of lifetimes and destructors aren't quite sound in all cases. For example, in your example, it should be required that the destructor of
Srun before the destructor toT(otherwiseSmay see uninitialized memory).Whereas, in this example (which compiles today), the destructor for
Truns first:alexcrichton commentedon Oct 7, 2014
And for a real world use case, you can see my comment which uses a standard
RefCellto generate unsafe reads and writes.bnoordhuis commentedon Oct 8, 2014
Thanks Alex, that makes perfect sense. Should I close the issue?
[-]impl Drop disallowed with E0141 for types with lifetimes[/-][+]Misleading error with Drop and lifetime parameters[/+]alexcrichton commentedon Oct 8, 2014
I think the error message could still use some improvement (mention lifetime parameters, for example), so I'm ok leaving this open to track that.
Byron commentedon Feb 9, 2015
There is something I don't understand about the example though: We explicitly specify that the lifetime of the
&Tmust match the one of theSinstance which contains it, and as Rust assures that, the destructor should be safe. After all, we specified that the reference toTneeds to live at least as long asS. It seems the actual problem is that we didn't actually express that instance ofTshall outlive instance ofS- as far as Rust is concerned, it only knows T must live as long as S, which might make the destructor a special case, as technically, an instance ofSis about to decease.After all, it appears there might be a problem with either expressiveness of lifetimes, or with the way destructors are handled, which is exactly what you said :) : "Right now the compiler's handling of lifetimes and destructors aren't quite sound in all cases.". Good I arrived at the same conclusion.
Another concern of mine is also stated in #11406/#8861: there may be an inflationary use of
#![feature(unsafe_destructor)]of people who don't really understand the implications (which includes me, usually). Therefore I hope this will be fixed until 1.0 is released to preventunsafe_destructors to pop up everywhere.pnkfelix commentedon Feb 9, 2015
@Byron this is exactly the topic of rust-lang/rfcs#769 , which has a prototype implementation (see #21972) essentially ready to land (and should land for 1.0), and that should remove the unsoundness discussed here.
nham commentedon May 12, 2015
I suspect this issue can be closed. Error
E0141is no longer in the code base, and the example code now produces this error:(
rustc 1.1.0-nightly (dc630d01e 2015-05-09) (built 2015-05-10))steveklabnik commentedon Nov 7, 2015
Agree with @nham
Auto merge of rust-lang#18075 - roife:fix-issue-17858, r=Veykril