-
Notifications
You must be signed in to change notification settings - Fork 288
Description
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.