commit
0603b2b1cc
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.rhai linguist-language=JavaScript
|
@ -264,7 +264,7 @@ impl Module {
|
||||
// NB: sub-modules must have their new items for exporting generated in depth-first order
|
||||
// to avoid issues caused by re-parsing them
|
||||
let inner_modules = sub_modules
|
||||
.drain(..)
|
||||
.into_iter()
|
||||
.try_fold::<_, _, Result<_, syn::Error>>(Vec::new(), |mut acc, m| {
|
||||
acc.push(m.generate_inner()?);
|
||||
Ok(acc)
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied
|
||||
error[E0599]: `bool` is not an iterator
|
||||
--> ui_tests/export_fn_raw_return.rs:10:33
|
||||
|
|
||||
10 | pub fn test_fn(input: Point) -> bool {
|
||||
| ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds
|
||||
| ^^^^ `bool` is not an iterator
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`bool: std::iter::Iterator`
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied
|
||||
error[E0599]: `bool` is not an iterator
|
||||
--> ui_tests/export_mod_raw_return.rs:12:33
|
||||
|
|
||||
12 | pub fn test_fn(input: Point) -> bool {
|
||||
| ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds
|
||||
| ^^^^ `bool` is not an iterator
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`bool: std::iter::Iterator`
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
||||
--> ui_tests/non_clonable.rs:11:23
|
||||
|
|
||||
10 | #[export_fn]
|
||||
| ------------ in this procedural macro expansion
|
||||
11 | pub fn test_fn(input: NonClonable) -> bool {
|
||||
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
||||
|
|
||||
@ -9,3 +11,4 @@ note: required by a bound in `rhai::Dynamic::cast`
|
||||
|
|
||||
| pub fn cast<T: Any + Clone>(self) -> T {
|
||||
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
||||
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
||||
--> ui_tests/non_clonable_second.rs:11:27
|
||||
|
|
||||
10 | #[export_fn]
|
||||
| ------------ in this procedural macro expansion
|
||||
11 | pub fn test_fn(a: u32, b: NonClonable) -> bool {
|
||||
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
||||
|
|
||||
@ -9,3 +11,4 @@ note: required by a bound in `rhai::Dynamic::cast`
|
||||
|
|
||||
| pub fn cast<T: Any + Clone>(self) -> T {
|
||||
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
||||
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
@ -69,12 +69,8 @@ impl Engine {
|
||||
let typ = self.map_type_name(result.type_name());
|
||||
|
||||
result.try_cast().ok_or_else(|| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
self.map_type_name(type_name::<T>()).into(),
|
||||
typ.into(),
|
||||
Position::NONE,
|
||||
)
|
||||
.into()
|
||||
let t = self.map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
||||
})
|
||||
}
|
||||
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments and the
|
||||
|
@ -195,12 +195,8 @@ impl Engine {
|
||||
let typ = self.map_type_name(result.type_name());
|
||||
|
||||
result.try_cast::<T>().ok_or_else(|| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
self.map_type_name(type_name::<T>()).into(),
|
||||
typ.into(),
|
||||
Position::NONE,
|
||||
)
|
||||
.into()
|
||||
let t = self.map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
||||
})
|
||||
}
|
||||
/// Evaluate an [`AST`] with own scope.
|
||||
|
@ -125,7 +125,7 @@ impl Engine {
|
||||
#[inline(never)]
|
||||
#[must_use]
|
||||
pub(crate) fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> RhaiError {
|
||||
ERR::ErrorMismatchDataType(self.map_type_name(type_name::<T>()).into(), typ.into(), pos)
|
||||
.into()
|
||||
let t = self.map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchDataType(t, typ.into(), pos).into()
|
||||
}
|
||||
}
|
||||
|
144
src/func/call.rs
144
src/func/call.rs
@ -37,6 +37,7 @@ struct ArgBackup<'a> {
|
||||
|
||||
impl<'a> ArgBackup<'a> {
|
||||
/// Create a new `ArgBackup`.
|
||||
#[inline(always)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
orig_mut: None,
|
||||
@ -60,8 +61,8 @@ impl<'a> ArgBackup<'a> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `args` is empty.
|
||||
#[inline]
|
||||
fn change_first_arg_to_copy(&mut self, args: &mut FnCallArgs<'a>) {
|
||||
#[inline(always)]
|
||||
pub fn change_first_arg_to_copy(&mut self, args: &mut FnCallArgs<'a>) {
|
||||
// Clone the original value.
|
||||
self.value_copy = args[0].clone();
|
||||
|
||||
@ -86,7 +87,7 @@ impl<'a> ArgBackup<'a> {
|
||||
/// If `change_first_arg_to_copy` has been called, this function **MUST** be called _BEFORE_
|
||||
/// exiting the current scope. Otherwise it is undefined behavior as the shorter lifetime will leak.
|
||||
#[inline(always)]
|
||||
fn restore_first_arg(mut self, args: &mut FnCallArgs<'a>) {
|
||||
pub fn restore_first_arg(mut self, args: &mut FnCallArgs<'a>) {
|
||||
if let Some(p) = self.orig_mut.take() {
|
||||
args[0] = p;
|
||||
}
|
||||
@ -94,7 +95,7 @@ impl<'a> ArgBackup<'a> {
|
||||
}
|
||||
|
||||
impl Drop for ArgBackup<'_> {
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
fn drop(&mut self) {
|
||||
// Panic if the shorter lifetime leaks.
|
||||
assert!(
|
||||
@ -382,15 +383,12 @@ impl Engine {
|
||||
let mut _result = if let Some(FnResolutionCacheEntry { func, source }) = func {
|
||||
assert!(func.is_native());
|
||||
|
||||
let mut backup = ArgBackup::new();
|
||||
|
||||
// Calling pure function but the first argument is a reference?
|
||||
let mut backup: Option<ArgBackup> = None;
|
||||
if is_ref_mut && func.is_pure() && !args.is_empty() {
|
||||
// Clone the first argument
|
||||
backup = Some(ArgBackup::new());
|
||||
backup
|
||||
.as_mut()
|
||||
.expect("`Some`")
|
||||
.change_first_arg_to_copy(args);
|
||||
backup.change_first_arg_to_copy(args);
|
||||
}
|
||||
|
||||
let source = match (source.as_str(), parent_source.as_str()) {
|
||||
@ -420,9 +418,7 @@ impl Engine {
|
||||
};
|
||||
|
||||
// Restore the original reference
|
||||
if let Some(bk) = backup {
|
||||
bk.restore_first_arg(args)
|
||||
}
|
||||
backup.restore_first_arg(args);
|
||||
|
||||
result
|
||||
} else {
|
||||
@ -470,11 +466,8 @@ impl Engine {
|
||||
KEYWORD_PRINT => {
|
||||
if let Some(ref print) = self.print {
|
||||
let text = result.into_immutable_string().map_err(|typ| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
self.map_type_name(type_name::<ImmutableString>()).into(),
|
||||
typ.into(),
|
||||
pos,
|
||||
)
|
||||
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
||||
})?;
|
||||
(print(&text).into(), false)
|
||||
} else {
|
||||
@ -484,11 +477,8 @@ impl Engine {
|
||||
KEYWORD_DEBUG => {
|
||||
if let Some(ref debug) = self.debug {
|
||||
let text = result.into_immutable_string().map_err(|typ| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
self.map_type_name(type_name::<ImmutableString>()).into(),
|
||||
typ.into(),
|
||||
pos,
|
||||
)
|
||||
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
||||
})?;
|
||||
let source = match global.source.as_str() {
|
||||
"" => None,
|
||||
@ -511,15 +501,10 @@ impl Engine {
|
||||
crate::engine::FN_IDX_GET => {
|
||||
assert!(args.len() == 2);
|
||||
|
||||
Err(ERR::ErrorIndexingType(
|
||||
format!(
|
||||
"{} [{}]",
|
||||
self.map_type_name(args[0].type_name()),
|
||||
self.map_type_name(args[1].type_name())
|
||||
),
|
||||
pos,
|
||||
)
|
||||
.into())
|
||||
let t0 = self.map_type_name(args[0].type_name());
|
||||
let t1 = self.map_type_name(args[1].type_name());
|
||||
|
||||
Err(ERR::ErrorIndexingType(format!("{} [{}]", t0, t1), pos).into())
|
||||
}
|
||||
|
||||
// index setter function not found?
|
||||
@ -527,16 +512,11 @@ impl Engine {
|
||||
crate::engine::FN_IDX_SET => {
|
||||
assert!(args.len() == 3);
|
||||
|
||||
Err(ERR::ErrorIndexingType(
|
||||
format!(
|
||||
"{} [{}] = {}",
|
||||
self.map_type_name(args[0].type_name()),
|
||||
self.map_type_name(args[1].type_name()),
|
||||
self.map_type_name(args[2].type_name())
|
||||
),
|
||||
pos,
|
||||
)
|
||||
.into())
|
||||
let t0 = self.map_type_name(args[0].type_name());
|
||||
let t1 = self.map_type_name(args[1].type_name());
|
||||
let t2 = self.map_type_name(args[2].type_name());
|
||||
|
||||
Err(ERR::ErrorIndexingType(format!("{} [{}] = {}", t0, t1, t2), pos).into())
|
||||
}
|
||||
|
||||
// Getter function not found?
|
||||
@ -544,11 +524,13 @@ impl Engine {
|
||||
_ if name.starts_with(crate::engine::FN_GET) => {
|
||||
assert!(args.len() == 1);
|
||||
|
||||
let prop = &name[crate::engine::FN_GET.len()..];
|
||||
let t0 = self.map_type_name(args[0].type_name());
|
||||
|
||||
Err(ERR::ErrorDotExpr(
|
||||
format!(
|
||||
"Unknown property '{}' - a getter is not registered for type '{}'",
|
||||
&name[crate::engine::FN_GET.len()..],
|
||||
self.map_type_name(args[0].type_name())
|
||||
prop, t0
|
||||
),
|
||||
pos,
|
||||
)
|
||||
@ -560,12 +542,14 @@ impl Engine {
|
||||
_ if name.starts_with(crate::engine::FN_SET) => {
|
||||
assert!(args.len() == 2);
|
||||
|
||||
let prop = &name[crate::engine::FN_SET.len()..];
|
||||
let t0 = self.map_type_name(args[0].type_name());
|
||||
let t1 = self.map_type_name(args[1].type_name());
|
||||
|
||||
Err(ERR::ErrorDotExpr(
|
||||
format!(
|
||||
"No writable property '{}' - a setter is not registered for type '{}' to handle '{}'",
|
||||
&name[crate::engine::FN_SET.len()..],
|
||||
self.map_type_name(args[0].type_name()),
|
||||
self.map_type_name(args[1].type_name()),
|
||||
prop, t0, t1
|
||||
),
|
||||
pos,
|
||||
)
|
||||
@ -612,8 +596,11 @@ impl Engine {
|
||||
level: usize,
|
||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||
fn no_method_err(name: &str, pos: Position) -> RhaiResultOf<(Dynamic, bool)> {
|
||||
let msg = format!("'{0}' should not be called this way. Try {0}(...);", name);
|
||||
Err(ERR::ErrorRuntime(msg.into(), pos).into())
|
||||
Err(ERR::ErrorRuntime(
|
||||
(format!("'{0}' should not be called this way. Try {0}(...);", name)).into(),
|
||||
pos,
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
// Check for data race.
|
||||
@ -627,10 +614,8 @@ impl Engine {
|
||||
match fn_name {
|
||||
// Handle type_of()
|
||||
KEYWORD_TYPE_OF if args.len() == 1 => {
|
||||
return Ok((
|
||||
self.map_type_name(args[0].type_name()).to_string().into(),
|
||||
false,
|
||||
))
|
||||
let typ = self.map_type_name(args[0].type_name()).to_string().into();
|
||||
return Ok((typ, false));
|
||||
}
|
||||
|
||||
// Handle is_def_fn()
|
||||
@ -711,7 +696,7 @@ impl Engine {
|
||||
// Method call of script function - map first argument to `this`
|
||||
let (first_arg, rest_args) = args.split_first_mut().unwrap();
|
||||
|
||||
let result = self.call_script_fn(
|
||||
self.call_script_fn(
|
||||
scope,
|
||||
global,
|
||||
state,
|
||||
@ -722,19 +707,14 @@ impl Engine {
|
||||
true,
|
||||
pos,
|
||||
level,
|
||||
);
|
||||
|
||||
result?
|
||||
)
|
||||
} else {
|
||||
// Normal call of script function
|
||||
let mut backup = ArgBackup::new();
|
||||
|
||||
// The first argument is a reference?
|
||||
let mut backup: Option<ArgBackup> = None;
|
||||
if is_ref_mut && !args.is_empty() {
|
||||
backup = Some(ArgBackup::new());
|
||||
backup
|
||||
.as_mut()
|
||||
.expect("`Some`")
|
||||
.change_first_arg_to_copy(args);
|
||||
backup.change_first_arg_to_copy(args);
|
||||
}
|
||||
|
||||
let result = self.call_script_fn(
|
||||
@ -742,17 +722,15 @@ impl Engine {
|
||||
);
|
||||
|
||||
// Restore the original reference
|
||||
if let Some(bk) = backup {
|
||||
bk.restore_first_arg(args)
|
||||
}
|
||||
backup.restore_first_arg(args);
|
||||
|
||||
result?
|
||||
result
|
||||
};
|
||||
|
||||
// Restore the original source
|
||||
mem::swap(&mut global.source, &mut source);
|
||||
|
||||
return Ok((result, false));
|
||||
return Ok((result?, false));
|
||||
}
|
||||
|
||||
// Native function call
|
||||
@ -827,16 +805,12 @@ impl Engine {
|
||||
KEYWORD_FN_PTR_CALL => {
|
||||
if !call_args.is_empty() {
|
||||
if !call_args[0].is::<FnPtr>() {
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||
self.map_type_name(call_args[0].type_name()),
|
||||
*call_arg_pos,
|
||||
));
|
||||
let typ = self.map_type_name(call_args[0].type_name());
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, *call_arg_pos));
|
||||
}
|
||||
} else {
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||
self.map_type_name(target.type_name()),
|
||||
pos,
|
||||
));
|
||||
let typ = self.map_type_name(target.type_name());
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, pos));
|
||||
}
|
||||
|
||||
// FnPtr call on object
|
||||
@ -866,10 +840,8 @@ impl Engine {
|
||||
}
|
||||
KEYWORD_FN_PTR_CURRY => {
|
||||
if !target.is::<FnPtr>() {
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||
self.map_type_name(target.type_name()),
|
||||
pos,
|
||||
));
|
||||
let typ = self.map_type_name(target.type_name());
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, pos));
|
||||
}
|
||||
|
||||
let fn_ptr = target.read_lock::<FnPtr>().expect("`FnPtr`");
|
||||
@ -1016,10 +988,8 @@ impl Engine {
|
||||
self.get_arg_value(scope, global, state, lib, this_ptr, arg, level)?;
|
||||
|
||||
if !arg_value.is::<FnPtr>() {
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||
self.map_type_name(arg_value.type_name()),
|
||||
arg_pos,
|
||||
));
|
||||
let typ = self.map_type_name(arg_value.type_name());
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, arg_pos));
|
||||
}
|
||||
|
||||
let fn_ptr = arg_value.cast::<FnPtr>();
|
||||
@ -1066,10 +1036,8 @@ impl Engine {
|
||||
self.get_arg_value(scope, global, state, lib, this_ptr, first, level)?;
|
||||
|
||||
if !arg_value.is::<FnPtr>() {
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||
self.map_type_name(arg_value.type_name()),
|
||||
arg_pos,
|
||||
));
|
||||
let typ = self.map_type_name(arg_value.type_name());
|
||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, arg_pos));
|
||||
}
|
||||
|
||||
let (name, fn_curry) = arg_value.cast::<FnPtr>().take_data();
|
||||
|
@ -277,12 +277,8 @@ impl<'a> NativeCallContext<'a> {
|
||||
let typ = self.engine().map_type_name(result.type_name());
|
||||
|
||||
result.try_cast().ok_or_else(|| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
self.engine().map_type_name(type_name::<T>()).into(),
|
||||
typ.into(),
|
||||
Position::NONE,
|
||||
)
|
||||
.into()
|
||||
let t = self.engine().map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
||||
})
|
||||
}
|
||||
/// Call a function inside the call context.
|
||||
@ -348,7 +344,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume a [`Shared`] resource and return a mutable reference to the wrapped value.
|
||||
/// Return a mutable reference to the wrapped value of a [`Shared`] resource.
|
||||
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
@ -357,6 +353,14 @@ pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
|
||||
Shared::make_mut(value)
|
||||
}
|
||||
|
||||
/// Return a mutable reference to the wrapped value of a [`Shared`] resource.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub fn shared_get_mut<T: Clone>(value: &mut Shared<T>) -> Option<&mut T> {
|
||||
Shared::get_mut(value)
|
||||
}
|
||||
|
||||
/// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1085,7 +1085,8 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
||||
match x.name.as_str() {
|
||||
KEYWORD_TYPE_OF if arg_values.len() == 1 => {
|
||||
state.set_dirty();
|
||||
*expr = Expr::from_dynamic(state.engine.map_type_name(arg_values[0].type_name()).into(), *pos);
|
||||
let typ = state.engine.map_type_name(arg_values[0].type_name()).into();
|
||||
*expr = Expr::from_dynamic(typ, *pos);
|
||||
return;
|
||||
}
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
|
@ -193,7 +193,11 @@ mod string_functions {
|
||||
/// Clear the string, making it empty.
|
||||
pub fn clear(string: &mut ImmutableString) {
|
||||
if !string.is_empty() {
|
||||
string.make_mut().clear();
|
||||
if let Some(s) = string.get_mut() {
|
||||
s.clear();
|
||||
} else {
|
||||
*string = ImmutableString::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Cut off the string at the specified number of characters.
|
||||
@ -220,8 +224,8 @@ mod string_functions {
|
||||
let copy = string.make_mut();
|
||||
copy.clear();
|
||||
copy.extend(chars.into_iter().take(len as usize));
|
||||
} else if !string.is_empty() {
|
||||
string.make_mut().clear();
|
||||
} else {
|
||||
clear(string);
|
||||
}
|
||||
}
|
||||
/// Remove whitespace characters from both ends of the string.
|
||||
@ -231,13 +235,23 @@ mod string_functions {
|
||||
/// ```rhai
|
||||
/// let text = " hello ";
|
||||
///
|
||||
/// print(text.trim()); // prints "hello"
|
||||
/// text.trim();
|
||||
///
|
||||
/// print(text); // prints "hello"
|
||||
/// ```
|
||||
pub fn trim(string: &mut ImmutableString) {
|
||||
let trimmed = string.trim();
|
||||
if let Some(s) = string.get_mut() {
|
||||
let trimmed = s.trim();
|
||||
|
||||
if trimmed.len() < string.len() {
|
||||
*string = trimmed.to_string().into();
|
||||
if trimmed != s {
|
||||
*s = trimmed.into();
|
||||
}
|
||||
} else {
|
||||
let trimmed = string.trim();
|
||||
|
||||
if trimmed != string {
|
||||
*string = trimmed.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Remove the last character from the string and return it.
|
||||
@ -313,7 +327,7 @@ mod string_functions {
|
||||
/// ```
|
||||
#[rhai_fn(pure)]
|
||||
pub fn to_upper(string: &mut ImmutableString) -> ImmutableString {
|
||||
if string.is_empty() || string.chars().all(char::is_uppercase) {
|
||||
if string.chars().all(char::is_uppercase) {
|
||||
string.clone()
|
||||
} else {
|
||||
string.to_uppercase().into()
|
||||
@ -366,7 +380,7 @@ mod string_functions {
|
||||
/// print(text); // prints "hello, world!";
|
||||
/// ```
|
||||
pub fn make_lower(string: &mut ImmutableString) {
|
||||
if !string.is_empty() && string.chars().any(|ch| !ch.is_lowercase()) {
|
||||
if string.chars().any(|ch| !ch.is_lowercase()) {
|
||||
*string = string.to_lowercase().into();
|
||||
}
|
||||
}
|
||||
|
@ -162,12 +162,8 @@ impl FnPtr {
|
||||
let typ = engine.map_type_name(result.type_name());
|
||||
|
||||
result.try_cast().ok_or_else(|| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
engine.map_type_name(type_name::<T>()).into(),
|
||||
typ.into(),
|
||||
Position::NONE,
|
||||
)
|
||||
.into()
|
||||
let t = engine.map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
||||
})
|
||||
}
|
||||
/// Call the function pointer with curried arguments (if any).
|
||||
@ -190,12 +186,8 @@ impl FnPtr {
|
||||
let typ = context.engine().map_type_name(result.type_name());
|
||||
|
||||
result.try_cast().ok_or_else(|| {
|
||||
ERR::ErrorMismatchOutputType(
|
||||
context.engine().map_type_name(type_name::<T>()).into(),
|
||||
typ.into(),
|
||||
Position::NONE,
|
||||
)
|
||||
.into()
|
||||
let t = context.engine().map_type_name(type_name::<T>()).into();
|
||||
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
||||
})
|
||||
}
|
||||
/// Call the function pointer with curried arguments (if any).
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! The `ImmutableString` type.
|
||||
|
||||
use crate::func::native::{shared_make_mut, shared_take};
|
||||
use crate::func::native::{shared_get_mut, shared_make_mut, shared_take};
|
||||
use crate::{Shared, SmartString};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@ -580,6 +580,7 @@ impl ImmutableString {
|
||||
Self(SmartString::new_const().into())
|
||||
}
|
||||
/// Consume the [`ImmutableString`] and convert it into a [`String`].
|
||||
///
|
||||
/// If there are other references to the same string, a cloned copy is returned.
|
||||
#[inline]
|
||||
pub fn into_owned(mut self) -> String {
|
||||
@ -588,10 +589,17 @@ impl ImmutableString {
|
||||
}
|
||||
/// Make sure that the [`ImmutableString`] is unique (i.e. no other outstanding references).
|
||||
/// Then return a mutable reference to the [`SmartString`].
|
||||
///
|
||||
/// If there are other references to the same string, a cloned copy is used.
|
||||
#[inline(always)]
|
||||
pub(crate) fn make_mut(&mut self) -> &mut SmartString {
|
||||
shared_make_mut(&mut self.0)
|
||||
}
|
||||
/// Return a mutable reference to the [`SmartString`] wrapped by the [`ImmutableString`].
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_mut(&mut self) -> Option<&mut SmartString> {
|
||||
shared_get_mut(&mut self.0)
|
||||
}
|
||||
/// Returns `true` if the two [`ImmutableString`]'s point to the same allocation.
|
||||
///
|
||||
/// # Example
|
||||
|
Loading…
Reference in New Issue
Block a user