8000 rune: Store String in AnyObj instead of Mutable (relates #844) · rune-rs/rune@e0103b8 · GitHub
[go: up one dir, main page]

< 8000 div class="position-relative header-wrapper js-header-wrapper "> Skip to content

Commit e0103b8

Browse files
committed
rune: Store String in AnyObj instead of Mutable (relates #844)
1 parent eaae51e commit e0103b8

File tree

23 files changed

+328
-358
lines changed

23 files changed

+328
-358
lines changed

crates/rune/src/any.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::any;
22

3+
use crate::alloc::String;
34
use crate::compile::Named;
45
use crate::runtime::{AnyTypeInfo, TypeHash};
56

@@ -124,3 +125,5 @@ cfg_std! {
124125
}
125126

126127
crate::__internal_impl_any!(::std::error, anyhow::Error);
128+
129+
impl Any for String {}

crates/rune/src/compile/error.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::macros::{SyntheticId, SyntheticKind};
2020
use crate::parse::{Expectation, IntoExpectation, LexerMode};
2121
use crate::runtime::debug::DebugSignature;
2222
use crate::runtime::unit::EncodeError;
23-
use crate::runtime::{AccessError, RuntimeError, TypeInfo, TypeOf, VmError};
23+
use crate::runtime::{AccessError, AnyObjError, RuntimeError, TypeInfo, TypeOf, VmError};
2424
#[cfg(feature = "std")]
2525
use crate::source;
2626
use crate::{Hash, Item, ItemBuf, SourceId};
@@ -1307,6 +1307,13 @@ impl From<RuntimeError> for ErrorKind {
13071307
}
13081308
}
13091309

1310+
impl From<AnyObjError> for ErrorKind {
1311+
#[inline]
1312+
fn from(error: AnyObjError) -> Self {
1313+
Self::from(RuntimeError::from(error))
1314+
}
1315+
}
1316+
13101317
impl From<EncodeError> for ErrorKind {
13111318
#[inline]
13121319
fn from(error: EncodeError) -> Self {

crates/rune/src/compile/ir/eval.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::ast::{Span, Spanned};
77
use crate::compile::ir::{self};
88
use crate::compile::{self, WithSpan};
99
use crate::query::Used;
10-
use crate::runtime::{Inline, Mutable, Object, OwnedTuple, Value, ValueBorrowRef};
10+
use crate::runtime::{Inline, Object, OwnedTuple, Value, ValueBorrowRef};
11+
use crate::TypeHash;
1112

1213
/// The outcome of a constant evaluation.
1314
pub enum EvalOutcome {
@@ -139,18 +140,22 @@ fn eval_ir_binary(
139140

140141
return Ok(Value::from(out));
141142
}
142-
(ValueBorrowRef::Mutable(a), ValueBorrowRef::Mutable(b)) => {
143-
let out = 'out: {
144-
if let (Mutable::String(a), Mutable::String(b)) = (&*a, &*b) {
143+
(ValueBorrowRef::Any(a), ValueBorrowRef::Any(b)) => {
144+
let value = 'out: {
145+
if let (String::HASH, String::HASH) = (a.type_hash(), b.type_hash()) {
146+
let a = a.borrow_ref::<String>().with_span(span)?;
147+
let b = b.borrow_ref::<String>().with_span(span)?;
148+
145149
if let ir::IrBinaryOp::Add = ir.op {
146-
break 'out Mutable::String(add_strings(a, b).with_span(span)?);
150+
let string = add_strings(&a, &b).with_span(span)?;
151+
break 'out Value::new(string).with_span(span)?;
147152
}
148153
}
149154

150155
return Err(EvalOutcome::not_const(span));
151156
};
152157

153-
return Ok(Value::try_from(out).with_span(span)?);
158+
return Ok(value);
154159
}
155160
_ => (),
156161
}
@@ -366,15 +371,16 @@ fn eval_ir_template(
366371
return Err(EvalOutcome::not_const(ir));
367372
}
368373
},
369-
ValueBorrowRef::Mutable(value) => match &*value {
370-
Mutable::String(s) => {
371-
buf.try_push_str(s)?;
374+
ValueBorrowRef::Any(value) => match value.type_hash() {
375+
String::HASH => {
376+
let s = value.borrow_ref::<String>().with_span(ir)?;
377+
buf.try_push_str(&s)?;
372378
}
373379
_ => {
374380
return Err(EvalOutcome::not_const(ir));
375381
}
376382
},
377-
ValueBorrowRef::Any(..) => {
383+
ValueBorrowRef::Mutable(..) => {
378384
return Err(EvalOutcome::not_const(ir));
379385
}
380386
}

crates/rune/src/macros/format_args.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use crate::ast::{self, Span, Spanned};
77
use crate::compile::{self, WithSpan};
88
use crate::macros::{quote, MacroContext, Quote, ToTokens, TokenStream};
99
use crate::parse::{Parse, Parser, Peek, Peeker};
10-
use crate::runtime::format;
11-
use crate::runtime::{Inline, Mutable, OwnedValue};
10+
use crate::runtime::{format, Inline};
1211

1312
/// A format specification: A format string followed by arguments to be
1413
/// formatted in accordance with that string.
@@ -49,14 +48,7 @@ impl FormatArgs {
4948
}
5049
}
5150

52-
let format = format.take_value().with_span(&self.format)?;
53-
54-
let OwnedValue::Mutable(Mutable::String(format)) = format else {
55-
return Err(compile::Error::msg(
56-
&self.format,
57-
"format argument must be a string",
58-
));
59-
};
51+
let format = format.into_any::<String>().with_span(&self.format)?;
6052

6153
let mut unused_pos = (0..pos.len()).try_collect::<BTreeSet<_>>()?;
6254
let mut unused_named = named

crates/rune/src/modules/iter.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use crate::modules::collections::VecDeque;
88
use crate::modules::collections::{HashMap, HashSet};
99
use crate::runtime::range::RangeIter;
1010
use crate::runtime::{
11-
FromValue, Function, Inline, InstAddress, Mutable, Object, Output, OwnedTuple, Protocol,
12-
TypeHash, Value, ValueBorrowRef, Vec, VmErrorKind, VmResult,
11+
FromValue, Function, Inline, InstAddress, Object, Output, OwnedTuple, Protocol, TypeHash,
12+
Value, ValueBorrowRef, Vec, VmErrorKind, VmResult,
1313
};
1414
use crate::shared::Caller;
1515
use crate::{Any, ContextError, Module, Params};
@@ -489,17 +489,21 @@ pub fn module() -> Result<Module, ContextError> {
489489
ValueBorrowRef::Inline(Inline::Char(c)) => {
490490
vm_try!(string.try_push(*c));
491491
}
492-
ValueBorrowRef::Mutable(value) => match &*value {
493-
Mutable::String(s) => {
494-
vm_try!(string.try_push_str(s));
492+
ValueBorrowRef::Inline(value) => {
493+
return VmResult::expected::<String>(value.type_info());
494+
}
495+
ValueBorrowRef::Mutable(value) => {
496+
return VmResult::expected::<String>(value.type_info());
497+
}
498+
ValueBorrowRef::Any(value) => match value.type_hash() {
499+
String::HASH => {
500+
let s = vm_try!(value.borrow_ref::<String>());
501+
vm_try!(string.try_push_str(&s));
495502
}
496-
actual => {
497-
return VmResult::expected::<String>(actual.type_info());
503+
_ => {
504+
return VmResult::expected::<String>(value.type_info());
498505
}
499506
},
500-
actual => {
501-
return VmResult::expected::<String>(actual.type_info());
502-
}
503507
}
504508
}
505509

crates/rune/src/modules/string.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -762,12 +762,6 @@ fn split(this: Ref<str>, value: Value) -> VmResult<Value> {
762762
vm_try!(rune::to_value(Split::new(this, *c)))
763763
}
764764
ValueBorrowRef::Mutable(value) => match &*value {
765-
Mutable::String(ref s) => {
766-
vm_try!(rune::to_value(Split::new(
767-
this,
768-
vm_try!(Box::try_from(s.as_str()))
769-
)))
770-
}
771765
Mutable::Function(ref f) => {
772766
vm_try!(rune::to_value(Split::new(this, vm_try!(f.try_clone()))))
773767
}
@@ -778,11 +772,27 @@ fn split(this: Ref<str>, value: Value) -> VmResult<Value> {
778772
])
779773
}
780774
},
781-
actual => {
775+
ValueBorrowRef::Any(value) => match value.type_hash() {
776+
String::HASH => {
777+
let s = vm_try!(value.borrow_ref::<String>());
778+
779+
vm_try!(rune::to_value(Split::new(
780+
this,
781+
vm_try!(Box::try_from(s.as_str()))
782+
)))
783+
}
784+
_ => {
785+
return VmResult::err([
786+
VmErrorKind::expected::<String>(value.type_info()),
787+
VmErrorKind::bad_argument(0),
788+
]);
789+
}
790+
},
791+
value => {
782792
return VmResult::err([
783-
VmErrorKind::expected::<String>(actual.type_info()),
793+
VmErrorKind::expected::<String>(value.type_info()),
784794
VmErrorKind::bad_argument(0),
785-
])
795+
]);
786796
}
787797
};
788798

@@ -805,7 +815,6 @@ fn split_once(this: &str, value: Value) -> VmResult<Option<(String, String)>> {
805815
let outcome = match vm_try!(value.borrow_ref()) {
806816
ValueBorrowRef::Inline(Inline::Char(pat)) => this.split_once(*pat),
807817
ValueBorrowRef::Mutable(value) => match &*value {
808-
Mutable::String(s) => this.split_once(s.as_str()),
809818
Mutable::Function(f) => {
810819
let mut err = None;
811820

@@ -833,6 +842,18 @@ fn split_once(this: &str, value: Value) -> VmResult<Option<(String, String)>> {
833842
])
834843
}
835844
},
845+
ValueBorrowRef::Any(value) => match value.type_hash() {
846+
String::HASH => {
847+
let s = vm_try!(value.borrow_ref::<String>());
848+
this.split_once(s.as_str())
849+
}
850+
_ => {
851+
return VmResult::err([
852+
VmErrorKind::expected::<String>(value.type_info()),
853+
VmErrorKind::bad_argument(0),
854+
]);
855+
}
856+
},
836857
ref actual => {
837858
return VmResult::err([
838859
VmErrorKind::expected::<String>(actual.type_info()),

crates/rune/src/runtime/access.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@ const MOVED: usize = 1usize.rotate_right(1);
1212
/// Mask indicating if the value is exclusively set or moved.
1313
const MASK: usize = EXCLUSIVE | MOVED;
1414

15-
/// An error raised while downcasting.
16-
#[derive(Debug, PartialEq)]
17-
#[allow(missing_docs)]
15+
/// An error raised when failing to access a value.
16+
///
17+
/// Access errors can be raised for various reasons, such as:
18+
/// * The value you are trying to access is an empty placeholder.
19+
/// * The value is already being accessed in an incompatible way, such as trying
20+
/// to access a value exclusively twice.
21+
/// * The value has been taken and is no longer present.
22+
#[derive(Debug)]
23+
#[cfg_attr(test, derive(PartialEq))]
1824
#[non_exhaustive]
19-
pub(crate) struct AccessError {
25+
pub struct AccessError {
2026
kind: AccessErrorKind,
2127
}
2228

@@ -64,7 +70,8 @@ impl From<AccessErrorKind> for AccessError {
6470
}
6571
}
6672

67-
#[derive(Debug, PartialEq)]
73+
#[derive(Debug)]
74+
#[cfg_attr(test, derive(PartialEq))]
6875
pub(crate) enum AccessErrorKind {
6976
Empty,
7077
NotAccessibleRef(Snapshot),

crates/rune/src/runtime/any_obj.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ use super::{
1313
RefVtable, Snapshot, TypeInfo, VmErrorKind,
1414
};
1515

16+
#[derive(Debug)]
17+
#[cfg_attr(test, derive(PartialEq))]
18+
pub(super) enum AnyObjErrorKind {
19+
Cast(AnyTypeInfo, TypeInfo),
20+
AccessError(AccessError),
21+
}
22+
1623
/// Errors caused when accessing or coercing an [`AnyObj`].
1724
#[cfg_attr(test, derive(PartialEq))]
1825
pub struct AnyObjError {
@@ -30,11 +37,17 @@ impl AnyObjError {
3037
}
3138
}
3239

33-
#[derive(Debug)]
34-
#[cfg_attr(test, derive(PartialEq))]
35-
pub(super) enum AnyObjErrorKind {
36-
Cast(AnyTypeInfo, TypeInfo),
37-
AccessError(AccessError),
40+
impl core::error::Error for AnyObjError {}
41+
42+
impl fmt::Display for AnyObjError {
43+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44+
match &self.kind {
45+
AnyObjErrorKind::Cast(expected, actual) => {
46+
write!(f, "Expected type `{expected}` but found `{actual}`")
47+
}
48+
AnyObjErrorKind::AccessError(error) => error.fmt(f),
49+
}
50+
}
3851
}
3952

4053
impl fmt::Debug for AnyObjError {
@@ -370,6 +383,31 @@ impl AnyObj {
370383
}
371384
}
372385

386+
/// Try to borrow a reference to the interior value while checking for
387+
/// shared access.
388+
///
389+
/// Returns `None` if the interior type is not `T`.
390+
///
391+
/// This prevents other exclusive accesses from being performed while the
392+
/// guard returned from this function is live.
393+
pub fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
394+
where
395+
T: Any,
396+
{
397+
let vtable = vtable(self);
398+
399+
if (vtable.type_id)() != TypeId::of::<T>() {
400+
return Ok(None);
401+
}
402+
403+
// SAFETY: We've checked for the appropriate type just above.
404+
unsafe {
405+
let guard = self.shared.as_ref().access.shared()?;
406+
let data = vtable.as_ptr(self.shared);
407+
Ok(Some(BorrowRef::new(data, guard)))
408+
}
409+
}
410+
373411
/// Returns some mutable reference to the boxed value if it is of type `T`.
374412
pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, AnyObjError>
375413
where

crates/rune/src/runtime/args.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use core::fmt;
33
use crate::alloc::Vec;
44
use crate::runtime::{GuardedArgs, Stack, ToValue, Value, VmResult};
55

6-
#[derive(Debug, PartialEq)]
741A
6+
#[derive(Debug)]
7+
#[cfg_attr(test, derive(PartialEq))]
78
pub(crate) struct DynArgsUsed;
89

910
impl fmt::Display for DynArgsUsed {

crates/rune/src/runtime/const_value.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::runtime::{
66
self, Bytes, FromValue, Inline, Mutable, Object, OwnedTuple, ToValue, TypeInfo, Value,
77
ValueBorrowRef, VmErrorKind, VmResult,
88
};
9+
use crate::TypeHash;
910

1011
/// A constant value.
1112
#[derive(Debug, Deserialize, Serialize)]
@@ -54,7 +55,6 @@ impl ConstValue {
5455
}
5556
},
5657
ValueBorrowRef::Mutable(value) => match &*value {
57-
Mutable::String(s) => Self::String(vm_try!(s.try_to_owned())),
5858
Mutable::Option(option) => Self::Option(match option {
5959
Some(some) => Some(vm_try!(Box::try_new(vm_try!(Self::from_value_ref(some))))),
6060
None => None,
@@ -95,11 +95,17 @@ impl ConstValue {
9595
})
9696
}
9797
},
98-
value => {
99-
return VmResult::err(VmErrorKind::ConstNotSupported {
100-
actual: value.type_info(),
101-
})
102-
}
98+
ValueBorrowRef::Any(value) => match value.type_hash() {
99+
String::HASH => {
100+
let s = vm_try!(value.borrow_ref::<String>());
101+
Self::String(vm_try!(s.try_to_owned()))
102+
}
103+
_ => {
104+
return VmResult::err(VmErrorKind::ConstNotSupported {
105+
actual: value.type_info(),
106+
});
107+
}
108+
},
103109
})
104110
}
105111

0 commit comments

Comments
 (0)
0