@Ericson2314 With either option, you need some sort of magic. I thnk you are under-estimating the amount of magic necessary to support drop-consuming T
properly.
You are either going to impose rules like "you cannot move out of self
in the context of fn drop
" (which to me seems much the same as Interior<T>
, or you are going to need some sort of ad-hoc analysis to determine which instances of T
should not have their destructor invoked.
As a quick example scenario, consider a destructor for T that can create other T’s:
#[derive(Debug)]
struct Tick { countdown: u32 }
impl Drop for Tick {
fn drop(&mut self) {
let t;
let s = self;
println!("dropping {:?}", s) {
if s.countdown > 0 {
t = Tick { countdown: s.countdown - 1 };
println!("created {:?}", t);
}
println!("done dropping {:?}", s);
}
}
fn main() {
let _spoon = Tick { countdown: 3 };
}
In the above code, if we solely changed the signature to fn drop(self)
and made no other changes, then you would need an analysis to distinguish cases like t
whose destructor should be invoked, versus cases like s
where doing so would cause infinite regress. (The easiest way to eliminate the above scenario is to disallow moves out of self
within fn drop
, but again, what’s the difference between that rule and adding Interior<T>
as an explicit form of it?