Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

static scope-shadowing restriction #11

Closed
dherman opened this issue Oct 12, 2015 · 4 comments
Closed

static scope-shadowing restriction #11

dherman opened this issue Oct 12, 2015 · 4 comments

Comments

@dherman
Copy link
Collaborator

dherman commented Oct 12, 2015

If we think of storing locals as "updating" a scope, we can rationalize changing the APIs to take an &mut impl Scope instead of an &impl Scope. From there we can use the borrow checker rules to "freeze" a scope when we shadow it with .nested and .chained, which lets us enforce most of the invariants of v8's HandleScope abstraction statically. For example:

    realm.scoped(|outer| {                  // &mut impl Scope
        let mut x = Integer::new(outer, 0); // Integer::new() takes an &mut outer
        outer.nested(|_| {                  // .nested() takes a frozen &outer
            x = Integer::new(outer, 666);   // borrow error: outer is frozen
        });
    });

The only thing it doesn't prevent statically is shadowing a frozen scope:

    realm.scoped(|outer| {
        outer.nested(|_| {      // .nested() takes a frozen &outer
            outer.nested(|_| {  // needs to be a dynamic error
                // ...
            });
        });
    });

The dynamic checks could be implemented with the same approach as today, but they would be rarer and possibly quite a bit less costly: instead of an extra branch on every creation of a local, they only have an extra branch on every shadowing of a scope.

One final thought: I wonder if this whole API is a fit for the future emplacement syntax.

@dherman
Copy link
Collaborator Author

dherman commented Oct 12, 2015

I think this doesn't work except possibly with non-lexical borrows. Code like

let mut array = Array::new(scope, 3);
array.set(0, Integer::new(scope, 0));
array.set(1, Integer::new(scope, 1));
array.set(2, Integer::new(scope, 2));

is going to be rejected for (purportedly) attempting multiple simultaneous mutable borrows.

@dherman
Copy link
Collaborator Author

dherman commented Oct 13, 2015

OK, nonlexical borrows won't really help enough. It's fundamental in Rust that you can't have multiple live &mut borrows tied to the same source. So for this to work we'd have to impose a mental model that you can only have one live handle at a time. (And it would require nonlexical borrows to be ergonomic, I think.) But this is just too weird and restrictive a mental model.

@dherman dherman closed this as completed Oct 13, 2015
@dherman
Copy link
Collaborator Author

dherman commented Oct 13, 2015

Stop press! Niko suggested a trick to circumvent the &mut restrictions that could work: create a shadow lifetime "behind" the Scope object's lifetime, and have the allocators return handles with the shadow lifetime.

@dherman dherman reopened this Oct 13, 2015
@dherman
Copy link
Collaborator Author

dherman commented Oct 30, 2015

Thanks to rust-lang PR 29188, my branch works in the latest Rust Nightly! Landing soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant