From becbfa8930321d64df58913a953a15d2bbbe9915 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 6 Feb 2022 23:02:59 +0800 Subject: [PATCH] Fix errors. --- src/api/custom_syntax.rs | 16 ++++++++-------- src/func/register.rs | 5 +++-- src/lib.rs | 3 +-- src/reify.rs | 32 ++++++++++++++++++++++++++------ src/types/dynamic.rs | 26 +++++++++++--------------- 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/api/custom_syntax.rs b/src/api/custom_syntax.rs index d5263ac4..5e6232b6 100644 --- a/src/api/custom_syntax.rs +++ b/src/api/custom_syntax.rs @@ -6,12 +6,12 @@ use crate::parser::ParseResult; use crate::tokenizer::{is_valid_identifier, Token}; use crate::types::dynamic::Variant; use crate::{ - Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult, Shared, - StaticVec, reify, + reify, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult, + Shared, StaticVec, }; +use std::ops::Deref; #[cfg(feature = "no_std")] use std::prelude::v1::*; -use std::ops::Deref; /// Collection of special markers for custom syntax definition. pub mod markers { @@ -94,18 +94,18 @@ impl Expression<'_> { pub fn get_literal_value(&self) -> Option { // Coded this way in order to maximally leverage potentials for dead-code removal. match self.0 { - Expr::IntegerConstant(x, _) => reify!(x, |x: T| Some(x), || None), + Expr::IntegerConstant(x, _) => reify!(*x, |x: T| Some(x), || None), #[cfg(not(feature = "no_float"))] - Expr::FloatConstant(x, _) => reify!(x, |x: T| Some(x), || None), + Expr::FloatConstant(x, _) => reify!(*x, |x: T| Some(x), || None), - Expr::CharConstant(x, _) => reify!(x, |x: T| Some(x), || None), + Expr::CharConstant(x, _) => reify!(*x, |x: T| Some(x), || None), Expr::StringConstant(x, _) => reify!(x.clone(), |x: T| Some(x), || None), Expr::Variable(_, _, x) => { - let x = Into::::into(&x.2); + let x: ImmutableString = x.2.clone().into(); reify!(x, |x: T| Some(x), || None) } - Expr::BoolConstant(x, _) => reify!(x, |x: T| Some(x), || None), + Expr::BoolConstant(x, _) => reify!(*x, |x: T| Some(x), || None), Expr::Unit(_) => reify!((), |x: T| Some(x), || None), _ => None, diff --git a/src/func/register.rs b/src/func/register.rs index d2171cfb..b87e0bec 100644 --- a/src/func/register.rs +++ b/src/func/register.rs @@ -7,7 +7,7 @@ use super::callable_function::CallableFunction; use super::native::{FnAny, SendSync}; use crate::tokenizer::Position; use crate::types::dynamic::{DynamicWriteLock, Variant}; -use crate::{Dynamic, NativeCallContext, RhaiResultOf, ERR, reify}; +use crate::{reify, Dynamic, NativeCallContext, RhaiResultOf, ERR}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{any::TypeId, mem}; @@ -45,7 +45,8 @@ pub fn by_value(data: &mut Dynamic) -> T { // If T is `&str`, data must be `ImmutableString`, so map directly to it data.flatten_in_place(); let ref_str = data.as_str_ref().expect("&str"); - let ref_t = reify!(ref_str, |ref_t: &T| ref_t, || unreachable!()); + //let ref_t = reify!(&ref_str, |ref_t: &T| ref_t, || unreachable!()); + let ref_t = unsafe { mem::transmute::<_, &T>(&ref_str) }; ref_t.clone() } else if TypeId::of::() == TypeId::of::() { // If T is `String`, data must be `ImmutableString`, so map directly to it diff --git a/src/lib.rs b/src/lib.rs index 98438971..883fe258 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,8 +68,6 @@ extern crate no_std_compat as std; use std::prelude::v1::*; // Internal modules -mod reify; - mod api; mod ast; mod engine; @@ -79,6 +77,7 @@ mod module; mod optimizer; pub mod packages; mod parser; +mod reify; mod tests; mod tokenizer; mod types; diff --git a/src/reify.rs b/src/reify.rs index 82d3bdbe..acb65579 100644 --- a/src/reify.rs +++ b/src/reify.rs @@ -1,13 +1,16 @@ /// Runs `$code` if `$old` is of type `$t`. +/// +/// This macro is primarily used for type casting between known types. #[macro_export] macro_rules! reify { ($old:ident, |$new:ident : $t:ty| $code:expr, || $fallback:expr) => {{ #[allow(unused_imports)] - use ::std::{any::{Any, TypeId}, mem::{ManuallyDrop, transmute_copy}}; - if TypeId::of::<$t>() == $old.type_id() { + use std::any::Any; + + if std::any::TypeId::of::<$t>() == $old.type_id() { // SAFETY: This is safe because we check to make sure the two types are // actually the same type. - let $new: $t = unsafe { transmute_copy(&ManuallyDrop::new($old)) }; + let $new: $t = unsafe { std::mem::transmute_copy(&std::mem::ManuallyDrop::new($old)) }; $code } else { $fallback @@ -15,12 +18,29 @@ macro_rules! reify { }}; ($old:expr, |$new:ident : $t:ty| $code:expr, || $fallback:expr) => {{ let old = $old; - reify!(old, |$new : $t| $code, || $fallback) + reify!(old, |$new: $t| $code, || $fallback) }}; ($old:ident, |$new:ident : $t:ty| $code:expr) => { - reify!($old, |$new : $t| $code, || ()) + reify!($old, |$new: $t| $code, || ()) }; ($old:expr, |$new:ident : $t:ty| $code:expr) => { - reify!($old, |$new : $t| $code, || ()) + reify!($old, |$new: $t| $code, || ()) }; } + +#[macro_export] +macro_rules! reify_dynamic { + ($old:ident, |$new:ident : $t:ty| $code:expr) => {{ + #[allow(unused_imports)] + use ::std::{ + any::{Any, TypeId}, + mem::{transmute_copy, ManuallyDrop}, + }; + if TypeId::of::<$t>() == TypeId::of::() { + // SAFETY: This is safe because we check to make sure the two types are + // actually the same type. + let $new: $t = unsafe { transmute_copy(&ManuallyDrop::new($old)) }; + $code + } + }}; +} diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index 489e4884..651c0c81 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -1,7 +1,7 @@ //! Helper module which defines the [`Any`] trait to to allow dynamic value handling. use crate::func::native::SendSync; -use crate::{ExclusiveRange, FnPtr, ImmutableString, InclusiveRange, INT, reify}; +use crate::{reify, reify_dynamic, ExclusiveRange, FnPtr, ImmutableString, InclusiveRange, INT}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ @@ -1182,10 +1182,10 @@ impl Dynamic { reify!(value, |v: bool| return v.into()); reify!(value, |v: char| return v.into()); reify!(value, |v: ImmutableString| return v.into()); + reify!(value, |v: String| return v.into()); reify!(value, |v: &str| return v.into()); reify!(value, |v: ()| return v.into()); - reify!(value, |v: String| return v.into()); #[cfg(not(feature = "no_index"))] reify!(value, |v: crate::Array| return v.into()); #[cfg(not(feature = "no_index"))] @@ -1200,7 +1200,8 @@ impl Dynamic { #[cfg(not(feature = "no_std"))] reify!(value, |v: Instant| return v.into()); #[cfg(not(feature = "no_closure"))] - reify!(value, |v: crate::Shared>| return v.into()); + reify!(value, |v: crate::Shared>| return v + .into()); Self(Union::Variant( Box::new(Box::new(value)), @@ -1269,20 +1270,20 @@ impl Dynamic { return self.flatten().try_cast::(); } - reify!(self, |v: T| return Some(v)); + reify_dynamic!(self, |v: T| return Some(v)); match self.0 { Union::Int(v, ..) => reify!(v, |v: T| Some(v), || None), #[cfg(not(feature = "no_float"))] - Union::Float(v, ..) => reify!(v, |v: T| Some(v), || None), + Union::Float(v, ..) => reify!(*v, |v: T| Some(v), || None), #[cfg(feature = "decimal")] - Union::Decimal(v, ..) => reify!(v, |v: T| Some(v), || None), + Union::Decimal(v, ..) => reify!(*v, |v: T| Some(v), || None), Union::Bool(v, ..) => reify!(v, |v: T| Some(v), || None), Union::Str(v, ..) => { reify!(v, |v: T| Some(v), || { reify!(v.to_string(), |v: T| Some(v), || None) }) - }, + } Union::Char(v, ..) => reify!(v, |v: T| Some(v), || None), #[cfg(not(feature = "no_index"))] Union::Array(v, ..) => reify!(v, |v: Box| Some(*v), || None), @@ -1293,7 +1294,7 @@ impl Dynamic { Union::FnPtr(v, ..) => reify!(v, |v: Box| Some(*v), || None), #[cfg(not(feature = "no_std"))] Union::TimeStamp(v, ..) => reify!(v, |v: Box| Some(*v), || None), - Union::Unit(v, ..) => reify!(v, |v: T| Some(v), || None), + Union::Unit(_, ..) => reify!((), |v: T| Some(v), || None), Union::Variant(v, _, _) => (*v).as_boxed_any().downcast().ok().map(|x| *x), #[cfg(not(feature = "no_closure"))] Union::Shared(_, _, _) => unreachable!("Union::Shared case should be already handled"), @@ -1335,13 +1336,8 @@ impl Dynamic { #[cfg(feature = "no_closure")] let self_type_name = self.type_name(); - self.try_cast::().unwrap_or_else(|| { - panic!( - "cannot cast {} value and to {}", - self_type_name, - type_name::() - ) - }) + self.try_cast::() + .unwrap_or_else(|| panic!("cannot cast {} to {}", self_type_name, type_name::())) } /// Clone the [`Dynamic`] value and convert it into a specific type. ///