Giter Site home page Giter Site logo

humpty_dumpty's Introduction

Humpty Dumpty

Build Status

The goal of this library is to be able to define types that cannot be implicitly dropped except in controlled situations.

A sketch of the design can be found here. The design does not handle branches, though it can be extended to do so. It's also a bit different from what I finally implemented

The idea is, that for a type that is marked #[drop_protection], only functions annotated with #[allowed_on_protected] can use these, and each local must be dropped with a function marked #[allowed_drop] before its scope finishes.

Current status: Is able to track such types and report on their usage. Maintains a list of what has been dropped properly to detect implicit drops.

Some missing (but planned) functionality:

  • Cannot yet handle conditional drops, i.e. those in branches.
  • Cannot yet handle any bindings other than a let binding
  • Allowed functions cannot yet take &/&mut inputs
  • Cannot yet mark method calls as allowed

To test, run cargo run --example test, or even better rustc examples/test.rs -L target (after building). The latter is better because it will rebuild every time, and we're only interested in build output.

humpty_dumpty's People

Contributors

manishearth avatar munksgaard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

munksgaard

humpty_dumpty's Issues

Remove "debug" output

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.

Handle closures

There are two issues here: linearity needs to be checked inside of closures, and we need to handle moved variables

Handle return statements

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);
}

Incorrent handling of breaks inside match statements

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;
            }
        }
    }
}

handling of for loops doesn't correctly take breaks into account

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.

Handle generic functions

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.

Add more tests

We should showcase most, if not all, of the cases we can detect.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.