Share constant variables for closures.

This commit is contained in:
Stephen Chung 2020-12-09 21:06:36 +08:00
parent dbee0eb0f5
commit 99dd7a6481
4 changed files with 24 additions and 27 deletions

View File

@ -10,6 +10,11 @@ Bug fixes
* Constants are no longer propagated by the optimizer if shadowed by a non-constant variable. * Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
* Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to. * Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to.
Enhancements
------------
* Capturing a constant variable in a closure is now supported, with no cloning.
Version 0.19.7 Version 0.19.7
============== ==============

View File

@ -57,24 +57,6 @@ f.call(2) == 42;
``` ```
Constants are Not Captured
--------------------------
Constants are never shared. Their values are simply cloned.
```rust
const x = 42; // constant variable 'x'
let f = |y| x += y; // constant 'x' is cloned and not captured
x.is_shared() == false; // 'x' is not shared
f.call(10); // the cloned copy of 'x' is changed
x == 42; // 'x' is not changed
```
Beware: Captured Variables are Truly Shared Beware: Captured Variables are Truly Shared
------------------------------------------ ------------------------------------------

View File

@ -615,7 +615,20 @@ impl Dynamic {
/// if its value is going to be modified. This safe-guards constant values from being modified /// if its value is going to be modified. This safe-guards constant values from being modified
/// from within Rust functions. /// from within Rust functions.
pub fn is_read_only(&self) -> bool { pub fn is_read_only(&self) -> bool {
self.access_mode().is_read_only() match self.0 {
#[cfg(not(feature = "no_closure"))]
Union::Shared(_, access) if access.is_read_only() => true,
#[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))]
Union::Shared(ref cell, _) => cell.borrow().access_mode().is_read_only(),
#[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")]
Union::Shared(ref cell, _) => cell.read().unwrap().access_mode().is_read_only(),
_ => self.access_mode().is_read_only(),
}
} }
/// Create a [`Dynamic`] from any type. A [`Dynamic`] value is simply returned as is. /// Create a [`Dynamic`] from any type. A [`Dynamic`] value is simply returned as is.
/// ///

View File

@ -2383,16 +2383,13 @@ impl Engine {
// Share statement // Share statement
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => { Stmt::Share(x) => {
match scope.get_index(&x.name) { if let Some((index, _)) = scope.get_index(&x.name) {
Some((index, AccessMode::ReadWrite)) => { let val = scope.get_mut(index);
let val = scope.get_mut(index);
if !val.is_shared() { if !val.is_shared() {
// Replace the variable with a shared value. // Replace the variable with a shared value.
*val = crate::stdlib::mem::take(val).into_shared(); *val = crate::stdlib::mem::take(val).into_shared();
}
} }
_ => (),
} }
Ok(Dynamic::UNIT) Ok(Dynamic::UNIT)
} }