Share constant variables for closures.
This commit is contained in:
parent
dbee0eb0f5
commit
99dd7a6481
@ -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
|
||||||
==============
|
==============
|
||||||
|
@ -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
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user