Add #[must_use]

This commit is contained in:
Stephen Chung 2021-06-12 22:47:43 +08:00
parent 68ea8c27fd
commit 8ca24059b1
28 changed files with 489 additions and 55 deletions

View File

@ -216,6 +216,7 @@ impl Default for AST {
impl AST {
/// Create a new [`AST`].
#[inline(always)]
#[must_use]
pub fn new(
statements: impl IntoIterator<Item = Stmt>,
functions: impl Into<Shared<Module>>,
@ -230,6 +231,7 @@ impl AST {
}
/// Create a new [`AST`] with a source name.
#[inline(always)]
#[must_use]
pub fn new_with_source(
statements: impl IntoIterator<Item = Stmt>,
functions: impl Into<Shared<Module>>,
@ -245,11 +247,13 @@ impl AST {
}
/// Get the source, if any.
#[inline(always)]
#[must_use]
pub fn source(&self) -> Option<&str> {
self.source.as_ref().map(|s| s.as_str())
}
/// Clone the source, if any.
#[inline(always)]
#[must_use]
pub(crate) fn clone_source(&self) -> Option<Identifier> {
self.source.clone()
}
@ -272,6 +276,7 @@ impl AST {
/// Get the statements.
#[cfg(not(feature = "internals"))]
#[inline(always)]
#[must_use]
pub(crate) fn statements(&self) -> &[Stmt] {
&self.body.0
}
@ -280,12 +285,14 @@ impl AST {
#[cfg(feature = "internals")]
#[deprecated = "this method is volatile and may change"]
#[inline(always)]
#[must_use]
pub fn statements(&self) -> &[Stmt] {
&self.body.0
}
/// Get a mutable reference to the statements.
#[cfg(not(feature = "no_optimize"))]
#[inline(always)]
#[must_use]
pub(crate) fn statements_mut(&mut self) -> &mut StaticVec<Stmt> {
&mut self.body.0
}
@ -294,6 +301,7 @@ impl AST {
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub(crate) fn shared_lib(&self) -> Shared<Module> {
self.functions.clone()
}
@ -306,12 +314,14 @@ impl AST {
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn shared_lib(&self) -> Shared<Module> {
self.functions.clone()
}
/// Get the internal [`Module`] containing all script-defined functions.
#[cfg(not(feature = "internals"))]
#[inline(always)]
#[must_use]
pub(crate) fn lib(&self) -> &Module {
&self.functions
}
@ -322,6 +332,7 @@ impl AST {
#[cfg(feature = "internals")]
#[deprecated = "this method is volatile and may change"]
#[inline(always)]
#[must_use]
pub fn lib(&self) -> &Module {
&self.functions
}
@ -329,6 +340,7 @@ impl AST {
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "internals"))]
#[inline(always)]
#[must_use]
pub(crate) fn resolver(
&self,
) -> Option<Shared<crate::module::resolvers::StaticModuleResolver>> {
@ -341,6 +353,7 @@ impl AST {
#[cfg(not(feature = "no_module"))]
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn resolver(&self) -> Option<Shared<crate::module::resolvers::StaticModuleResolver>> {
self.resolver.clone()
}
@ -362,6 +375,7 @@ impl AST {
/// This operation is cheap because functions are shared.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn clone_functions_only(&self) -> Self {
self.clone_functions_only_filtered(|_, _, _, _, _| true)
}
@ -373,6 +387,7 @@ impl AST {
/// This operation is cheap because functions are shared.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn clone_functions_only_filtered(
&self,
filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool,
@ -390,6 +405,7 @@ impl AST {
/// Clone the [`AST`]'s script statements into a new [`AST`].
/// No functions are cloned.
#[inline(always)]
#[must_use]
pub fn clone_statements_only(&self) -> Self {
Self {
source: self.source.clone(),
@ -449,6 +465,7 @@ impl AST {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn merge(&self, other: &Self) -> Self {
self.merge_filtered(other, |_, _, _, _, _| true)
}
@ -557,6 +574,7 @@ impl AST {
/// # }
/// ```
#[inline]
#[must_use]
pub fn merge_filtered(
&self,
other: &Self,
@ -694,6 +712,7 @@ impl AST {
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub(crate) fn iter_fn_def(&self) -> impl Iterator<Item = &ScriptFnDef> {
self.functions
.iter_script_fn()
@ -704,6 +723,7 @@ impl AST {
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = ScriptFnMetadata> + 'a {
self.functions
.iter_script_fn()
@ -714,13 +734,15 @@ impl AST {
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
pub fn clear_functions(&mut self) {
pub fn clear_functions(&mut self) -> &mut Self {
self.functions = Default::default();
self
}
/// Clear all statements in the [`AST`], leaving only function definitions.
#[inline(always)]
pub fn clear_statements(&mut self) {
pub fn clear_statements(&mut self) -> &mut Self {
self.body = Default::default();
self
}
/// Recursively walk the [`AST`], including function bodies (if any).
/// Return `false` from the callback to terminate the walk.
@ -869,25 +891,32 @@ pub struct StmtBlock(StaticVec<Stmt>, Position);
impl StmtBlock {
/// Create a new [`StmtBlock`].
#[must_use]
pub fn new(mut statements: StaticVec<Stmt>, pos: Position) -> Self {
statements.shrink_to_fit();
Self(statements, pos)
}
/// Is this statements block empty?
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Number of statements in this statements block.
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
/// Get the position of this statements block.
#[inline(always)]
#[must_use]
pub fn position(&self) -> Position {
self.1
}
/// Get the statements of this statements block.
#[inline(always)]
#[must_use]
pub fn statements(&mut self) -> &mut StaticVec<Stmt> {
&mut self.0
}
@ -896,12 +925,14 @@ impl StmtBlock {
impl Deref for StmtBlock {
type Target = StaticVec<Stmt>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for StmtBlock {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
@ -917,6 +948,7 @@ impl fmt::Debug for StmtBlock {
}
impl From<StmtBlock> for Stmt {
#[inline(always)]
fn from(block: StmtBlock) -> Self {
let block_pos = block.position();
Self::Block(block.0.into_boxed_slice(), block_pos)
@ -1015,6 +1047,7 @@ impl From<Stmt> for StmtBlock {
impl Stmt {
/// Is this statement [`Noop`][Stmt::Noop]?
#[inline(always)]
#[must_use]
pub fn is_noop(&self) -> bool {
match self {
Self::Noop(_) => true,
@ -1022,6 +1055,7 @@ impl Stmt {
}
}
/// Get the [position][Position] of this statement.
#[must_use]
pub fn position(&self) -> Position {
match self {
Self::Noop(pos)
@ -1086,6 +1120,7 @@ impl Stmt {
self
}
/// Does this statement return a value?
#[must_use]
pub fn returns_value(&self) -> bool {
match self {
Self::If(_, _, _)
@ -1115,6 +1150,7 @@ impl Stmt {
}
}
/// Is this statement self-terminated (i.e. no need for a semicolon terminator)?
#[must_use]
pub fn is_self_terminated(&self) -> bool {
match self {
Self::If(_, _, _)
@ -1147,6 +1183,7 @@ impl Stmt {
/// Is this statement _pure_?
///
/// A pure statement has no side effects.
#[must_use]
pub fn is_pure(&self) -> bool {
match self {
Self::Noop(_) => true,
@ -1194,6 +1231,7 @@ impl Stmt {
/// Only variable declarations (i.e. `let` and `const`) and `import`/`export` statements
/// are internally pure.
#[inline(always)]
#[must_use]
pub fn is_internally_pure(&self) -> bool {
match self {
Self::Let(expr, _, _, _) | Self::Const(expr, _, _, _) => expr.is_pure(),
@ -1212,6 +1250,7 @@ impl Stmt {
///
/// All statements following this statement will essentially be dead code.
#[inline(always)]
#[must_use]
pub fn is_control_flow_break(&self) -> bool {
match self {
Self::Return(_, _, _) | Self::Break(_) | Self::Continue(_) => true,
@ -1397,6 +1436,7 @@ impl OpAssignment<'_> {
/// # Panics
///
/// Panics if the operator name is not an op-assignment operator.
#[must_use]
pub fn new(op: Token) -> Self {
let op_raw = op
.map_op_assignment()
@ -1466,6 +1506,7 @@ impl fmt::Debug for FnCallHashes {
impl FnCallHashes {
/// Create a [`FnCallHashes`] with only the native Rust hash.
#[inline(always)]
#[must_use]
pub fn from_native(hash: u64) -> Self {
Self {
script: None,
@ -1474,6 +1515,7 @@ impl FnCallHashes {
}
/// Create a [`FnCallHashes`] with both native Rust and script function hashes set to the same value.
#[inline(always)]
#[must_use]
pub fn from_script(hash: u64) -> Self {
Self {
script: Some(hash),
@ -1482,6 +1524,7 @@ impl FnCallHashes {
}
/// Create a [`FnCallHashes`] with both native Rust and script function hashes.
#[inline(always)]
#[must_use]
pub fn from_script_and_native(script: u64, native: u64) -> Self {
Self {
script: Some(script),
@ -1490,16 +1533,19 @@ impl FnCallHashes {
}
/// Is this [`FnCallHashes`] native Rust only?
#[inline(always)]
#[must_use]
pub fn is_native_only(&self) -> bool {
self.script.is_none()
}
/// Get the script function hash from this [`FnCallHashes`].
#[inline(always)]
#[must_use]
pub fn script_hash(&self) -> Option<u64> {
self.script
}
/// Get the naive Rust function hash from this [`FnCallHashes`].
#[inline(always)]
#[must_use]
pub fn native_hash(&self) -> u64 {
self.native
}
@ -1530,6 +1576,7 @@ pub struct FnCallExpr {
impl FnCallExpr {
/// Does this function call contain a qualified namespace?
#[inline(always)]
#[must_use]
pub fn is_qualified(&self) -> bool {
self.namespace.is_some()
}
@ -1638,6 +1685,7 @@ impl<F: Float> FloatWrapper<F> {
pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.0000000000001;
#[inline(always)]
#[must_use]
pub fn new(value: F) -> Self {
Self(value)
}
@ -1646,6 +1694,7 @@ impl<F: Float> FloatWrapper<F> {
#[cfg(not(feature = "no_float"))]
impl FloatWrapper<FLOAT> {
#[inline(always)]
#[must_use]
pub(crate) const fn const_new(value: FLOAT) -> Self {
Self(value)
}
@ -1823,6 +1872,7 @@ impl Expr {
///
/// Returns [`None`] if the expression is not a literal constant.
#[inline]
#[must_use]
pub fn get_literal_value(&self) -> Option<Dynamic> {
Some(match self {
Self::DynamicConstant(x, _) => x.as_ref().clone(),
@ -1861,6 +1911,7 @@ impl Expr {
}
/// Create an [`Expr`] from a [`Dynamic`] value.
#[inline]
#[must_use]
pub fn from_dynamic(value: Dynamic, pos: Position) -> Self {
match value.0 {
Union::Unit(_, _, _) => Self::Unit(pos),
@ -1877,6 +1928,7 @@ impl Expr {
}
/// Is the expression a simple variable access?
#[inline(always)]
#[must_use]
pub(crate) fn is_variable_access(&self, non_qualified: bool) -> bool {
match self {
Self::Variable(_, _, x) => !non_qualified || x.1.is_none(),
@ -1885,6 +1937,7 @@ impl Expr {
}
/// Return the variable name if the expression a simple variable access.
#[inline(always)]
#[must_use]
pub(crate) fn get_variable_name(&self, non_qualified: bool) -> Option<&str> {
match self {
Self::Variable(_, _, x) if !non_qualified || x.1.is_none() => Some(x.2.as_str()),
@ -1893,6 +1946,7 @@ impl Expr {
}
/// Get the [position][Position] of the expression.
#[inline]
#[must_use]
pub fn position(&self) -> Position {
match self {
#[cfg(not(feature = "no_float"))]
@ -1966,6 +2020,7 @@ impl Expr {
///
/// A pure expression has no side effects.
#[inline]
#[must_use]
pub fn is_pure(&self) -> bool {
match self {
Self::InterpolatedString(x) | Self::Array(x, _) => x.iter().all(Self::is_pure),
@ -1983,6 +2038,7 @@ impl Expr {
}
/// Is the expression the unit `()` literal?
#[inline(always)]
#[must_use]
pub fn is_unit(&self) -> bool {
match self {
Self::Unit(_) => true,
@ -1991,6 +2047,7 @@ impl Expr {
}
/// Is the expression a constant?
#[inline]
#[must_use]
pub fn is_constant(&self) -> bool {
match self {
#[cfg(not(feature = "no_float"))]
@ -2013,6 +2070,7 @@ impl Expr {
}
/// Is a particular [token][Token] allowed as a postfix operator to this expression?
#[inline]
#[must_use]
pub fn is_valid_postfix(&self, token: &Token) -> bool {
match token {
#[cfg(not(feature = "no_object"))]

View File

@ -55,21 +55,27 @@ mod private {
#[cfg(not(feature = "sync"))]
pub trait Variant: Any + private::Sealed {
/// Convert this [`Variant`] trait object to [`&dyn Any`][Any].
#[must_use]
fn as_any(&self) -> &dyn Any;
/// Convert this [`Variant`] trait object to [`&mut dyn Any`][Any].
#[must_use]
fn as_mut_any(&mut self) -> &mut dyn Any;
/// Convert this [`Variant`] trait object to an [`Any`] trait object.
#[must_use]
fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
/// Get the name of this type.
#[must_use]
fn type_name(&self) -> &'static str;
/// Convert into [`Dynamic`].
#[must_use]
fn into_dynamic(self) -> Dynamic;
/// Clone into [`Dynamic`].
#[must_use]
fn clone_into_dynamic(&self) -> Dynamic;
}
@ -80,21 +86,27 @@ pub trait Variant: Any + private::Sealed {
#[cfg(feature = "sync")]
pub trait Variant: Any + Send + Sync + private::Sealed {
/// Convert this [`Variant`] trait object to [`&dyn Any`][Any].
#[must_use]
fn as_any(&self) -> &dyn Any;
/// Convert this [`Variant`] trait object to [`&mut dyn Any`][Any].
#[must_use]
fn as_mut_any(&mut self) -> &mut dyn Any;
/// Convert this [`Variant`] trait object to an [`Any`] trait object.
#[must_use]
fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
/// Get the name of this type.
#[must_use]
fn type_name(&self) -> &'static str;
/// Convert into [`Dynamic`].
#[must_use]
fn into_dynamic(self) -> Dynamic;
/// Clone into [`Dynamic`].
#[must_use]
fn clone_into_dynamic(&self) -> Dynamic;
}
@ -128,6 +140,7 @@ impl<T: Any + Clone + SendSync> Variant for T {
impl dyn Variant {
/// Is this [`Variant`] a specific type?
#[inline(always)]
#[must_use]
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id()
}
@ -308,6 +321,7 @@ impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
impl Dynamic {
/// Get the arbitrary data attached to this [`Dynamic`].
#[must_use]
pub const fn tag(&self) -> Tag {
match self.0 {
Union::Unit(_, tag, _)
@ -333,7 +347,7 @@ impl Dynamic {
}
}
/// Attach arbitrary data to this [`Dynamic`].
pub fn set_tag(&mut self, value: Tag) {
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
match &mut self.0 {
Union::Unit(_, tag, _)
| Union::Bool(_, tag, _)
@ -356,10 +370,12 @@ impl Dynamic {
#[cfg(not(feature = "no_closure"))]
Union::Shared(_, tag, _) => *tag = value,
}
self
}
/// Does this [`Dynamic`] hold a variant data type
/// instead of one of the supported system primitive types?
#[inline(always)]
#[must_use]
pub const fn is_variant(&self) -> bool {
match self.0 {
Union::Variant(_, _, _) => true,
@ -371,6 +387,7 @@ impl Dynamic {
/// Not available under `no_closure`.
#[cfg(not(feature = "no_closure"))]
#[inline(always)]
#[must_use]
pub const fn is_shared(&self) -> bool {
#[cfg(not(feature = "no_closure"))]
match self.0 {
@ -385,6 +402,7 @@ impl Dynamic {
/// If the [`Dynamic`] is a shared variant checking is performed on
/// top of its internal value.
#[inline(always)]
#[must_use]
pub fn is<T: Any + Clone>(&self) -> bool {
let mut target_type_id = TypeId::of::<T>();
@ -400,6 +418,7 @@ impl Dynamic {
///
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
/// Otherwise, this call panics if the data is currently borrowed for write.
#[must_use]
pub fn type_id(&self) -> TypeId {
match &self.0 {
Union::Unit(_, _, _) => TypeId::of::<()>(),
@ -438,6 +457,7 @@ impl Dynamic {
///
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
/// Otherwise, this call panics if the data is currently borrowed for write.
#[must_use]
pub fn type_name(&self) -> &'static str {
match &self.0 {
Union::Unit(_, _, _) => "()",
@ -561,6 +581,7 @@ impl Hash for Dynamic {
/// Map the name of a standard type into a friendly form.
#[inline(always)]
#[must_use]
pub(crate) fn map_std_type_name(name: &str) -> &str {
if name == type_name::<String>() {
return "string";
@ -803,6 +824,7 @@ impl Clone for Dynamic {
impl Default for Dynamic {
#[inline(always)]
#[must_use]
fn default() -> Self {
Self::UNIT
}
@ -872,6 +894,7 @@ impl Dynamic {
));
/// Get the [`AccessMode`] for this [`Dynamic`].
#[must_use]
pub(crate) const fn access_mode(&self) -> AccessMode {
match self.0 {
Union::Unit(_, _, access)
@ -897,7 +920,7 @@ impl Dynamic {
}
}
/// Set the [`AccessMode`] for this [`Dynamic`].
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) {
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
match &mut self.0 {
Union::Unit(_, _, access)
| Union::Bool(_, _, access)
@ -914,18 +937,23 @@ impl Dynamic {
#[cfg(not(feature = "no_index"))]
Union::Array(a, _, access) => {
*access = typ;
a.iter_mut().for_each(|v| v.set_access_mode(typ));
a.iter_mut().for_each(|v| {
v.set_access_mode(typ);
});
}
#[cfg(not(feature = "no_object"))]
Union::Map(m, _, access) => {
*access = typ;
m.values_mut().for_each(|v| v.set_access_mode(typ));
m.values_mut().for_each(|v| {
v.set_access_mode(typ);
});
}
#[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, access) => *access = typ,
#[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, access) => *access = typ,
}
self
}
/// Is this [`Dynamic`] read-only?
///
@ -934,6 +962,7 @@ impl Dynamic {
/// [`ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant]
/// if its value is going to be modified. This safe-guards constant values from being modified
/// from within Rust functions.
#[must_use]
pub fn is_read_only(&self) -> bool {
#[cfg(not(feature = "no_closure"))]
match self.0 {
@ -958,6 +987,7 @@ impl Dynamic {
}
}
/// Can this [`Dynamic`] be hashed?
#[must_use]
pub(crate) fn is_hashable(&self) -> bool {
match &self.0 {
Union::Unit(_, _, _)
@ -1019,6 +1049,7 @@ impl Dynamic {
/// assert_eq!(new_result.to_string(), "hello");
/// ```
#[inline(always)]
#[must_use]
pub fn from<T: Variant + Clone>(mut value: T) -> Self {
// Coded this way in order to maximally leverage potentials for dead-code removal.
@ -1124,6 +1155,7 @@ impl Dynamic {
/// If the [`Dynamic`] value is already shared, this method returns itself.
#[cfg(not(feature = "no_closure"))]
#[inline(always)]
#[must_use]
pub fn into_shared(self) -> Self {
let _access = self.access_mode();
@ -1160,6 +1192,7 @@ impl Dynamic {
/// assert_eq!(x.try_cast::<u32>().unwrap(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn try_cast<T: Any>(self) -> Option<T> {
// Coded this way in order to maximally leverage potentials for dead-code removal.
@ -1295,6 +1328,7 @@ impl Dynamic {
/// assert_eq!(x.cast::<u32>(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn cast<T: Any + Clone>(self) -> T {
#[cfg(not(feature = "no_closure"))]
let self_type_name = if self.is_shared() {
@ -1342,6 +1376,7 @@ impl Dynamic {
/// assert_eq!(y.clone_cast::<u32>(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn clone_cast<T: Any + Clone>(&self) -> T {
self.flatten_clone().cast::<T>()
}
@ -1351,6 +1386,7 @@ impl Dynamic {
///
/// If the [`Dynamic`] is a shared value, it returns a cloned copy of the shared value.
#[inline(always)]
#[must_use]
pub fn flatten_clone(&self) -> Self {
#[cfg(not(feature = "no_closure"))]
match &self.0 {
@ -1374,6 +1410,7 @@ impl Dynamic {
/// If the [`Dynamic`] is a shared value, it returns the shared value if there are no
/// outstanding references, or a cloned copy.
#[inline(always)]
#[must_use]
pub fn flatten(self) -> Self {
#[cfg(not(feature = "no_closure"))]
match self.0 {
@ -1407,7 +1444,7 @@ impl Dynamic {
/// If the [`Dynamic`] is a shared value, it is set to the shared value if there are no
/// outstanding references, or a cloned copy otherwise.
#[inline(always)]
pub(crate) fn flatten_in_place(&mut self) {
pub(crate) fn flatten_in_place(&mut self) -> &mut Self {
#[cfg(not(feature = "no_closure"))]
match self.0 {
Union::Shared(_, _, _) => match std::mem::take(self).0 {
@ -1433,6 +1470,7 @@ impl Dynamic {
},
_ => (),
}
self
}
/// Is the [`Dynamic`] a shared value that is locked?
///
@ -1445,6 +1483,7 @@ impl Dynamic {
/// So this method always returns [`false`] under [`Sync`].
#[cfg(not(feature = "no_closure"))]
#[inline(always)]
#[must_use]
pub fn is_locked(&self) -> bool {
#[cfg(not(feature = "no_closure"))]
match self.0 {
@ -1470,6 +1509,7 @@ impl Dynamic {
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
/// Otherwise, this call panics if the data is currently borrowed for write.
#[inline(always)]
#[must_use]
pub fn read_lock<T: Any + Clone>(&self) -> Option<DynamicReadLock<T>> {
match self.0 {
#[cfg(not(feature = "no_closure"))]
@ -1503,6 +1543,7 @@ impl Dynamic {
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
/// Otherwise, this call panics if the data is currently borrowed for write.
#[inline(always)]
#[must_use]
pub fn write_lock<T: Any + Clone>(&mut self) -> Option<DynamicWriteLock<T>> {
match self.0 {
#[cfg(not(feature = "no_closure"))]
@ -1531,6 +1572,7 @@ impl Dynamic {
///
/// Returns [`None`] if the cast fails, or if the value is shared.
#[inline(always)]
#[must_use]
pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
// Coded this way in order to maximally leverage potentials for dead-code removal.
@ -1621,6 +1663,7 @@ impl Dynamic {
///
/// Returns [`None`] if the cast fails, or if the value is shared.
#[inline(always)]
#[must_use]
pub(crate) fn downcast_mut<T: Any + Clone>(&mut self) -> Option<&mut T> {
// Coded this way in order to maximally leverage potentials for dead-code removal.
@ -1709,6 +1752,7 @@ impl Dynamic {
/// Cast the [`Dynamic`] as a unit `()` and return it.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_unit(&self) -> Result<(), &'static str> {
match self.0 {
Union::Unit(value, _, _) => Ok(value),
@ -1720,6 +1764,7 @@ impl Dynamic {
/// Cast the [`Dynamic`] as the system integer type [`INT`] and return it.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_int(&self) -> Result<INT, &'static str> {
match self.0 {
Union::Int(n, _, _) => Ok(n),
@ -1734,6 +1779,7 @@ impl Dynamic {
/// Not available under `no_float`.
#[cfg(not(feature = "no_float"))]
#[inline(always)]
#[must_use]
pub fn as_float(&self) -> Result<FLOAT, &'static str> {
match self.0 {
Union::Float(n, _, _) => Ok(*n),
@ -1748,6 +1794,7 @@ impl Dynamic {
/// Exported under the `decimal` feature only.
#[cfg(feature = "decimal")]
#[inline(always)]
#[must_use]
pub fn as_decimal(&self) -> Result<Decimal, &'static str> {
match self.0 {
Union::Decimal(ref n, _, _) => Ok(**n),
@ -1759,6 +1806,7 @@ impl Dynamic {
/// Cast the [`Dynamic`] as a [`bool`] and return it.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_bool(&self) -> Result<bool, &'static str> {
match self.0 {
Union::Bool(b, _, _) => Ok(b),
@ -1770,6 +1818,7 @@ impl Dynamic {
/// Cast the [`Dynamic`] as a [`char`] and return it.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_char(&self) -> Result<char, &'static str> {
match self.0 {
Union::Char(n, _, _) => Ok(n),
@ -1785,6 +1834,7 @@ impl Dynamic {
///
/// Panics if the value is shared.
#[inline(always)]
#[must_use]
pub(crate) fn as_str_ref(&self) -> Result<&str, &'static str> {
match self.0 {
Union::Str(ref s, _, _) => Ok(s),
@ -1802,6 +1852,7 @@ impl Dynamic {
/// This method is deprecated and will be removed in the future.
/// Use [`as_string`][Dynamic::as_string] instead.
#[inline(always)]
#[must_use]
#[deprecated(
since = "0.20.3",
note = "this method is deprecated and will be removed in the future"
@ -1813,6 +1864,7 @@ impl Dynamic {
/// If there are other references to the same string, a cloned copy is returned.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_string(self) -> Result<String, &'static str> {
self.as_immutable_string().map(ImmutableString::into_owned)
}
@ -1824,6 +1876,7 @@ impl Dynamic {
/// This method is deprecated and will be removed in the future.
/// Use [`as_immutable_string`][Dynamic::as_immutable_string] instead.
#[inline(always)]
#[must_use]
#[deprecated(
since = "0.20.3",
note = "this method is deprecated and will be removed in the future"
@ -1834,6 +1887,7 @@ impl Dynamic {
/// Convert the [`Dynamic`] into an [`ImmutableString`] and return it.
/// Returns the name of the actual type if the cast fails.
#[inline(always)]
#[must_use]
pub fn as_immutable_string(self) -> Result<ImmutableString, &'static str> {
match self.0 {
Union::Str(s, _, _) => Ok(s),

View File

@ -64,27 +64,32 @@ pub struct Imports {
impl Imports {
/// Get the length of this stack of imported [modules][Module].
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.keys.len()
}
/// Is this stack of imported [modules][Module] empty?
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.keys.is_empty()
}
/// Get the imported [modules][Module] at a particular index.
#[inline(always)]
#[must_use]
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
self.modules.get(index).cloned()
}
/// Get the imported [modules][Module] at a particular index.
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> {
self.modules.get_mut(index)
}
/// Get the index of an imported [modules][Module] by name.
#[inline(always)]
#[must_use]
pub fn find(&self, name: &str) -> Option<usize> {
self.keys
.iter()
@ -107,6 +112,7 @@ impl Imports {
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
self.keys
.iter()
@ -117,17 +123,20 @@ impl Imports {
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub(crate) fn iter_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
self.keys.iter().rev().zip(self.modules.iter().rev())
}
/// Get an iterator to this stack of imported [modules][Module] in forward order.
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
self.keys.iter().zip(self.modules.iter())
}
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
#[inline(always)]
#[must_use]
pub fn into_iter(self) -> impl Iterator<Item = (Identifier, Shared<Module>)> {
self.keys
.into_iter()
@ -137,11 +146,13 @@ impl Imports {
/// Does the specified function hash key exist in this stack of imported [modules][Module]?
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub fn contains_fn(&self, hash: u64) -> bool {
self.modules.iter().any(|m| m.contains_qualified_fn(hash))
}
/// Get specified function via its hash key.
#[inline(always)]
#[must_use]
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&Identifier>)> {
self.modules
.iter()
@ -152,11 +163,13 @@ impl Imports {
/// imported [modules][Module]?
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub fn contains_iter(&self, id: TypeId) -> bool {
self.modules.iter().any(|m| m.contains_qualified_iter(id))
}
/// Get the specified [`TypeId`][std::any::TypeId] iterator.
#[inline(always)]
#[must_use]
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.modules
.iter()
@ -278,6 +291,7 @@ impl ChainArgument {
/// Panics if not `ChainArgument::IndexValue`.
#[inline(always)]
#[cfg(not(feature = "no_index"))]
#[must_use]
pub fn as_index_value(self) -> Dynamic {
match self {
#[cfg(not(feature = "no_object"))]
@ -294,6 +308,7 @@ impl ChainArgument {
/// Panics if not `ChainArgument::MethodCallArgs`.
#[inline(always)]
#[cfg(not(feature = "no_object"))]
#[must_use]
pub fn as_fn_call_args(self) -> (StaticVec<Dynamic>, Position) {
match self {
Self::Property(_) => {
@ -349,6 +364,7 @@ impl<'a> Target<'a> {
/// Is the `Target` a reference pointing to other data?
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub fn is_ref(&self) -> bool {
match self {
Self::RefMut(_) => true,
@ -363,6 +379,7 @@ impl<'a> Target<'a> {
}
/// Is the `Target` a temp value?
#[inline(always)]
#[must_use]
pub fn is_temp_value(&self) -> bool {
match self {
Self::RefMut(_) => false,
@ -378,6 +395,7 @@ impl<'a> Target<'a> {
/// Is the `Target` a shared value?
#[cfg(not(feature = "no_closure"))]
#[inline(always)]
#[must_use]
pub fn is_shared(&self) -> bool {
match self {
Self::RefMut(r) => r.is_shared(),
@ -393,6 +411,7 @@ impl<'a> Target<'a> {
/// Is the `Target` a specific type?
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub fn is<T: Variant + Clone>(&self) -> bool {
match self {
Self::RefMut(r) => r.is::<T>(),
@ -407,6 +426,7 @@ impl<'a> Target<'a> {
}
/// Get the value of the `Target` as a `Dynamic`, cloning a referenced value if necessary.
#[inline(always)]
#[must_use]
pub fn take_or_clone(self) -> Dynamic {
match self {
Self::RefMut(r) => r.clone(), // Referenced value is cloned
@ -421,6 +441,7 @@ impl<'a> Target<'a> {
}
/// Take a `&mut Dynamic` reference from the `Target`.
#[inline(always)]
#[must_use]
pub fn take_ref(self) -> Option<&'a mut Dynamic> {
match self {
Self::RefMut(r) => Some(r),
@ -429,12 +450,14 @@ impl<'a> Target<'a> {
}
/// Convert a shared or reference `Target` into a target with an owned value.
#[inline(always)]
#[must_use]
pub fn into_owned(self) -> Target<'static> {
self.take_or_clone().into()
}
/// Propagate a changed value back to the original source.
/// This has no effect except for string indexing.
#[inline(always)]
#[must_use]
pub fn propagate_changed_value(&mut self) -> Result<(), Box<EvalAltResult>> {
match self {
Self::RefMut(_) | Self::TempValue(_) => (),
@ -566,6 +589,7 @@ impl AsMut<Dynamic> for Target<'_> {
impl<T: Into<Dynamic>> From<T> for Target<'_> {
#[inline(always)]
#[must_use]
fn from(value: T) -> Self {
Self::TempValue(value.into())
}
@ -614,11 +638,13 @@ pub struct State {
impl State {
/// Is the state currently at global (root) level?
#[inline(always)]
#[must_use]
pub fn is_global(&self) -> bool {
self.scope_level == 0
}
/// Get a mutable reference to the current function resolution cache.
#[inline(always)]
#[must_use]
pub fn fn_resolution_cache_mut(&mut self) -> &mut FnResolutionCache {
if self.fn_resolution_caches.0.is_empty() {
// Push a new function resolution cache if the stack is empty
@ -714,27 +740,32 @@ pub struct EvalContext<'a, 'x, 'px, 'm, 's, 't, 'pt> {
impl<'x, 'px> EvalContext<'_, 'x, 'px, '_, '_, '_, '_> {
/// The current [`Engine`].
#[inline(always)]
#[must_use]
pub fn engine(&self) -> &Engine {
self.engine
}
/// The current source.
#[inline(always)]
#[must_use]
pub fn source(&self) -> Option<&str> {
self.state.source.as_ref().map(|s| s.as_str())
}
/// The current [`Scope`].
#[inline(always)]
#[must_use]
pub fn scope(&self) -> &Scope {
self.scope
}
/// Mutable reference to the current [`Scope`].
#[inline(always)]
#[must_use]
pub fn scope_mut(&mut self) -> &mut &'x mut Scope<'px> {
&mut self.scope
}
/// Get an iterator over the current set of modules imported via `import` statements.
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
self.mods.iter()
}
@ -743,11 +774,13 @@ impl<'x, 'px> EvalContext<'_, 'x, 'px, '_, '_, '_, '_> {
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn imports(&self) -> &Imports {
self.mods
}
/// Get an iterator over the namespaces containing definition of all script-defined functions.
#[inline(always)]
#[must_use]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned()
}
@ -755,16 +788,19 @@ impl<'x, 'px> EvalContext<'_, 'x, 'px, '_, '_, '_, '_> {
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn namespaces(&self) -> &[&Module] {
self.lib
}
/// The current bound `this` pointer, if any.
#[inline(always)]
#[must_use]
pub fn this_ptr(&self) -> Option<&Dynamic> {
self.this_ptr.as_ref().map(|v| &**v)
}
/// The current nesting level of function calls.
#[inline(always)]
#[must_use]
pub fn call_level(&self) -> usize {
self.level
}
@ -853,6 +889,7 @@ impl Default for Engine {
/// Make getter function
#[cfg(not(feature = "no_object"))]
#[inline(always)]
#[must_use]
pub fn make_getter(id: &str) -> String {
format!("{}{}", FN_GET, id)
}
@ -860,6 +897,7 @@ pub fn make_getter(id: &str) -> String {
/// Make setter function
#[cfg(not(feature = "no_object"))]
#[inline(always)]
#[must_use]
pub fn make_setter(id: &str) -> String {
format!("{}{}", FN_SET, id)
}
@ -867,6 +905,7 @@ pub fn make_setter(id: &str) -> String {
/// Is this function an anonymous function?
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn is_anonymous_fn(fn_name: &str) -> bool {
fn_name.starts_with(FN_ANONYMOUS)
}
@ -896,6 +935,7 @@ fn default_debug(_s: &str, _source: Option<&str>, _pos: Position) {
impl Engine {
/// Create a new [`Engine`]
#[inline]
#[must_use]
pub fn new() -> Self {
// Create the new scripting Engine
let mut engine = Self {
@ -959,6 +999,7 @@ impl Engine {
///
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
#[inline(always)]
#[must_use]
pub fn new_raw() -> Self {
let mut engine = Self {
global_namespace: Default::default(),
@ -1009,6 +1050,7 @@ impl Engine {
/// Search for a module within an imports stack.
#[inline]
#[must_use]
pub(crate) fn search_imports(
&self,
mods: &Imports,
@ -1042,6 +1084,7 @@ impl Engine {
/// Search for a variable within the scope or within imports,
/// depending on whether the variable name is namespace-qualified.
#[must_use]
pub(crate) fn search_namespace<'s>(
&self,
scope: &'s mut Scope,
@ -1091,6 +1134,7 @@ impl Engine {
/// # Panics
///
/// Panics if `expr` is not [`Expr::Variable`].
#[must_use]
pub(crate) fn search_scope_only<'s>(
&self,
scope: &'s mut Scope,
@ -1162,6 +1206,7 @@ impl Engine {
/// Chain-evaluate a dot/index chain.
/// [`Position`] in [`EvalAltResult`] is [`NONE`][Position::NONE] and must be set afterwards.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use]
fn eval_dot_index_chain_helper(
&self,
mods: &mut Imports,
@ -1586,6 +1631,8 @@ impl Engine {
/// Evaluate a dot/index chain.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use]
#[must_use]
fn eval_dot_index_chain(
&self,
scope: &mut Scope,
@ -1649,6 +1696,7 @@ impl Engine {
/// [`StaticVec`] is used to avoid an allocation in the overwhelming cases of
/// just a few levels of indexing.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use]
fn eval_indexed_chain(
&self,
scope: &mut Scope,
@ -1774,6 +1822,7 @@ impl Engine {
/// Get the value at the indexed position of a base type.
/// [`Position`] in [`EvalAltResult`] may be [`NONE`][Position::NONE] and should be set afterwards.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use]
fn get_indexed_mut<'t>(
&self,
mods: &mut Imports,
@ -1795,7 +1844,7 @@ impl Engine {
// val_array[idx]
let index = idx
.as_int()
.map_err(|err| self.make_type_mismatch_err::<crate::INT>(err, idx_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
let arr_len = arr.len();
@ -1854,7 +1903,7 @@ impl Engine {
// val_int[idx]
let index = idx
.as_int()
.map_err(|err| self.make_type_mismatch_err::<crate::INT>(err, idx_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
let bits = std::mem::size_of_val(value) * 8;
@ -1891,7 +1940,7 @@ impl Engine {
// val_string[idx]
let index = idx
.as_int()
.map_err(|err| self.make_type_mismatch_err::<crate::INT>(err, idx_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
let (ch, offset) = if index >= 0 {
let offset = index as usize;
@ -1939,6 +1988,7 @@ impl Engine {
}
/// Evaluate an expression.
#[must_use]
pub(crate) fn eval_expr(
&self,
scope: &mut Scope,
@ -2086,12 +2136,12 @@ impl Engine {
Ok((self
.eval_expr(scope, mods, state, lib, this_ptr, &x.lhs, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, x.lhs.position()))?
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.lhs.position()))?
&& // Short-circuit using &&
self
.eval_expr(scope, mods, state, lib, this_ptr, &x.rhs, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, x.rhs.position()))?)
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.rhs.position()))?)
.into())
}
@ -2099,12 +2149,12 @@ impl Engine {
Ok((self
.eval_expr(scope, mods, state, lib, this_ptr, &x.lhs, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, x.lhs.position()))?
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.lhs.position()))?
|| // Short-circuit using ||
self
.eval_expr(scope, mods, state, lib, this_ptr, &x.rhs, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, x.rhs.position()))?)
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.rhs.position()))?)
.into())
}
@ -2139,6 +2189,7 @@ impl Engine {
}
/// Evaluate a statements block.
#[must_use]
pub(crate) fn eval_stmt_block(
&self,
scope: &mut Scope,
@ -2216,6 +2267,7 @@ impl Engine {
/// Evaluate an op-assignment statement.
/// [`Position`] in [`EvalAltResult`] is [`NONE`][Position::NONE] and should be set afterwards.
#[must_use]
pub(crate) fn eval_op_assignment(
&self,
mods: &mut Imports,
@ -2289,6 +2341,7 @@ impl Engine {
///
/// This method uses some unsafe code, mainly for avoiding cloning of local variable names via
/// direct lifetime casting.
#[must_use]
pub(crate) fn eval_stmt(
&self,
scope: &mut Scope,
@ -2397,7 +2450,7 @@ impl Engine {
let guard_val = self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?;
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?;
if guard_val {
if !x.0.is_empty() {
@ -2430,9 +2483,9 @@ impl Engine {
match self
.eval_expr(scope, mods, state, lib, this_ptr, &condition, level)
.and_then(|v| {
v.as_bool().map_err(|err| {
v.as_bool().map_err(|typ| {
self.make_type_mismatch_err::<bool>(
err,
typ,
condition.position(),
)
})
@ -2474,7 +2527,7 @@ impl Engine {
let condition = if !expr.is_unit() {
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?
} else {
true
};
@ -2512,7 +2565,7 @@ impl Engine {
let condition = self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.as_bool()
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?;
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?;
if condition ^ *is_while {
return Ok(Dynamic::UNIT);
@ -2932,6 +2985,7 @@ impl Engine {
/// Check a result to ensure that the data size is within allowable limit.
#[cfg(feature = "unchecked")]
#[inline(always)]
#[must_use]
fn check_return_value(&self, result: RhaiResult) -> RhaiResult {
result
}
@ -2939,17 +2993,20 @@ impl Engine {
/// Check a result to ensure that the data size is within allowable limit.
#[cfg(not(feature = "unchecked"))]
#[inline(always)]
#[must_use]
fn check_return_value(&self, result: RhaiResult) -> RhaiResult {
result.and_then(|r| self.check_data_size(&r).map(|_| r))
}
#[cfg(feature = "unchecked")]
#[inline(always)]
#[must_use]
fn check_data_size(&self, _value: &Dynamic) -> Result<(), Box<EvalAltResult>> {
Ok(())
}
#[cfg(not(feature = "unchecked"))]
#[must_use]
fn check_data_size(&self, value: &Dynamic) -> Result<(), Box<EvalAltResult>> {
// Recursively calculate the size of a value (especially `Array` and `Map`)
fn calc_size(value: &Dynamic) -> (usize, usize, usize) {
@ -3052,6 +3109,7 @@ impl Engine {
/// Check if the number of operations stay within limit.
#[cfg(not(feature = "unchecked"))]
#[must_use]
pub(crate) fn inc_operations(
&self,
state: &mut State,
@ -3080,6 +3138,7 @@ impl Engine {
/// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name],
/// the type name provided for the registration will be used.
#[inline(always)]
#[must_use]
pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str {
self.type_names
.get(name)
@ -3089,6 +3148,7 @@ impl Engine {
/// Make a `Box<`[`EvalAltResult<ErrorMismatchDataType>`][EvalAltResult::ErrorMismatchDataType]`>`.
#[inline(always)]
#[must_use]
pub(crate) fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> Box<EvalAltResult> {
EvalAltResult::ErrorMismatchDataType(
self.map_type_name(type_name::<T>()).into(),

View File

@ -1031,6 +1031,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn compile(&self, script: &str) -> Result<AST, ParseError> {
self.compile_with_scope(&Default::default(), script)
}
@ -1073,6 +1074,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn compile_with_scope(&self, scope: &Scope, script: &str) -> Result<AST, ParseError> {
self.compile_scripts_with_scope(scope, &[script])
}
@ -1086,6 +1088,7 @@ impl Engine {
/// [`AST`]. When it is evaluated later, `import` statement directly recall pre-resolved
/// [modules][Module] and the resolution process is not performed again.
#[cfg(not(feature = "no_module"))]
#[must_use]
pub fn compile_into_self_contained(
&self,
scope: &Scope,
@ -1197,6 +1200,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn compile_scripts_with_scope(
&self,
scope: &Scope,
@ -1206,6 +1210,7 @@ impl Engine {
}
/// Join a list of strings and compile into an [`AST`] using own scope at a specific optimization level.
#[inline(always)]
#[must_use]
pub(crate) fn compile_with_scope_and_optimization_level(
&self,
scope: &Scope,
@ -1224,6 +1229,7 @@ impl Engine {
/// Read the contents of a file into a string.
#[cfg(not(feature = "no_std"))]
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
#[must_use]
fn read_file(path: std::path::PathBuf) -> Result<String, Box<EvalAltResult>> {
use std::io::Read;
@ -1279,6 +1285,7 @@ impl Engine {
#[cfg(not(feature = "no_std"))]
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
#[inline(always)]
#[must_use]
pub fn compile_file(&self, path: std::path::PathBuf) -> Result<AST, Box<EvalAltResult>> {
self.compile_file_with_scope(&Default::default(), path)
}
@ -1318,6 +1325,7 @@ impl Engine {
#[cfg(not(feature = "no_std"))]
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
#[inline(always)]
#[must_use]
pub fn compile_file_with_scope(
&self,
scope: &Scope,
@ -1368,6 +1376,7 @@ impl Engine {
/// # }
/// ```
#[cfg(not(feature = "no_object"))]
#[must_use]
pub fn parse_json(
&self,
json: impl AsRef<str>,
@ -1443,6 +1452,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn compile_expression(&self, script: &str) -> Result<AST, ParseError> {
self.compile_expression_with_scope(&Default::default(), script)
}
@ -1486,6 +1496,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn compile_expression_with_scope(
&self,
scope: &Scope,
@ -1518,6 +1529,7 @@ impl Engine {
#[cfg(not(feature = "no_std"))]
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
#[inline(always)]
#[must_use]
pub fn eval_file<T: Variant + Clone>(
&self,
path: std::path::PathBuf,
@ -1548,6 +1560,7 @@ impl Engine {
#[cfg(not(feature = "no_std"))]
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
#[inline(always)]
#[must_use]
pub fn eval_file_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope,
@ -1570,6 +1583,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval<T: Variant + Clone>(&self, script: &str) -> Result<T, Box<EvalAltResult>> {
self.eval_with_scope(&mut Default::default(), script)
}
@ -1596,6 +1610,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope,
@ -1623,6 +1638,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval_expression<T: Variant + Clone>(
&self,
script: &str,
@ -1648,6 +1664,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval_expression_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope,
@ -1686,6 +1703,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval_ast<T: Variant + Clone>(&self, ast: &AST) -> Result<T, Box<EvalAltResult>> {
self.eval_ast_with_scope(&mut Default::default(), ast)
}
@ -1719,6 +1737,7 @@ impl Engine {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn eval_ast_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope,
@ -1741,6 +1760,7 @@ impl Engine {
}
/// Evaluate an [`AST`] with own scope.
#[inline(always)]
#[must_use]
pub(crate) fn eval_ast_with_scope_raw<'a>(
&self,
scope: &mut Scope,
@ -1889,6 +1909,7 @@ impl Engine {
/// ```
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn call_fn<T: Variant + Clone>(
&self,
scope: &mut Scope,
@ -1968,6 +1989,7 @@ impl Engine {
/// ```
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn call_fn_dynamic(
&self,
scope: &mut Scope,
@ -1991,6 +2013,7 @@ impl Engine {
/// clone them _before_ calling this function.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub(crate) fn call_fn_dynamic_raw(
&self,
scope: &mut Scope,
@ -2048,6 +2071,7 @@ impl Engine {
/// Then, the [`AST`] is cloned and the copy re-optimized before running.
#[cfg(not(feature = "no_optimize"))]
#[inline(always)]
#[must_use]
pub fn optimize_ast(
&self,
scope: &Scope,
@ -2076,6 +2100,7 @@ impl Engine {
/// 2) Functions in registered sub-modules
/// 3) Functions in packages (optional)
#[cfg(feature = "metadata")]
#[must_use]
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
let mut signatures: Vec<_> = Default::default();

View File

@ -28,6 +28,7 @@ impl Engine {
/// Not available under `no_optimize`.
#[cfg(not(feature = "no_optimize"))]
#[inline(always)]
#[must_use]
pub fn optimization_level(&self) -> crate::OptimizationLevel {
self.optimization_level
}
@ -48,6 +49,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn max_call_levels(&self) -> usize {
self.limits.max_call_stack_depth
}
@ -66,6 +68,7 @@ impl Engine {
/// Not available under `unchecked`.
#[cfg(not(feature = "unchecked"))]
#[inline(always)]
#[must_use]
pub fn max_operations(&self) -> u64 {
self.limits.max_operations.map_or(0, NonZeroU64::get)
}
@ -85,6 +88,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn max_modules(&self) -> usize {
self.limits.max_modules
}
@ -110,6 +114,7 @@ impl Engine {
/// Not available under `unchecked`.
#[cfg(not(feature = "unchecked"))]
#[inline(always)]
#[must_use]
pub fn max_expr_depth(&self) -> usize {
self.limits.max_expr_depth.map_or(0, NonZeroUsize::get)
}
@ -119,6 +124,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn max_function_expr_depth(&self) -> usize {
self.limits
.max_function_expr_depth
@ -138,6 +144,7 @@ impl Engine {
/// Not available under `unchecked`.
#[cfg(not(feature = "unchecked"))]
#[inline(always)]
#[must_use]
pub fn max_string_size(&self) -> usize {
self.limits.max_string_size.map_or(0, NonZeroUsize::get)
}
@ -157,6 +164,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_index"))]
#[inline(always)]
#[must_use]
pub fn max_array_size(&self) -> usize {
self.limits.max_array_size.map_or(0, NonZeroUsize::get)
}
@ -176,6 +184,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_object"))]
#[inline(always)]
#[must_use]
pub fn max_map_size(&self) -> usize {
self.limits.max_map_size.map_or(0, NonZeroUsize::get)
}
@ -260,6 +269,7 @@ impl Engine {
/// # Ok(())
/// # }
/// ```
#[must_use]
pub fn register_custom_operator(
&mut self,
keyword: impl AsRef<str> + Into<Identifier>,

View File

@ -17,6 +17,7 @@ const BUILTIN: &str = "never fails because this is built-in code and the type is
/// Is the type a numeric type?
#[inline(always)]
#[must_use]
fn is_numeric(type_id: TypeId) -> bool {
let result = type_id == TypeId::of::<u8>()
|| type_id == TypeId::of::<u16>()
@ -40,6 +41,7 @@ fn is_numeric(type_id: TypeId) -> bool {
}
/// Build in common binary operator implementations to avoid the cost of calling a registered function.
#[must_use]
pub fn get_builtin_binary_op_fn(
op: &str,
x: &Dynamic,
@ -425,6 +427,7 @@ pub fn get_builtin_binary_op_fn(
}
/// Build in common operator assignment implementations to avoid the cost of calling a registered function.
#[must_use]
pub fn get_builtin_op_assignment_fn(
op: &str,
x: &Dynamic,

View File

@ -98,6 +98,7 @@ impl Drop for ArgBackup<'_> {
#[cfg(not(feature = "no_closure"))]
#[inline(always)]
#[must_use]
pub fn ensure_no_data_race(
fn_name: &str,
args: &FnCallArgs,
@ -123,6 +124,7 @@ pub fn ensure_no_data_race(
impl Engine {
/// Generate the signature for a function call.
#[inline]
#[must_use]
fn gen_call_signature(
&self,
namespace: Option<&NamespaceRef>,
@ -153,7 +155,8 @@ impl Engine {
/// 4) Imported modules - functions marked with global namespace
/// 5) Global sub-modules - functions marked with global namespace
#[inline(always)]
fn resolve_function<'s>(
#[must_use]
fn resolve_fn<'s>(
&self,
mods: &Imports,
state: &'s mut State,
@ -286,16 +289,17 @@ impl Engine {
/// Function call arguments be _consumed_ when the function requires them to be passed by value.
/// All function arguments not in the first position are always passed by value and thus consumed.
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
#[must_use]
pub(crate) fn call_native_fn(
&self,
mods: &Imports,
state: &mut State,
lib: &[&Module],
fn_name: &str,
hash_native: u64,
name: &str,
hash: u64,
args: &mut FnCallArgs,
is_ref: bool,
is_op_assignment: bool,
is_op_assign: bool,
pos: Position,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
#[cfg(not(feature = "unchecked"))]
@ -304,16 +308,7 @@ impl Engine {
let state_source = state.source.clone();
// Check if function access already in the cache
let func = self.resolve_function(
mods,
state,
lib,
fn_name,
hash_native,
Some(args),
true,
is_op_assignment,
);
let func = self.resolve_fn(mods, state, lib, name, hash, Some(args), true, is_op_assign);
if let Some(f) = func {
let FnResolutionCacheEntry { func, source } = f.as_ref();
@ -334,9 +329,9 @@ impl Engine {
let result = if func.is_plugin_fn() {
func.get_plugin_fn()
.call((self, fn_name, source, mods, lib).into(), args)
.call((self, name, source, mods, lib).into(), args)
} else {
func.get_native_fn()((self, fn_name, source, mods, lib).into(), args)
func.get_native_fn()((self, name, source, mods, lib).into(), args)
};
// Restore the original reference
@ -345,7 +340,7 @@ impl Engine {
let result = result.map_err(|err| err.fill_position(pos))?;
// See if the function match print/debug (which requires special processing)
return Ok(match fn_name {
return Ok(match name {
KEYWORD_PRINT => {
let text = result.as_immutable_string().map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType(
@ -371,7 +366,7 @@ impl Engine {
});
}
match fn_name {
match name {
// index getter function not found?
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
crate::engine::FN_IDX_GET => {
@ -398,13 +393,13 @@ impl Engine {
// Getter function not found?
#[cfg(not(feature = "no_object"))]
_ if fn_name.starts_with(crate::engine::FN_GET) => {
_ if name.starts_with(crate::engine::FN_GET) => {
assert!(args.len() == 1);
EvalAltResult::ErrorDotExpr(
format!(
"Unknown property '{}' - a getter is not registered for type '{}'",
&fn_name[crate::engine::FN_GET.len()..],
&name[crate::engine::FN_GET.len()..],
self.map_type_name(args[0].type_name())
),
pos,
@ -414,13 +409,13 @@ impl Engine {
// Setter function not found?
#[cfg(not(feature = "no_object"))]
_ if fn_name.starts_with(crate::engine::FN_SET) => {
_ if name.starts_with(crate::engine::FN_SET) => {
assert!(args.len() == 2);
EvalAltResult::ErrorDotExpr(
format!(
"No writable property '{}' - a setter is not registered for type '{}' to handle '{}'",
&fn_name[crate::engine::FN_SET.len()..],
&name[crate::engine::FN_SET.len()..],
self.map_type_name(args[0].type_name()),
self.map_type_name(args[1].type_name()),
),
@ -431,7 +426,7 @@ impl Engine {
// Raise error
_ => EvalAltResult::ErrorFunctionNotFound(
self.gen_call_signature(None, fn_name, args.as_ref()),
self.gen_call_signature(None, name, args.as_ref()),
pos,
)
.into(),
@ -446,6 +441,7 @@ impl Engine {
/// All function arguments not in the first position are always passed by value and thus consumed.
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
#[cfg(not(feature = "no_function"))]
#[must_use]
pub(crate) fn call_script_fn(
&self,
scope: &mut Scope,
@ -576,6 +572,7 @@ impl Engine {
// Does a scripted function exist?
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub(crate) fn has_script_fn(
&self,
mods: Option<&Imports>,
@ -614,6 +611,7 @@ impl Engine {
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
/// All function arguments not in the first position are always passed by value and thus consumed.
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
#[must_use]
pub(crate) fn exec_fn_call(
&self,
mods: &mut Imports,
@ -695,7 +693,7 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
if let Some(f) = hash_script.and_then(|hash| {
self.resolve_function(mods, state, lib, fn_name, hash, None, false, false)
self.resolve_fn(mods, state, lib, fn_name, hash, None, false, false)
.clone()
}) {
let FnResolutionCacheEntry { func, source } = *f;
@ -788,6 +786,7 @@ impl Engine {
/// Evaluate a list of statements with no `this` pointer.
/// This is commonly used to evaluate a list of statements in an [`AST`] or a script function body.
#[inline(always)]
#[must_use]
pub(crate) fn eval_global_statements(
&self,
scope: &mut Scope,
@ -808,6 +807,7 @@ impl Engine {
}
/// Evaluate a text script in place - used primarily for 'eval'.
#[must_use]
fn eval_script_expr_in_place(
&self,
scope: &mut Scope,
@ -859,6 +859,7 @@ impl Engine {
/// Call a dot method.
#[cfg(not(feature = "no_object"))]
#[must_use]
pub(crate) fn make_method_call(
&self,
mods: &mut Imports,
@ -900,7 +901,7 @@ impl Engine {
if call_args.len() > 0 {
if !call_args[0].is::<FnPtr>() {
return Err(self.make_type_mismatch_err::<FnPtr>(
self.map_type_name(target.type_name()),
self.map_type_name(call_args[0].type_name()),
*call_arg_pos,
));
}
@ -1020,6 +1021,7 @@ impl Engine {
/// Evaluate an argument.
#[inline(always)]
#[must_use]
pub(crate) fn get_arg_value(
&self,
scope: &mut Scope,
@ -1041,6 +1043,7 @@ impl Engine {
}
/// Call a function in normal function-call style.
#[must_use]
pub(crate) fn make_function_call(
&self,
scope: &mut Scope,
@ -1155,7 +1158,7 @@ impl Engine {
let fn_name = arg
.as_immutable_string()
.map_err(|err| self.make_type_mismatch_err::<ImmutableString>(err, arg_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<ImmutableString>(typ, arg_pos))?;
let (arg, arg_pos) = self.get_arg_value(
scope, mods, state, lib, this_ptr, level, args_expr, constants, 1,
@ -1163,7 +1166,7 @@ impl Engine {
let num_params = arg
.as_int()
.map_err(|err| self.make_type_mismatch_err::<crate::INT>(err, arg_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, arg_pos))?;
return Ok(if num_params < 0 {
Dynamic::FALSE
@ -1181,7 +1184,7 @@ impl Engine {
)?;
let var_name = arg
.as_immutable_string()
.map_err(|err| self.make_type_mismatch_err::<ImmutableString>(err, arg_pos))?;
.map_err(|typ| self.make_type_mismatch_err::<ImmutableString>(typ, arg_pos))?;
return Ok(scope.contains(&var_name).into());
}
@ -1291,6 +1294,7 @@ impl Engine {
}
/// Call a namespace-qualified function in normal function-call style.
#[must_use]
pub(crate) fn make_qualified_function_call(
&self,
scope: &mut Scope,

View File

@ -92,6 +92,7 @@ impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M)>
impl<'a> NativeCallContext<'a> {
/// Create a new [`NativeCallContext`].
#[inline(always)]
#[must_use]
pub fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self {
Self {
engine,
@ -108,6 +109,7 @@ impl<'a> NativeCallContext<'a> {
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn new_with_all_fields(
engine: &'a Engine,
fn_name: &'a str,
@ -125,16 +127,19 @@ impl<'a> NativeCallContext<'a> {
}
/// The current [`Engine`].
#[inline(always)]
#[must_use]
pub fn engine(&self) -> &Engine {
self.engine
}
/// Name of the function called.
#[inline(always)]
#[must_use]
pub fn fn_name(&self) -> &str {
self.fn_name
}
/// The current source.
#[inline(always)]
#[must_use]
pub fn source(&self) -> Option<&str> {
self.source
}
@ -143,6 +148,7 @@ impl<'a> NativeCallContext<'a> {
/// Not available under `no_module`.
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
self.mods.iter().flat_map(|&m| m.iter())
}
@ -150,6 +156,7 @@ impl<'a> NativeCallContext<'a> {
#[cfg(not(feature = "no_module"))]
#[allow(dead_code)]
#[inline(always)]
#[must_use]
pub(crate) fn iter_imports_raw(
&self,
) -> impl Iterator<Item = (&crate::Identifier, &Shared<Module>)> {
@ -162,11 +169,13 @@ impl<'a> NativeCallContext<'a> {
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn imports(&self) -> Option<&Imports> {
self.mods
}
/// Get an iterator over the namespaces containing definitions of all script-defined functions.
#[inline(always)]
#[must_use]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned()
}
@ -174,6 +183,7 @@ impl<'a> NativeCallContext<'a> {
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn namespaces(&self) -> &[&Module] {
self.lib
}
@ -190,6 +200,7 @@ impl<'a> NativeCallContext<'a> {
/// If `is_method` is [`true`], the first argument is assumed to be passed
/// by reference and is not consumed.
#[inline(always)]
#[must_use]
pub fn call_fn_dynamic_raw(
&self,
fn_name: impl AsRef<str>,
@ -228,18 +239,21 @@ impl<'a> NativeCallContext<'a> {
/// Consume a [`Shared`] resource and return a mutable reference to the wrapped value.
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
#[inline(always)]
#[must_use]
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
Shared::make_mut(value)
}
/// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise.
#[inline(always)]
#[must_use]
pub fn shared_take_or_clone<T: Clone>(value: Shared<T>) -> T {
shared_try_take(value).unwrap_or_else(|v| v.as_ref().clone())
}
/// Consume a [`Shared`] resource if is unique (i.e. not shared).
#[inline(always)]
#[must_use]
pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
Shared::try_unwrap(value)
}
@ -250,6 +264,7 @@ pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
///
/// Panics if the resource is shared (i.e. has other outstanding references).
#[inline(always)]
#[must_use]
pub fn shared_take<T>(value: Shared<T>) -> T {
shared_try_take(value)
.ok()
@ -267,31 +282,37 @@ pub struct FnPtr(Identifier, StaticVec<Dynamic>);
impl FnPtr {
/// Create a new function pointer.
#[inline(always)]
#[must_use]
pub fn new(name: impl Into<Identifier>) -> Result<Self, Box<EvalAltResult>> {
name.into().try_into()
}
/// Create a new function pointer without checking its parameters.
#[inline(always)]
#[must_use]
pub(crate) fn new_unchecked(name: Identifier, curry: StaticVec<Dynamic>) -> Self {
Self(name.into(), curry)
}
/// Get the name of the function.
#[inline(always)]
#[must_use]
pub fn fn_name(&self) -> &str {
self.get_fn_name().as_ref()
}
/// Get the name of the function.
#[inline(always)]
#[must_use]
pub(crate) fn get_fn_name(&self) -> &Identifier {
&self.0
}
/// Get the underlying data of the function pointer.
#[inline(always)]
#[must_use]
pub(crate) fn take_data(self) -> (Identifier, StaticVec<Dynamic>) {
(self.0, self.1)
}
/// Get the curried arguments.
#[inline(always)]
#[must_use]
pub fn curry(&self) -> &[Dynamic] {
self.1.as_ref()
}
@ -309,11 +330,13 @@ impl FnPtr {
}
/// Is the function pointer curried?
#[inline(always)]
#[must_use]
pub fn is_curried(&self) -> bool {
!self.1.is_empty()
}
/// Get the number of curried arguments.
#[inline(always)]
#[must_use]
pub fn num_curried(&self) -> usize {
self.1.len()
}
@ -322,6 +345,7 @@ impl FnPtr {
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn is_anonymous(&self) -> bool {
self.0.starts_with(crate::engine::FN_ANONYMOUS)
}
@ -336,6 +360,7 @@ impl FnPtr {
/// Do not use the arguments after this call. If they are needed afterwards,
/// clone them _before_ calling this function.
#[inline(always)]
#[must_use]
pub fn call_dynamic(
&self,
ctx: &NativeCallContext,
@ -518,6 +543,7 @@ impl fmt::Display for CallableFunction {
impl CallableFunction {
/// Is this a pure native Rust function?
#[inline(always)]
#[must_use]
pub fn is_pure(&self) -> bool {
match self {
Self::Pure(_) => true,
@ -531,6 +557,7 @@ impl CallableFunction {
}
/// Is this a native Rust method function?
#[inline(always)]
#[must_use]
pub fn is_method(&self) -> bool {
match self {
Self::Method(_) => true,
@ -544,6 +571,7 @@ impl CallableFunction {
}
/// Is this an iterator function?
#[inline(always)]
#[must_use]
pub fn is_iter(&self) -> bool {
match self {
Self::Iterator(_) => true,
@ -555,6 +583,7 @@ impl CallableFunction {
}
/// Is this a Rhai-scripted function?
#[inline(always)]
#[must_use]
pub fn is_script(&self) -> bool {
match self {
#[cfg(not(feature = "no_function"))]
@ -565,6 +594,7 @@ impl CallableFunction {
}
/// Is this a plugin function?
#[inline(always)]
#[must_use]
pub fn is_plugin_fn(&self) -> bool {
match self {
Self::Plugin(_) => true,
@ -576,6 +606,7 @@ impl CallableFunction {
}
/// Is this a native Rust function?
#[inline(always)]
#[must_use]
pub fn is_native(&self) -> bool {
match self {
Self::Pure(_) | Self::Method(_) => true,
@ -588,6 +619,7 @@ impl CallableFunction {
}
/// Get the access mode.
#[inline(always)]
#[must_use]
pub fn access(&self) -> FnAccess {
match self {
Self::Plugin(_) => FnAccess::Public,
@ -604,6 +636,7 @@ impl CallableFunction {
/// Panics if the [`CallableFunction`] is not [`Pure`][CallableFunction::Pure] or
/// [`Method`][CallableFunction::Method].
#[inline(always)]
#[must_use]
pub fn get_native_fn(&self) -> &Shared<FnAny> {
match self {
Self::Pure(f) | Self::Method(f) => f,
@ -622,6 +655,7 @@ impl CallableFunction {
/// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script].
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn get_fn_def(&self) -> &Shared<crate::ast::ScriptFnDef> {
match self {
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => {
@ -636,6 +670,7 @@ impl CallableFunction {
///
/// Panics if the [`CallableFunction`] is not [`Iterator`][CallableFunction::Iterator].
#[inline(always)]
#[must_use]
pub fn get_iter_fn(&self) -> IteratorFn {
match self {
Self::Iterator(f) => *f,
@ -653,6 +688,7 @@ impl CallableFunction {
///
/// Panics if the [`CallableFunction`] is not [`Plugin`][CallableFunction::Plugin].
#[inline(always)]
#[must_use]
pub fn get_plugin_fn<'s>(&'s self) -> &Shared<FnPlugin> {
match self {
Self::Plugin(f) => f,
@ -666,16 +702,19 @@ impl CallableFunction {
}
/// Create a new [`CallableFunction::Pure`].
#[inline(always)]
#[must_use]
pub fn from_pure(func: Box<FnAny>) -> Self {
Self::Pure(func.into())
}
/// Create a new [`CallableFunction::Method`].
#[inline(always)]
#[must_use]
pub fn from_method(func: Box<FnAny>) -> Self {
Self::Method(func.into())
}
/// Create a new [`CallableFunction::Plugin`].
#[inline(always)]
#[must_use]
pub fn from_plugin(func: impl PluginFunction + 'static + SendSync) -> Self {
Self::Plugin((Box::new(func) as Box<FnPlugin>).into())
}

View File

@ -30,6 +30,7 @@ pub struct Mut<T>(T);
/// Dereference into DynamicWriteLock
#[inline(always)]
#[must_use]
pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<T> {
// Directly cast the &mut Dynamic into DynamicWriteLock to access the underlying data.
data.write_lock::<T>()
@ -38,6 +39,7 @@ pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<T> {
/// Dereference into value.
#[inline(always)]
#[must_use]
pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
if TypeId::of::<T>() == TypeId::of::<&str>() {
// If T is `&str`, data must be `ImmutableString`, so map directly to it
@ -63,24 +65,30 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
/// Trait to register custom Rust functions.
pub trait RegisterNativeFunction<Args, Result> {
/// Convert this function into a [`CallableFunction`].
#[must_use]
fn into_callable_function(self) -> CallableFunction;
/// Get the type ID's of this function's parameters.
#[must_use]
fn param_types() -> Box<[TypeId]>;
/// _(METADATA)_ Get the type names of this function's parameters.
/// Exported under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[must_use]
fn param_names() -> Box<[&'static str]>;
/// _(METADATA)_ Get the type ID of this function's return value.
/// Exported under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[must_use]
fn return_type() -> TypeId;
/// _(METADATA)_ Get the type name of this function's return value.
/// Exported under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[must_use]
fn return_type_name() -> &'static str;
}
#[inline(always)]
#[must_use]
fn is_setter(_fn_name: &str) -> bool {
#[cfg(not(feature = "no_object"))]
if _fn_name.starts_with(crate::engine::FN_SET) {

View File

@ -67,6 +67,7 @@ impl FuncInfo {
/// Generate a signature of the function.
/// Exported under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[must_use]
pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.name);
@ -240,6 +241,7 @@ impl Module {
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Self {
id: None,
@ -269,6 +271,7 @@ impl Module {
/// assert_eq!(module.id(), Some("hello"));
/// ```
#[inline(always)]
#[must_use]
pub fn id(&self) -> Option<&str> {
self.id_raw().map(|s| s.as_str())
}
@ -285,6 +288,7 @@ impl Module {
/// assert_eq!(module.id_raw().map(|s| s.as_str()), Some("hello"));
/// ```
#[inline(always)]
#[must_use]
pub fn id_raw(&self) -> Option<&Identifier> {
self.id.as_ref()
}
@ -317,6 +321,7 @@ impl Module {
/// assert!(module.is_empty());
/// ```
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.functions.is_empty()
&& self.all_functions.is_empty()
@ -349,6 +354,7 @@ impl Module {
/// # }
/// ```
#[inline(always)]
#[must_use]
pub fn is_indexed(&self) -> bool {
self.indexed
}
@ -357,6 +363,7 @@ impl Module {
/// Exported under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[inline(always)]
#[must_use]
pub fn gen_fn_signatures(&self) -> impl Iterator<Item = String> + '_ {
self.functions
.values()
@ -379,6 +386,7 @@ impl Module {
/// assert!(module.contains_var("answer"));
/// ```
#[inline(always)]
#[must_use]
pub fn contains_var(&self, name: &str) -> bool {
self.variables.contains_key(name)
}
@ -395,6 +403,7 @@ impl Module {
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn get_var_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
self.get_var(name).and_then(Dynamic::try_cast::<T>)
}
@ -411,6 +420,7 @@ impl Module {
/// assert_eq!(module.get_var("answer").unwrap().cast::<i64>(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn get_var(&self, name: &str) -> Option<Dynamic> {
self.variables.get(name).cloned()
}
@ -448,6 +458,7 @@ impl Module {
/// Get a reference to a namespace-qualified variable.
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
#[inline(always)]
#[must_use]
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Result<&Dynamic, Box<EvalAltResult>> {
self.all_variables.get(&hash_var).ok_or_else(|| {
EvalAltResult::ErrorVariableNotFound(String::new(), Position::NONE).into()
@ -489,6 +500,7 @@ impl Module {
/// and number of parameters.
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn get_script_fn(
&self,
name: &str,
@ -508,6 +520,7 @@ impl Module {
/// Thus the [`Module`] is automatically set to be non-indexed.
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub(crate) fn sub_modules_mut(&mut self) -> &mut BTreeMap<Identifier, Shared<Module>> {
// We must assume that the user has changed the sub-modules
// (otherwise why take a mutable reference?)
@ -533,6 +546,7 @@ impl Module {
/// assert!(module.contains_sub_module("question"));
/// ```
#[inline(always)]
#[must_use]
pub fn contains_sub_module(&self, name: &str) -> bool {
self.modules.contains_key(name)
}
@ -550,6 +564,7 @@ impl Module {
/// assert!(module.get_sub_module("question").is_some());
/// ```
#[inline(always)]
#[must_use]
pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
self.modules.get(name).map(|m| m.as_ref())
}
@ -594,6 +609,7 @@ impl Module {
/// assert!(module.contains_fn(hash));
/// ```
#[inline(always)]
#[must_use]
pub fn contains_fn(&self, hash_fn: u64) -> bool {
self.functions.contains_key(&hash_fn)
}
@ -641,6 +657,7 @@ impl Module {
/// Remap type ID.
#[inline(always)]
#[must_use]
fn map_type(map: bool, type_id: TypeId) -> TypeId {
if !map {
return type_id;
@ -1104,6 +1121,7 @@ impl Module {
///
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
#[inline(always)]
#[must_use]
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
}
@ -1112,6 +1130,7 @@ impl Module {
///
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
#[inline(always)]
#[must_use]
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
self.all_functions.contains_key(&hash_fn)
}
@ -1120,6 +1139,7 @@ impl Module {
///
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
#[inline(always)]
#[must_use]
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
self.all_functions
.get(&hash_qualified_fn)
@ -1266,6 +1286,7 @@ impl Module {
/// Get the number of variables, functions and type iterators in the [`Module`].
#[inline(always)]
#[must_use]
pub fn count(&self) -> (usize, usize, usize) {
(
self.variables.len(),
@ -1276,12 +1297,14 @@ impl Module {
/// Get an iterator to the sub-modules in the [`Module`].
#[inline(always)]
#[must_use]
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
self.modules.iter().map(|(k, m)| (k.as_str(), m.clone()))
}
/// Get an iterator to the variables in the [`Module`].
#[inline(always)]
#[must_use]
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
self.variables.iter().map(|(k, v)| (k.as_str(), v))
}
@ -1289,6 +1312,7 @@ impl Module {
/// Get an iterator to the functions in the [`Module`].
#[inline(always)]
#[allow(dead_code)]
#[must_use]
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
self.functions.values().map(Box::as_ref)
}
@ -1303,6 +1327,7 @@ impl Module {
/// 5) Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef].
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub(crate) fn iter_script_fn(
&self,
) -> impl Iterator<
@ -1338,6 +1363,7 @@ impl Module {
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "internals"))]
#[inline(always)]
#[must_use]
pub fn iter_script_fn_info(
&self,
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize)> {
@ -1359,6 +1385,7 @@ impl Module {
#[cfg(not(feature = "no_function"))]
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn iter_script_fn_info(
&self,
) -> impl Iterator<
@ -1395,6 +1422,7 @@ impl Module {
/// # }
/// ```
#[cfg(not(feature = "no_module"))]
#[must_use]
pub fn eval_ast_as_new(
mut scope: crate::Scope,
ast: &crate::AST,
@ -1463,6 +1491,7 @@ impl Module {
///
/// Panics if the [`Module`] is not yet indexed via [`build_index`][Module::build_index].
#[inline(always)]
#[must_use]
pub fn contains_indexed_global_functions(&self) -> bool {
self.contains_indexed_global_functions
}
@ -1562,12 +1591,14 @@ impl Module {
/// Does a type iterator exist in the entire module tree?
#[inline(always)]
#[must_use]
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
self.all_type_iterators.contains_key(&id)
}
/// Does a type iterator exist in the module?
#[inline(always)]
#[must_use]
pub fn contains_iter(&self, id: TypeId) -> bool {
self.type_iterators.contains_key(&id)
}
@ -1609,12 +1640,14 @@ impl Module {
/// Get the specified type iterator.
#[inline(always)]
#[must_use]
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.all_type_iterators.get(&id).cloned()
}
/// Get the specified type iterator.
#[inline(always)]
#[must_use]
pub(crate) fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.type_iterators.get(&id).cloned()
}
@ -1693,6 +1726,7 @@ impl From<StaticVec<Ident>> for NamespaceRef {
impl NamespaceRef {
/// Get the [`Scope`][crate::Scope] index offset.
#[inline(always)]
#[must_use]
pub(crate) fn index(&self) -> Option<NonZeroUsize> {
self.index
}

View File

@ -41,6 +41,7 @@ impl ModuleResolversCollection {
/// engine.set_module_resolver(collection);
/// ```
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Default::default()
}
@ -76,11 +77,13 @@ impl ModuleResolversCollection {
}
/// Get an iterator of all the [module resolvers][ModuleResolver].
#[inline(always)]
#[must_use]
pub fn iter(&self) -> impl Iterator<Item = &dyn ModuleResolver> {
self.0.iter().map(|v| v.as_ref())
}
/// Get a mutable iterator of all the [module resolvers][ModuleResolver].
#[inline(always)]
#[must_use]
pub fn into_iter(self) -> impl Iterator<Item = Box<dyn ModuleResolver>> {
self.0.into_iter()
}
@ -92,11 +95,13 @@ impl ModuleResolversCollection {
}
/// Is this [`ModuleResolversCollection`] empty?
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Get the number of [module resolvers][ModuleResolver] in this [`ModuleResolversCollection`].
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}

View File

@ -77,6 +77,7 @@ impl FileModuleResolver {
/// engine.set_module_resolver(resolver);
/// ```
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Self::new_with_extension(RHAI_SCRIPT_EXTENSION)
}
@ -99,6 +100,7 @@ impl FileModuleResolver {
/// engine.set_module_resolver(resolver);
/// ```
#[inline(always)]
#[must_use]
pub fn new_with_path(path: impl Into<PathBuf>) -> Self {
Self::new_with_path_and_extension(path, RHAI_SCRIPT_EXTENSION)
}
@ -118,6 +120,7 @@ impl FileModuleResolver {
/// engine.set_module_resolver(resolver);
/// ```
#[inline(always)]
#[must_use]
pub fn new_with_extension(extension: impl Into<Identifier>) -> Self {
Self {
base_path: None,
@ -143,6 +146,7 @@ impl FileModuleResolver {
/// engine.set_module_resolver(resolver);
/// ```
#[inline(always)]
#[must_use]
pub fn new_with_path_and_extension(
path: impl Into<PathBuf>,
extension: impl Into<Identifier>,
@ -157,6 +161,7 @@ impl FileModuleResolver {
/// Get the base path for script files.
#[inline(always)]
#[must_use]
pub fn base_path(&self) -> Option<&Path> {
self.base_path.as_ref().map(PathBuf::as_ref)
}
@ -169,6 +174,7 @@ impl FileModuleResolver {
/// Get the script file extension.
#[inline(always)]
#[must_use]
pub fn extension(&self) -> &str {
&self.extension
}
@ -188,12 +194,14 @@ impl FileModuleResolver {
}
/// Is the cache enabled?
#[inline(always)]
#[must_use]
pub fn is_cache_enabled(&self) -> bool {
self.cache_enabled
}
/// Is a particular path cached?
#[inline(always)]
#[must_use]
pub fn is_cached(&self, path: &str, source_path: Option<&str>) -> bool {
if !self.cache_enabled {
return false;
@ -208,16 +216,19 @@ impl FileModuleResolver {
}
/// Empty the internal cache.
#[inline(always)]
pub fn clear_cache(&mut self) {
pub fn clear_cache(&mut self) -> &mut Self {
#[cfg(not(feature = "sync"))]
self.cache.borrow_mut().clear();
#[cfg(feature = "sync")]
self.cache.write().unwrap().clear();
self
}
/// Remove the specified path from internal cache.
///
/// The next time this path is resolved, the script file will be loaded once again.
#[inline(always)]
#[must_use]
pub fn clear_cache_for_path(
&mut self,
path: &str,
@ -240,6 +251,8 @@ impl FileModuleResolver {
.map(|(_, v)| v);
}
/// Construct a full file path.
#[must_use]
#[must_use]
fn get_file_path(&self, path: &str, source_path: Option<&str>) -> PathBuf {
let path = Path::new(path);

View File

@ -23,6 +23,7 @@ pub use stat::StaticModuleResolver;
/// Trait that encapsulates a module resolution service.
pub trait ModuleResolver: SendSync {
/// Resolve a module based on a path string.
#[must_use]
fn resolve(
&self,
engine: &Engine,
@ -41,6 +42,7 @@ pub trait ModuleResolver: SendSync {
/// Override the default implementation of this method if the module resolver
/// serves modules based on compiled Rhai scripts.
#[allow(unused_variables)]
#[must_use]
fn resolve_ast(
&self,
engine: &Engine,

View File

@ -41,6 +41,7 @@ impl StaticModuleResolver {
/// engine.set_module_resolver(resolver);
/// ```
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Default::default()
}
@ -57,38 +58,45 @@ impl StaticModuleResolver {
}
/// Does the path exist?
#[inline(always)]
#[must_use]
pub fn contains_path(&self, path: &str) -> bool {
self.0.contains_key(path)
}
/// Get an iterator of all the [modules][Module].
#[inline(always)]
#[must_use]
pub fn iter(&self) -> impl Iterator<Item = (&str, &Shared<Module>)> {
self.0.iter().map(|(k, v)| (k.as_str(), v))
}
/// Get a mutable iterator of all the [modules][Module].
#[inline(always)]
#[must_use]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&str, &mut Shared<Module>)> {
self.0.iter_mut().map(|(k, v)| (k.as_str(), v))
}
/// Get a mutable iterator of all the modules.
#[inline(always)]
#[must_use]
pub fn into_iter(self) -> impl Iterator<Item = (Identifier, Shared<Module>)> {
self.0.into_iter()
}
/// Get an iterator of all the [module][Module] paths.
#[inline(always)]
#[must_use]
pub fn paths(&self) -> impl Iterator<Item = &str> {
self.0.keys().map(|s| s.as_str())
}
/// Get an iterator of all the [modules][Module].
#[inline(always)]
#[must_use]
pub fn values(&self) -> impl Iterator<Item = &Shared<Module>> {
self.0.values().map(|m| m)
}
/// Remove all [modules][Module].
#[inline(always)]
pub fn clear(&mut self) {
pub fn clear(&mut self) -> &mut Self {
self.0.clear();
self
}
/// Is this [`StaticModuleResolver`] empty?
#[inline(always)]
@ -97,6 +105,7 @@ impl StaticModuleResolver {
}
/// Get the number of [modules][Module] in this [`StaticModuleResolver`].
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
@ -105,10 +114,11 @@ impl StaticModuleResolver {
///
/// Existing modules of the same path name are overwritten.
#[inline(always)]
pub fn merge(&mut self, other: Self) {
pub fn merge(&mut self, other: Self) -> &mut Self {
if !other.is_empty() {
self.0.extend(other.0.into_iter());
}
self
}
}

View File

@ -38,11 +38,13 @@ pub trait Package {
fn init(lib: &mut Module);
/// Retrieve the generic package library from this package.
#[must_use]
fn as_shared_module(&self) -> Shared<Module>;
/// Retrieve the generic package library from this package.
/// This method is deprecated and will be removed in the future.
/// Use [`as_shared_module`][Package::as_shared_module] instead.
#[must_use]
#[deprecated(since = "0.19.9", note = "use `as_shared_module` instead")]
fn get(&self) -> Shared<Module> {
self.as_shared_module()

View File

@ -58,6 +58,7 @@ impl fmt::Display for LexError {
}
impl LexError {
#[must_use]
pub(crate) fn desc(&self) -> &str {
match self {
Self::UnexpectedInput(_) => "Unexpected character encountered",
@ -72,6 +73,7 @@ impl LexError {
}
/// Convert a [`LexError`] into a [`ParseError`].
#[inline(always)]
#[must_use]
pub fn into_err(self, pos: Position) -> ParseError {
ParseError(Box::new(self.into()), pos)
}
@ -188,10 +190,12 @@ pub enum ParseErrorType {
impl ParseErrorType {
/// Make a [`ParseError`] using the current type and position.
#[inline(always)]
#[must_use]
pub(crate) fn into_err(self, pos: Position) -> ParseError {
ParseError(Box::new(self), pos)
}
#[must_use]
pub(crate) fn desc(&self) -> &str {
match self {
Self::UnexpectedEOF => "Script is incomplete",

View File

@ -59,8 +59,8 @@ pub struct ParseState<'e> {
external_vars: BTreeMap<Identifier, Position>,
/// An indicator that disables variable capturing into externals one single time
/// up until the nearest consumed Identifier token.
/// If set to false the next call to `access_var` will not capture the variable.
/// All consequent calls to `access_var` will not be affected
/// If set to false the next call to [`access_var`][ParseState::access_var] will not capture the variable.
/// All consequent calls to [`access_var`][ParseState::access_var] will not be affected
#[cfg(not(feature = "no_closure"))]
allow_capture: bool,
/// Encapsulates a local stack with imported [module][crate::Module] names.
@ -78,6 +78,7 @@ pub struct ParseState<'e> {
impl<'e> ParseState<'e> {
/// Create a new [`ParseState`].
#[inline(always)]
#[must_use]
pub fn new(engine: &'e Engine, tokenizer_control: TokenizerControl) -> Self {
Self {
engine,
@ -103,8 +104,8 @@ impl<'e> ParseState<'e> {
///
/// If the variable is not present in the scope adds it to the list of external variables
///
/// The return value is the offset to be deducted from `Stack::len`,
/// i.e. the top element of the [`ParseState`] is offset 1.
/// The return value is the offset to be deducted from `ParseState::stack::len`,
/// i.e. the top element of [`ParseState`]'s variables stack is offset 1.
///
/// Return `None` when the variable name is not found in the `stack`.
#[inline(always)]
@ -155,6 +156,7 @@ impl<'e> ParseState<'e> {
/// Panics when called under `no_module`.
#[cfg(not(feature = "no_module"))]
#[inline(always)]
#[must_use]
pub fn find_module(&self, name: &str) -> Option<NonZeroUsize> {
self.modules
.iter()
@ -166,6 +168,7 @@ impl<'e> ParseState<'e> {
/// Get an interned string, creating one if it is not yet interned.
#[inline(always)]
#[must_use]
pub fn get_identifier(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
self.interned_strings.get(text)
}
@ -197,6 +200,7 @@ struct ParseSettings {
impl ParseSettings {
/// Create a new `ParseSettings` with one higher expression level.
#[inline(always)]
#[must_use]
pub fn level_up(&self) -> Self {
Self {
level: self.level + 1,
@ -206,6 +210,7 @@ impl ParseSettings {
/// Make sure that the current level of expression nesting is within the maximum limit.
#[cfg(not(feature = "unchecked"))]
#[inline(always)]
#[must_use]
pub fn ensure_level_within_max_limit(
&self,
limit: Option<NonZeroUsize>,
@ -222,6 +227,7 @@ impl Expr {
/// All other variants are untouched.
#[cfg(not(feature = "no_object"))]
#[inline(always)]
#[must_use]
fn into_property(self, state: &mut ParseState) -> Self {
match self {
Self::Variable(_, pos, x) if x.1.is_none() => {
@ -1441,6 +1447,7 @@ fn make_assignment_stmt<'a>(
rhs: Expr,
op_pos: Position,
) -> Result<Stmt, ParseError> {
#[must_use]
fn check_lvalue(expr: &Expr, parent_is_dot: bool) -> Option<Position> {
match expr {
Expr::Index(x, _) | Expr::Dot(x, _) if parent_is_dot => match x.lhs {
@ -3091,6 +3098,8 @@ fn parse_anon_fn(
}
impl Engine {
/// Parse a global level expression.
#[must_use]
pub(crate) fn parse_global_expr(
&self,
input: &mut TokenStream,
@ -3132,6 +3141,7 @@ impl Engine {
}
/// Parse the global level statements.
#[must_use]
fn parse_global_level(
&self,
input: &mut TokenStream,
@ -3193,6 +3203,7 @@ impl Engine {
/// Run the parser on an input stream, returning an AST.
#[inline(always)]
#[must_use]
pub(crate) fn parse(
&self,
input: &mut TokenStream,

View File

@ -21,8 +21,10 @@ pub use rhai_codegen::{export_fn, register_exported_fn};
/// Use the `#[export_module]` and `#[export_fn]` procedural attributes instead.
pub trait PluginFunction {
/// Call the plugin function with the arguments provided.
#[must_use]
fn call(&self, context: NativeCallContext, args: &mut FnCallArgs) -> RhaiResult;
/// Is this plugin function a method?
#[must_use]
fn is_method_call(&self) -> bool;
}

View File

@ -95,6 +95,7 @@ pub enum EvalAltResult {
}
impl EvalAltResult {
#[must_use]
pub(crate) fn desc(&self) -> &str {
match self {
#[allow(deprecated)]
@ -275,6 +276,7 @@ impl EvalAltResult {
/// Is this a pseudo error? A pseudo error is one that does not occur naturally.
///
/// [`LoopBreak`][EvalAltResult::LoopBreak] and [`Return`][EvalAltResult::Return] are pseudo errors.
#[must_use]
pub fn is_pseudo_error(&self) -> bool {
match self {
Self::LoopBreak(_, _) | Self::Return(_, _) => true,
@ -286,6 +288,7 @@ impl EvalAltResult {
/// # Panics
///
/// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return].
#[must_use]
pub fn is_catchable(&self) -> bool {
match self {
Self::ErrorSystem(_, _) => false,
@ -325,6 +328,7 @@ impl EvalAltResult {
/// # Panics
///
/// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return].
#[must_use]
pub fn is_system_exception(&self) -> bool {
match self {
Self::ErrorSystem(_, _) => true,
@ -412,6 +416,7 @@ impl EvalAltResult {
};
}
/// Get the [position][Position] of this error.
#[must_use]
pub fn position(&self) -> Position {
match self {
Self::ErrorSystem(_, _) => Position::NONE,
@ -444,6 +449,12 @@ impl EvalAltResult {
| Self::Return(_, pos) => *pos,
}
}
/// Remove the [position][Position] information from this error.
///
/// The [position][Position] of this error is set to [`NONE`][Position::NONE] afterwards.
pub fn clear_position(&mut self) -> &mut Self {
self.set_position(Position::NONE)
}
/// Remove the [position][Position] information from this error and return it.
///
/// The [position][Position] of this error is set to [`NONE`][Position::NONE] afterwards.
@ -453,7 +464,7 @@ impl EvalAltResult {
pos
}
/// Override the [position][Position] of this error.
pub fn set_position(&mut self, new_position: Position) {
pub fn set_position(&mut self, new_position: Position) -> &mut Self {
match self {
Self::ErrorSystem(_, _) => (),
@ -484,10 +495,12 @@ impl EvalAltResult {
| Self::LoopBreak(_, pos)
| Self::Return(_, pos) => *pos = new_position,
}
self
}
/// Consume the current [`EvalAltResult`] and return a new one with the specified [`Position`]
/// if the current position is [`Position::None`].
#[inline(always)]
#[must_use]
pub(crate) fn fill_position(mut self: Box<Self>, new_position: Position) -> Box<Self> {
if self.position().is_none() {
self.set_position(new_position);

View File

@ -95,6 +95,7 @@ impl<'a> Scope<'a> {
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Self {
values: Default::default(),
@ -121,6 +122,7 @@ impl<'a> Scope<'a> {
/// assert!(my_scope.is_empty());
/// ```
#[inline(always)]
#[must_use]
pub fn clear(&mut self) -> &mut Self {
self.names.clear();
self.values.clear();
@ -140,6 +142,7 @@ impl<'a> Scope<'a> {
/// assert_eq!(my_scope.len(), 1);
/// ```
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.values.len()
}
@ -157,6 +160,7 @@ impl<'a> Scope<'a> {
/// assert!(!my_scope.is_empty());
/// ```
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.values.len() == 0
}
@ -301,6 +305,7 @@ impl<'a> Scope<'a> {
/// assert!(!my_scope.contains("y"));
/// ```
#[inline(always)]
#[must_use]
pub fn contains(&self, name: &str) -> bool {
self.names
.iter()
@ -309,6 +314,7 @@ impl<'a> Scope<'a> {
}
/// Find an entry in the [`Scope`], starting from the last.
#[inline(always)]
#[must_use]
pub(crate) fn get_index(&self, name: &str) -> Option<(usize, AccessMode)> {
self.names
.iter()
@ -335,6 +341,7 @@ impl<'a> Scope<'a> {
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42);
/// ```
#[inline(always)]
#[must_use]
pub fn get_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
self.names
.iter()
@ -402,6 +409,7 @@ impl<'a> Scope<'a> {
///
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 123);
/// ```
#[must_use]
pub fn get_mut(&mut self, name: &str) -> Option<&mut Dynamic> {
self.get_index(name)
.and_then(move |(index, access)| match access {
@ -415,6 +423,7 @@ impl<'a> Scope<'a> {
///
/// Panics if the index is out of bounds.
#[inline(always)]
#[must_use]
pub(crate) fn get_mut_by_index(&mut self, index: usize) -> &mut Dynamic {
self.values
.get_mut(index)
@ -448,6 +457,7 @@ impl<'a> Scope<'a> {
/// Clone the [`Scope`], keeping only the last instances of each variable name.
/// Shadowed variables are omitted in the copy.
#[inline(always)]
#[must_use]
pub(crate) fn clone_visible(&self) -> Self {
let mut entries: Self = Default::default();
@ -467,6 +477,7 @@ impl<'a> Scope<'a> {
/// Get an iterator to entries in the [`Scope`].
#[inline(always)]
#[allow(dead_code)]
#[must_use]
pub(crate) fn into_iter(
self,
) -> impl Iterator<Item = (Cow<'a, str>, Dynamic, Vec<Identifier>)> {
@ -503,6 +514,7 @@ impl<'a> Scope<'a> {
/// assert_eq!(value.cast::<String>(), "hello");
/// ```
#[inline(always)]
#[must_use]
pub fn iter(&self) -> impl Iterator<Item = (&str, bool, Dynamic)> {
self.iter_raw()
.map(|(name, constant, value)| (name, constant, value.flatten_clone()))
@ -510,6 +522,7 @@ impl<'a> Scope<'a> {
/// Get an iterator to entries in the [`Scope`].
/// Shared values are not expanded.
#[inline(always)]
#[must_use]
pub fn iter_raw(&self) -> impl Iterator<Item = (&str, bool, &Dynamic)> {
self.names
.iter()

View File

@ -28,14 +28,17 @@ impl<'de> DynamicDeserializer<'de> {
///
/// The reference is necessary because the deserialized type may hold references
/// (especially `&str`) to the source [`Dynamic`][crate::Dynamic].
#[must_use]
pub fn from_dynamic(value: &'de Dynamic) -> Self {
Self { value }
}
/// Shortcut for a type conversion error.
#[must_use]
fn type_error<T>(&self) -> Result<T, Box<EvalAltResult>> {
self.type_error_str(type_name::<T>())
}
/// Shortcut for a type conversion error.
#[must_use]
fn type_error_str<T>(&self, error: &str) -> Result<T, Box<EvalAltResult>> {
EvalAltResult::ErrorMismatchOutputType(
error.into(),
@ -44,6 +47,7 @@ impl<'de> DynamicDeserializer<'de> {
)
.into()
}
#[must_use]
fn deserialize_int<V: Visitor<'de>>(
&mut self,
v: crate::INT,
@ -107,6 +111,7 @@ impl<'de> DynamicDeserializer<'de> {
/// # Ok(())
/// # }
/// ```
#[must_use]
pub fn from_dynamic<'de, T: Deserialize<'de>>(
value: &'de Dynamic,
) -> Result<T, Box<EvalAltResult>> {
@ -494,6 +499,7 @@ struct IterateArray<'a, ITER: Iterator<Item = &'a Dynamic>> {
#[cfg(not(feature = "no_index"))]
impl<'a, ITER: Iterator<Item = &'a Dynamic>> IterateArray<'a, ITER> {
#[must_use]
pub fn new(iter: ITER) -> Self {
Self { iter }
}
@ -534,6 +540,7 @@ where
KEYS: Iterator<Item = &'a str>,
VALUES: Iterator<Item = &'a Dynamic>,
{
#[must_use]
pub fn new(keys: KEYS, values: VALUES) -> Self {
Self { keys, values }
}

View File

@ -214,6 +214,7 @@ impl Engine {
/// 2) Functions registered into the global namespace
/// 3) Functions in static modules
/// 4) Functions in global modules (optional)
#[must_use]
pub fn gen_fn_metadata_with_ast_to_json(
&self,
ast: &AST,
@ -253,6 +254,7 @@ impl Engine {
/// 1) Functions registered into the global namespace
/// 2) Functions in static modules
/// 3) Functions in global modules (optional)
#[must_use]
pub fn gen_fn_metadata_to_json(&self, include_global: bool) -> serde_json::Result<String> {
self.gen_fn_metadata_with_ast_to_json(&Default::default(), include_global)
}

View File

@ -25,6 +25,7 @@ struct DynamicSerializer {
impl DynamicSerializer {
/// Create a [`DynamicSerializer`] from a [`Dynamic`][crate::Dynamic] value.
#[must_use]
pub fn new(_value: Dynamic) -> Self {
Self {
_key: Default::default(),
@ -81,6 +82,7 @@ impl DynamicSerializer {
/// # Ok(())
/// # }
/// ```
#[must_use]
pub fn to_dynamic<T: Serialize>(value: T) -> RhaiResult {
let mut s = DynamicSerializer::new(Default::default());
value.serialize(&mut s)

View File

@ -13,10 +13,12 @@ pub struct StringSliceDeserializer<'a> {
impl<'a> StringSliceDeserializer<'a> {
/// Create an `ImmutableStringDeserializer` from an `&str` reference.
#[must_use]
pub fn from_str(value: &'a str) -> Self {
Self { value }
}
/// Shortcut for a type conversion error.
#[must_use]
fn type_error<T>(&self) -> Result<T, Box<EvalAltResult>> {
EvalAltResult::ErrorMismatchOutputType(
type_name::<T>().into(),

View File

@ -50,21 +50,25 @@ impl<'a> From<&'a Expr> for Expression<'a> {
impl Expression<'_> {
/// If this expression is a variable name, return it. Otherwise [`None`].
#[inline(always)]
#[must_use]
pub fn get_variable_name(&self) -> Option<&str> {
self.0.get_variable_name(true)
}
/// Get the expression.
#[inline(always)]
#[must_use]
pub(crate) fn expr(&self) -> &Expr {
&self.0
}
/// Get the position of this expression.
#[inline(always)]
#[must_use]
pub fn position(&self) -> Position {
self.0.position()
}
/// Get the value of this expression if it is a literal constant.
#[inline(always)]
#[must_use]
pub fn get_literal_value(&self) -> Option<Dynamic> {
self.0.get_literal_value()
}
@ -77,6 +81,7 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_> {
///
/// This function is very low level. It evaluates an expression from an [`AST`][crate::AST].
#[inline(always)]
#[must_use]
pub fn eval_expression_tree(&mut self, expr: &Expression) -> RhaiResult {
self.engine.eval_expr(
self.scope,
@ -120,6 +125,7 @@ impl Engine {
/// since they all go away at the end of the block.
///
/// Variables in parent blocks should be left untouched as they persist beyond the current block.
#[must_use]
pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>(
&mut self,
keywords: &[S],

View File

@ -89,6 +89,7 @@ impl Position {
///
/// Panics if `line` is zero.
#[inline(always)]
#[must_use]
pub fn new(line: u16, _position: u16) -> Self {
assert!(line != 0, "line cannot be zero");
@ -101,6 +102,7 @@ impl Position {
}
/// Get the line number (1-based), or [`None`] if there is no position.
#[inline(always)]
#[must_use]
pub fn line(self) -> Option<usize> {
if self.is_none() {
None
@ -113,6 +115,7 @@ impl Position {
}
/// Get the character position (1-based), or [`None`] if at beginning of a line.
#[inline(always)]
#[must_use]
pub fn position(self) -> Option<usize> {
if self.is_none() {
None
@ -171,6 +174,7 @@ impl Position {
}
/// Is this [`Position`] at the beginning of a line?
#[inline(always)]
#[must_use]
pub fn is_beginning_of_line(self) -> bool {
#[cfg(not(feature = "no_position"))]
return self.pos == 0 && !self.is_none();
@ -179,6 +183,7 @@ impl Position {
}
/// Is there no [`Position`]?
#[inline(always)]
#[must_use]
pub fn is_none(self) -> bool {
#[cfg(not(feature = "no_position"))]
return self == Self::NONE;
@ -187,6 +192,7 @@ impl Position {
}
/// Print this [`Position`] for debug purposes.
#[inline(always)]
#[must_use]
pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(not(feature = "no_position"))]
if !self.is_none() {
@ -465,6 +471,7 @@ impl Token {
/// # Panics
///
/// Panics if the token is not a keyword.
#[must_use]
pub fn keyword_syntax(&self) -> &'static str {
use Token::*;
@ -554,6 +561,7 @@ impl Token {
}
/// Get the syntax of the token.
#[must_use]
pub fn syntax(&self) -> Cow<'static, str> {
use Token::*;
@ -580,6 +588,7 @@ impl Token {
/// Is this token an op-assignment operator?
#[inline]
#[must_use]
pub fn is_op_assignment(&self) -> bool {
match self {
Self::PlusAssign
@ -598,6 +607,7 @@ impl Token {
}
/// Get the corresponding operator of the token if it is an op-assignment operator.
#[must_use]
pub fn map_op_assignment(&self) -> Option<Self> {
Some(match self {
Self::PlusAssign => Self::Plus,
@ -617,6 +627,7 @@ impl Token {
/// Has this token a corresponding op-assignment operator?
#[inline]
#[must_use]
pub fn has_op_assignment(&self) -> bool {
match self {
Self::Plus
@ -635,6 +646,7 @@ impl Token {
}
/// Get the corresponding op-assignment operator of the token.
#[must_use]
pub fn make_op_assignment(&self) -> Option<Self> {
Some(match self {
Self::Plus => Self::PlusAssign,
@ -653,6 +665,7 @@ impl Token {
}
/// Reverse lookup a token from a piece of syntax.
#[must_use]
pub fn lookup_from_syntax(syntax: &str) -> Option<Self> {
use Token::*;
@ -763,6 +776,7 @@ impl Token {
// Is this token [`EOF`][Token::EOF]?
#[inline(always)]
#[must_use]
pub fn is_eof(&self) -> bool {
use Token::*;
@ -774,6 +788,7 @@ impl Token {
// If another operator is after these, it's probably an unary operator
// (not sure about `fn` name).
#[must_use]
pub fn is_next_unary(&self) -> bool {
use Token::*;
@ -834,6 +849,7 @@ impl Token {
}
/// Get the precedence number of the token.
#[must_use]
pub fn precedence(&self) -> Option<Precedence> {
use Token::*;
@ -868,6 +884,7 @@ impl Token {
}
/// Does an expression bind to the right (instead of left)?
#[must_use]
pub fn is_bind_right(&self) -> bool {
use Token::*;
@ -888,6 +905,7 @@ impl Token {
}
/// Is this token a standard symbol used in the language?
#[must_use]
pub fn is_symbol(&self) -> bool {
use Token::*;
@ -905,6 +923,7 @@ impl Token {
}
/// Is this token an active standard keyword?
#[must_use]
pub fn is_keyword(&self) -> bool {
use Token::*;
@ -924,6 +943,7 @@ impl Token {
/// Is this token a reserved symbol?
#[inline(always)]
#[must_use]
pub fn is_reserved(&self) -> bool {
match self {
Self::Reserved(_) => true,
@ -933,6 +953,7 @@ impl Token {
/// Convert a token into a function name, if possible.
#[cfg(not(feature = "no_function"))]
#[must_use]
pub(crate) fn into_function_name_for_override(self) -> Result<String, Self> {
match self {
Self::Custom(s) | Self::Identifier(s) if is_valid_identifier(s.chars()) => Ok(s),
@ -942,6 +963,7 @@ impl Token {
/// Is this token a custom keyword?
#[inline(always)]
#[must_use]
pub fn is_custom(&self) -> bool {
match self {
Self::Custom(_) => true,
@ -991,6 +1013,7 @@ pub trait InputStream {
/// Get the next character from the `InputStream`.
fn get_next(&mut self) -> Option<char>;
/// Peek the next character in the `InputStream`.
#[must_use]
fn peek_next(&mut self) -> Option<char>;
}
@ -1028,6 +1051,7 @@ pub trait InputStream {
/// # Volatile API
///
/// This function is volatile and may change.
#[must_use]
pub fn parse_string_literal(
stream: &mut impl InputStream,
state: &mut TokenizeState,
@ -1287,6 +1311,7 @@ fn scan_block_comment(
///
/// This function is volatile and may change.
#[inline(always)]
#[must_use]
pub fn get_next_token(
stream: &mut impl InputStream,
state: &mut TokenizeState,
@ -1326,12 +1351,14 @@ fn is_numeric_digit(c: char) -> bool {
#[cfg(not(feature = "no_function"))]
#[cfg(feature = "metadata")]
#[inline(always)]
#[must_use]
pub fn is_doc_comment(comment: &str) -> bool {
(comment.starts_with("///") && !comment.starts_with("////"))
|| (comment.starts_with("/**") && !comment.starts_with("/***"))
}
/// Get the next token.
#[must_use]
fn get_next_token_inner(
stream: &mut impl InputStream,
state: &mut TokenizeState,
@ -1962,6 +1989,7 @@ fn get_identifier(
/// Is this keyword allowed as a function?
#[inline(always)]
#[must_use]
pub fn is_keyword_function(name: &str) -> bool {
match name {
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
@ -1975,6 +2003,7 @@ pub fn is_keyword_function(name: &str) -> bool {
}
/// Is a text string a valid identifier?
#[must_use]
pub fn is_valid_identifier(name: impl Iterator<Item = char>) -> bool {
let mut first_alphabetic = false;
@ -1994,6 +2023,7 @@ pub fn is_valid_identifier(name: impl Iterator<Item = char>) -> bool {
/// Is a character valid to start an identifier?
#[cfg(feature = "unicode-xid-ident")]
#[inline(always)]
#[must_use]
pub fn is_id_first_alphabetic(x: char) -> bool {
unicode_xid::UnicodeXID::is_xid_start(x)
}
@ -2001,6 +2031,7 @@ pub fn is_id_first_alphabetic(x: char) -> bool {
/// Is a character valid for an identifier?
#[cfg(feature = "unicode-xid-ident")]
#[inline(always)]
#[must_use]
pub fn is_id_continue(x: char) -> bool {
unicode_xid::UnicodeXID::is_xid_continue(x)
}
@ -2008,6 +2039,7 @@ pub fn is_id_continue(x: char) -> bool {
/// Is a character valid to start an identifier?
#[cfg(not(feature = "unicode-xid-ident"))]
#[inline(always)]
#[must_use]
pub fn is_id_first_alphabetic(x: char) -> bool {
x.is_ascii_alphabetic()
}
@ -2015,6 +2047,7 @@ pub fn is_id_first_alphabetic(x: char) -> bool {
/// Is a character valid for an identifier?
#[cfg(not(feature = "unicode-xid-ident"))]
#[inline(always)]
#[must_use]
pub fn is_id_continue(x: char) -> bool {
x.is_ascii_alphanumeric() || x == '_'
}
@ -2201,6 +2234,7 @@ impl Engine {
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn lex<'a>(
&'a self,
input: impl IntoIterator<Item = &'a &'a str>,
@ -2211,6 +2245,7 @@ impl Engine {
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn lex_with_map<'a>(
&'a self,
input: impl IntoIterator<Item = &'a &'a str>,
@ -2220,6 +2255,7 @@ impl Engine {
}
/// Tokenize an input text stream with an optional mapping function.
#[inline(always)]
#[must_use]
pub(crate) fn lex_raw<'a>(
&'a self,
input: impl IntoIterator<Item = &'a &'a str>,

View File

@ -9,6 +9,7 @@ use std::{
/// Cast a type into another type.
#[inline(always)]
#[must_use]
pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Result<B, A> {
if TypeId::of::<B>() == a.type_id() {
// SAFETY: Just checked we have the right type. We explicitly forget the
@ -26,6 +27,7 @@ pub fn unsafe_try_cast<A: Any, B: Any>(a: A) -> Result<B, A> {
/// Cast a Boxed type into another type.
#[inline(always)]
#[must_use]
pub fn unsafe_cast_box<X: Any, T: Any>(item: Box<X>) -> Result<Box<T>, Box<X>> {
// Only allow casting to the exact same type
if TypeId::of::<X>() == TypeId::of::<T>() {
@ -50,6 +52,7 @@ pub fn unsafe_cast_box<X: Any, T: Any>(item: Box<X>) -> Result<Box<T>, Box<X>> {
/// Force-casting a local variable's lifetime to the current [`Scope`][crate::Scope]'s larger lifetime saves
/// on allocations and string cloning, thus avoids us having to maintain a chain of [`Scope`][crate::Scope]'s.
#[inline(always)]
#[must_use]
pub fn unsafe_cast_var_name_to_lifetime<'s>(name: &str) -> &'s str {
// WARNING - force-cast the variable name into the scope's lifetime to avoid cloning it
// this is safe because all local variables are cleared at the end of the block

View File

@ -54,6 +54,7 @@ impl BuildHasher for StraightHasherBuilder {
/// Create an instance of the default hasher.
#[inline(always)]
#[must_use]
pub fn get_hasher() -> ahash::AHasher {
Default::default()
}
@ -68,6 +69,7 @@ pub fn get_hasher() -> ahash::AHasher {
///
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
#[inline]
#[must_use]
pub fn calc_qualified_fn_hash<'a>(
modules: impl Iterator<Item = &'a str>,
fn_name: impl AsRef<str>,
@ -92,6 +94,7 @@ pub fn calc_qualified_fn_hash<'a>(
///
/// Parameter types are passed in via [`TypeId`] values from an iterator.
#[inline(always)]
#[must_use]
pub fn calc_fn_hash(fn_name: impl AsRef<str>, num: usize) -> u64 {
calc_qualified_fn_hash(empty(), fn_name, num)
}
@ -100,6 +103,7 @@ pub fn calc_fn_hash(fn_name: impl AsRef<str>, num: usize) -> u64 {
///
/// Parameter types are passed in via [`TypeId`] values from an iterator.
#[inline]
#[must_use]
pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
let s = &mut get_hasher();
let mut len = 0;
@ -110,6 +114,7 @@ pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
/// Combine two [`u64`] hashes by taking the XOR of them.
#[inline(always)]
#[must_use]
pub(crate) fn combine_hashes(a: u64, b: u64) -> u64 {
a ^ b
}
@ -640,6 +645,7 @@ pub struct IdentifierBuilder(
impl IdentifierBuilder {
/// Get an identifier from a text string.
#[inline(always)]
#[must_use]
pub fn get(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
#[cfg(not(feature = "no_smartstring"))]
return text.as_ref().into();