manishearth / humpty_dumpty Goto Github PK
View Code? Open in Web Editor NEWImplicit Drop/move protection for Rust (linear types)
Implicit Drop/move protection for Rust (linear types)
The following code compiles without errors:
#![feature(plugin)]
#![feature(custom_attribute)]
#![plugin(humpty_dumpty)]
#![allow(unused_attributes)]
#![allow(unused_variables)]
#![allow(dead_code)]
#[drop_protect]
struct Foo;
impl Foo {
#[allow_drop="Foo"]
fn close(self) { }
}
fn test1() {
let f = vec!(Foo); //~ ERROR dropped
for i in f {
if true {
break;
}
i.close();
}
}
fn main() {}
It really shouldn't.
As per the title, we should clarify what humpty can and cannot handle. Stuff that we currently cannot handle are clear candidates for issues/future fixes.
The following code should be allowed
#[drop_protect]
struct Foo;
#[allow_drop(Foo)]
fn close(_: Foo) { }
fn bla(x: Foo) {
if true {
close(x);
return;
}
close(x);
}
However, this shouldn't
#[drop_protect]
struct Foo;
#[allow_drop(Foo)]
fn close(_: Foo) { }
fn bla(x: Foo) {
if true {
return;
}
close(x);
}
It should be quite similar to ExprLoop
The following code incorrectly compiles without errors:
#[drop_protect]
struct Foo;
#[allow_drop="Foo"]
fn close(_: Foo) { }
fn main() {
let x = Foo;
loop {
match true {
true => {
close(x);
break
}
false => {
let y = Foo;
}
}
}
}
Something like rustc's compiletest would be nice to have.
cc @laumann
#[drop_protect]
struct Foo;
#[allow_drop="Foo"]
fn close(_: Foo) { }
fn main() {
loop {
let y = Foo;
}
}
Should warn that y
is dropped at the end of the loop.
The following should be allowed
let c = chan();
let mut n = 0;
loop {
if n < 10 {
n += 1;
} else {
close(c);
break;
}
}
One thing we don't handle is functions like this:
fn dropit<T>(x: T) { }
Since we just check all functions, but not instantiations of them, we can call dropit on a drop protected var. Any suggestions?
@Manishearth writes:
But we do; we still have allow_drop on the functions, right? If one of the arguments transitively resolves to a protected type (unless behind &, we probably want a utility function for that), and the function isn't annotated with #[allow_drop(Foo)], then it's a case of a generic function being fed a protected type, and we can error.
However, stuff like let mut v = Vec::new(); let c = Chan(); v.push(c); let c_ = v.pop(); c_.close()
should be allowed.
There are two issues here: linearity needs to be checked inside of closures, and we need to handle moved variables
There's a lot of unnecessary debug output when running humpty_dumpty. For example, compiling tests/if-return.rs yields:
tests/if-return.rs:13:14: 13:18 note: Adding drop protected type to map. Id: 11
tests/if-return.rs:13 fn close(self) { }
^~~~
tests/if-return.rs:18:9: 18:10 note: Adding drop protected type to map. Id: 21
tests/if-return.rs:18 let f = Foo;
^
tests/if-return.rs:21:9: 21:10 note: Consuming protected var
tests/if-return.rs:21 f.close();
^
tests/if-return.rs:30:9: 30:10 note: Adding drop protected type to map. Id: 40
tests/if-return.rs:30 let f = Foo;
^
tests/if-return.rs:33:9: 33:10 note: Consuming protected var
tests/if-return.rs:33 f.close();
^
tests/if-return.rs:39:5: 39:6 note: Consuming protected var
tests/if-return.rs:39 f.close();
^
tests/if-return.rs:44:9: 44:10 note: Adding drop protected type to map. Id: 61
tests/if-return.rs:44 let f = Foo;
^
tests/if-return.rs:47:9: 47:10 note: Consuming protected var
tests/if-return.rs:47 f.close();
^
tests/if-return.rs:50:9: 50:10 note: Consuming protected var
tests/if-return.rs:50 f.close();
^
tests/if-return.rs:57:9: 57:10 note: Adding drop protected type to map. Id: 83
tests/if-return.rs:57 let f = Foo;
^
tests/if-return.rs:62:9: 62:10 note: Consuming protected var
tests/if-return.rs:62 f.close();
^
tests/if-return.rs:66:5: 66:6 note: Consuming protected var
tests/if-return.rs:66 f.close();
^
tests/if-return.rs:71:9: 71:10 note: Adding drop protected type to map. Id: 104
tests/if-return.rs:71 let f = Foo;
^
tests/if-return.rs:78:5: 78:6 note: Consuming protected var
tests/if-return.rs:78 f.close();
^
tests/if-return.rs:85:9: 85:12 note: Adding drop protected type to map. Id: 122
tests/if-return.rs:85 let foo = Foo;
^~~
tests/if-return.rs:88:9: 88:12 note: Consuming protected var
tests/if-return.rs:88 foo.close();
^~~
tests/if-return.rs:92:5: 92:8 note: Consuming protected var
tests/if-return.rs:92 foo.close();
^~~
tests/if-return.rs:98:9: 98:12 note: Adding drop protected type to map. Id: 143
tests/if-return.rs:98 let foo = Foo;
^~~
tests/if-return.rs:101:9: 101:12 note: Consuming protected var
tests/if-return.rs:101 foo.close();
which is clearly undesired. Many of these are trivial and should be removed, others should be hidden behind RUST_LOG.
We should showcase most, if not all, of the cases we can detect.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.