diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index ef70e9d49..3911e5de2 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* [Rust] Updated derived traits mapping (by @ncave) * [Rust] Fixed try finally handler order of execution (by @ncave) * [JS/TS/Python/Rust] Fixed String.StartsWith/EndsWith (#3934) (by @ncave) * [All/Rust] Removed Regex.Replace from hot paths (by @ncave) diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs index 91fe2e366..5c0404103 100644 --- a/src/Fable.Transforms/Rust/Fable2Rust.fs +++ b/src/Fable.Transforms/Rust/Fable2Rust.fs @@ -402,75 +402,58 @@ module TypeInfo = ent.IsValueType | _ -> false - let isEntityOfType (com: IRustCompiler) isTypeOf entNames (ent: Fable.Entity) = + let hasTypeOfType (com: IRustCompiler) isTypeOf isEntityOf entNames typ = + match typ with + | Fable.Option(genArg, _) -> isTypeOf com entNames genArg + | Fable.Array(genArg, _) -> isTypeOf com entNames genArg + | Fable.List genArg -> isTypeOf com entNames genArg + | Fable.Tuple(genArgs, _) -> List.exists (isTypeOf com entNames) genArgs + | Fable.AnonymousRecordType(_, genArgs, _) -> List.exists (isTypeOf com entNames) genArgs + | Replacements.Util.Builtin(Replacements.Util.FSharpSet genArg) -> isTypeOf com entNames genArg + | Replacements.Util.Builtin(Replacements.Util.FSharpMap(k, v)) -> + isTypeOf com entNames k || isTypeOf com entNames v + | Fable.DeclaredType(entRef, _genArgs) -> + let ent = com.GetEntity(entRef) + isEntityOf com entNames ent //|| hasFieldOfType com isTypeOf entNames ent + | _ -> false + + let hasFieldOfType (com: IRustCompiler) isTypeOf entNames (ent: Fable.Entity) = if Set.contains ent.FullName entNames then - true // already checked, avoids circular checks + false // already checked, avoids circular checks else let entNames = Set.add ent.FullName entNames if ent.IsFSharpUnion then ent.UnionCases - |> Seq.forall (fun uci -> + |> Seq.exists (fun uci -> uci.UnionCaseFields - |> List.forall (fun field -> isTypeOf com entNames field.FieldType) + |> List.exists (fun fi -> isTypeOf com entNames fi.FieldType) ) else - ent.FSharpFields |> Seq.forall (fun fi -> isTypeOf com entNames fi.FieldType) + ent.FSharpFields |> Seq.exists (fun fi -> isTypeOf com entNames fi.FieldType) - let isTypeOfType (com: IRustCompiler) isTypeOf isEntityOf entNames typ = + let isNonPrintableType (com: IRustCompiler) entNames typ = match typ with - | Fable.Option(genArg, _) -> isTypeOf com entNames genArg - | Fable.Array(genArg, _) -> isTypeOf com entNames genArg - | Fable.List genArg -> isTypeOf com entNames genArg - | Fable.Tuple(genArgs, _) -> List.forall (isTypeOf com entNames) genArgs - | Fable.AnonymousRecordType(_, genArgs, _isStruct) -> List.forall (isTypeOf com entNames) genArgs - | Replacements.Util.Builtin(Replacements.Util.FSharpSet genArg) -> isTypeOf com entNames genArg - | Replacements.Util.Builtin(Replacements.Util.FSharpMap(k, v)) -> - isTypeOf com entNames k && isTypeOf com entNames v - | Fable.DeclaredType(entRef, _) -> - let ent = com.GetEntity(entRef) - isEntityOf com entNames ent - | _ -> true + // TODO: more unprintable types? + | _ -> hasTypeOfType com isNonPrintableType isNonPrintableEntity entNames typ - let isPrintableType (com: IRustCompiler) entNames typ = - match typ with - // TODO: Any unprintable types? - | _ -> isTypeOfType com isPrintableType isPrintableEntity entNames typ - - let isPrintableEntity com entNames (ent: Fable.Entity) = - not (ent.IsInterface) && (isEntityOfType com isPrintableType entNames ent) + let isNonPrintableEntity com entNames (ent: Fable.Entity) = false + // || (hasFieldOfType com isNonPrintableType entNames ent) - let isDefaultableType (com: IRustCompiler) entNames typ = + let isNonDefaultableType (com: IRustCompiler) entNames typ = match typ with // TODO: more undefaultable types? | Fable.LambdaType _ - | Fable.DelegateType _ -> false - | _ -> isTypeOfType com isDefaultableType isDefaultableEntity entNames typ - - let isDefaultableEntity com entNames (ent: Fable.Entity) = - ent.IsValueType - && not (ent.IsInterface) - && not (ent.IsFSharpUnion) // deriving 'Default' on enums is experimental - && (isEntityOfType com isDefaultableType entNames ent) - - let isHashableType (com: IRustCompiler) entNames typ = - match typ with - // TODO: more unhashable types? - | Fable.Any - | Fable.Unit - | Fable.Measure _ - | Fable.MetaType - | Fable.Number((Float32 | Float64), _) - | Fable.LambdaType _ - | Fable.DelegateType _ -> false - | _ -> isTypeOfType com isHashableType isHashableEntity entNames typ + | Fable.DelegateType _ -> true + | _ -> hasTypeOfType com isNonDefaultableType isNonDefaultableEntity entNames typ - let isHashableEntity com entNames (ent: Fable.Entity) = - not (ent.IsInterface) - && (FSharp2Fable.Util.hasStructuralEquality ent) - && (isEntityOfType com isHashableType entNames ent) + let isNonDefaultableEntity com entNames (ent: Fable.Entity) = + ent.IsInterface + || not ent.IsValueType + || ent.IsFSharpUnion // deriving 'Default' on enums is experimental + || (hasFieldOfType com isNonDefaultableType entNames ent) - let isCopyableType (com: IRustCompiler) entNames typ = + let isNonCopyableType (com: IRustCompiler) entNames typ = match typ with // TODO: more uncopyable types? | Fable.Any @@ -481,19 +464,17 @@ module TypeInfo = | Fable.DelegateType _ | Fable.GenericParam _ | Fable.String - | Fable.Regex -> false - | Fable.Tuple(genArgs, isStruct) -> isStruct && (List.forall (isCopyableType com entNames) genArgs) - | Fable.AnonymousRecordType(_, genArgs, isStruct) -> - isStruct && (List.forall (isCopyableType com entNames) genArgs) - | _ -> isTypeOfType com isCopyableType isCopyableEntity entNames typ - - let isCopyableEntity com entNames (ent: Fable.Entity) = - ent.IsValueType - && not (ent.IsInterface) - && not (hasMutableFields com ent) - && (isEntityOfType com isCopyableType entNames ent) - - let isEquatableType (com: IRustCompiler) entNames typ = + | Fable.Regex -> true + | Fable.Tuple(genArgs, isStruct) when not isStruct -> true + | Fable.AnonymousRecordType(_, genArgs, isStruct) when not isStruct -> true + | _ -> hasTypeOfType com isNonCopyableType isNonCopyableEntity entNames typ + + let isNonCopyableEntity com entNames (ent: Fable.Entity) = + not ent.IsValueType + || (hasMutableFields com ent) + || (hasFieldOfType com isNonCopyableType entNames ent) + + let isNonEquatableType (com: IRustCompiler) entNames typ = match typ with // TODO: more unequatable types? | Fable.Any @@ -501,17 +482,16 @@ module TypeInfo = | Fable.Measure _ | Fable.MetaType | Fable.LambdaType _ - | Fable.DelegateType _ -> false + | Fable.DelegateType _ -> true // | Fable.GenericParam(_, _, constraints) -> - // constraints |> List.contains Fable.Constraint.HasEquality - | _ -> isTypeOfType com isEquatableType isEquatableEntity entNames typ + // not (constraints |> List.contains Fable.Constraint.HasEquality) + | _ -> hasTypeOfType com isNonEquatableType isNonEquatableEntity entNames typ - let isEquatableEntity com entNames (ent: Fable.Entity) = - not (ent.IsInterface) - && (FSharp2Fable.Util.hasStructuralEquality ent) - && (isEntityOfType com isEquatableType entNames ent) + let isNonEquatableEntity com entNames (ent: Fable.Entity) = + ent.IsInterface || not (FSharp2Fable.Util.hasStructuralEquality ent) + // || (hasFieldOfType com isNonEquatableType entNames ent) - let isComparableType (com: IRustCompiler) entNames typ = + let isNonComparableType (com: IRustCompiler) entNames typ = match typ with // TODO: more uncomparable types? | Fable.Any @@ -520,15 +500,32 @@ module TypeInfo = | Fable.MetaType | Fable.LambdaType _ | Fable.DelegateType _ - | Fable.Regex -> false + | Fable.Regex -> true // | Fable.GenericParam(_, _, constraints) -> - // constraints |> List.contains Fable.Constraint.HasComparison - | _ -> isTypeOfType com isComparableType isComparableEntity entNames typ + // not (constraints |> List.contains Fable.Constraint.HasComparison) + | _ -> hasTypeOfType com isNonComparableType isNonComparableEntity entNames typ - let isComparableEntity com entNames (ent: Fable.Entity) = - not (ent.IsInterface) - && (FSharp2Fable.Util.hasStructuralComparison ent) - && (isEntityOfType com isComparableType entNames ent) + let isNonComparableEntity com entNames (ent: Fable.Entity) = + ent.IsInterface + || not (FSharp2Fable.Util.hasStructuralComparison ent) + || (hasFieldOfType com isNonComparableType entNames ent) + + let isNonHashableType com entNames typ = + match typ with + // TODO: more unhashable types? + | Fable.Any + | Fable.Unit + | Fable.Measure _ + | Fable.MetaType + | Fable.Number((Float32 | Float64), _) + | Fable.LambdaType _ + | Fable.DelegateType _ -> true + | _ -> hasTypeOfType com isNonHashableType isNonHashableEntity entNames typ + + let isNonHashableEntity com entNames (ent: Fable.Entity) = + ent.IsInterface + || not (FSharp2Fable.Util.hasStructuralEquality ent) + || (hasFieldOfType com isNonHashableType entNames ent) let isWrappedType com typ = match typ with @@ -1301,11 +1298,6 @@ module Util = else ty - let memberFromName (memberName: string) : Rust.Expr * bool = - match memberName with - | "ToString" -> (mkGenericPathExpr [ "ToString" ] None), false - | n -> (mkGenericPathExpr [ n ] None), false - let getField r (expr: Rust.Expr) (fieldName: string) = mkFieldExpr expr (fieldName |> sanitizeMember) // ?loc=r) @@ -3890,10 +3882,7 @@ module Util = | Fable.Constraint.HasDefaultConstructor -> [] | Fable.Constraint.HasComparison -> [ makeRawBound "PartialOrd" ] | Fable.Constraint.HasEquality -> - [ - makeGenBound ("core" :: "hash" :: "Hash" :: []) [] - makeRawBound "PartialEq" // "Eq" - ] + [ makeGenBound ("core" :: "hash" :: "Hash" :: []) []; makeRawBound "PartialEq" ] | Fable.Constraint.IsUnmanaged -> [] | Fable.Constraint.IsEnum -> [] @@ -4259,32 +4248,28 @@ module Util = fnItem let makeDerivedFrom com (ent: Fable.Entity) = - let isCopyable = ent |> isCopyableEntity com Set.empty - let isPrintable = ent |> isPrintableEntity com Set.empty - let isDefaultable = ent |> isDefaultableEntity com Set.empty - let isComparable = ent |> isComparableEntity com Set.empty - let isEquatable = ent |> isEquatableEntity com Set.empty - let isHashable = ent |> isHashableEntity com Set.empty + // let isCopyable = not (ent |> isNonCopyableEntity com Set.empty) + let isPrintable = not (ent |> isNonPrintableEntity com Set.empty) + let isDefaultable = not (ent |> isNonDefaultableEntity com Set.empty) + let isHashable = not (ent |> isNonHashableEntity com Set.empty) + let isEquatable = not (ent |> isNonEquatableEntity com Set.empty) + let isComparable = not (ent |> isNonComparableEntity com Set.empty) let derivedFrom = [ rawIdent "Clone" - if isCopyable then - rawIdent "Copy" + // if isCopyable then + // rawIdent "Copy" if isPrintable then rawIdent "Debug" if isDefaultable then rawIdent "Default" + if isHashable then + rawIdent "Hash" if isEquatable then rawIdent "PartialEq" if isComparable then rawIdent "PartialOrd" - if isHashable then - rawIdent "Hash" - if isEquatable && isHashable then - rawIdent "Eq" - // if isComparable && isHashable then - // rawIdent "Ord" ] derivedFrom diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs index 9b07cb494..54b6b31a8 100644 --- a/src/Fable.Transforms/Rust/Replacements.fs +++ b/src/Fable.Transforms/Rust/Replacements.fs @@ -433,7 +433,8 @@ let isCompatibleWithNativeComparison = | GenericParam _ | Array _ | List _ - | Builtin(BclGuid | BclTimeSpan) -> true + | Builtin(BclGuid) -> true + | Builtin(BclTimeSpan) -> true | _ -> false // Overview of hash rules: @@ -474,7 +475,8 @@ let equals (com: ICompiler) ctx r (left: Expr) (right: Expr) = | Boolean | Char | String - | Number _ -> makeEqOp r left right BinaryEqual + | Number _ + | Builtin(FSharpChoice _ | FSharpResult _) -> makeEqOp r left right BinaryEqual | Builtin kind -> Helper.LibCall(com, coreModFor kind, "equals", t, [ left; right ], ?loc = r) | Array _ -> Helper.LibCall(com, "Array", "equals", t, [ left; right ], ?loc = r) | List _ -> Helper.LibCall(com, "List", "equals", t, [ left; right ], ?loc = r) @@ -499,7 +501,8 @@ let compare (com: ICompiler) ctx r (left: Expr) (right: Expr) = | Boolean | Char | String - | Number _ -> Helper.LibCall(com, "Native", "compare", t, [ left; right ], ?loc = r) + | Number _ + | Builtin(FSharpChoice _ | FSharpResult _) -> Helper.LibCall(com, "Native", "compare", t, [ left; right ], ?loc = r) | Builtin kind -> Helper.LibCall(com, coreModFor kind, "compareTo", t, [ left; right ], ?loc = r) | Array _ -> Helper.LibCall(com, "Array", "compareTo", t, [ left; right ], ?loc = r) | List _ -> Helper.LibCall(com, "List", "compareTo", t, [ left; right ], ?loc = r) diff --git a/src/fable-library-rust/src/Async.rs b/src/fable-library-rust/src/Async.rs index efdcf0f2c..806cdee7b 100644 --- a/src/fable-library-rust/src/Async.rs +++ b/src/fable-library-rust/src/Async.rs @@ -161,7 +161,7 @@ pub mod Monitor_ { use std::thread; use std::time::Duration; - use crate::Native_::{Func0, Lrc}; + use crate::Native_::{Func0, LrcPtr}; static mut LOCKS: Option>> = None; fn try_init_and_get_locks() -> &'static RwLock> { @@ -175,7 +175,7 @@ pub mod Monitor_ { } } - pub fn enter(o: Lrc) { + pub fn enter(o: LrcPtr) { let p = Arc::::as_ptr(&o) as usize; loop { let otherHasLock = try_init_and_get_locks().read().unwrap().get(&p).is_some(); @@ -188,7 +188,7 @@ pub mod Monitor_ { } } - pub fn exit(o: Lrc) { + pub fn exit(o: LrcPtr) { let p = Arc::::as_ptr(&o) as usize; let hasRemoved = try_init_and_get_locks().write().unwrap().remove(&p); if (!hasRemoved) { @@ -197,7 +197,7 @@ pub mod Monitor_ { } // Not technically part of monitor, but it needs to be behind a feature switch, so cannot just dump this in Native - pub fn lock(toLock: Arc, f: Func0) -> U { + pub fn lock(toLock: LrcPtr, f: Func0) -> U { enter(toLock.clone()); let returnVal = f(); // panics will bypass this - need some finally mechanism @@ -401,7 +401,7 @@ pub mod Task_ { #[cfg(feature = "threaded")] pub mod TaskBuilder_ { - use super::super::Native_::Lrc; + use super::super::Native_::LrcPtr; use super::Task_::Task; use std::sync::Arc; @@ -414,8 +414,8 @@ pub mod TaskBuilder_ { } } - pub fn new() -> Lrc { - Lrc::from(TaskBuilder {}) + pub fn new() -> LrcPtr { + LrcPtr::new(TaskBuilder {}) } } @@ -424,7 +424,7 @@ pub mod Thread_ { use std::thread; use std::time::Duration; - use crate::Native_::{Func0, Lrc, MutCell}; + use crate::Native_::{Func0, LrcPtr, MutCell}; enum ThreadInt { New(Func0<()>), @@ -439,8 +439,8 @@ pub mod Thread_ { } pub struct Thread(MutCell); - pub fn new(f: Func0<()>) -> Lrc { - Lrc::from(Thread(MutCell::from(ThreadInt::New(f)))) + pub fn new(f: Func0<()>) -> LrcPtr { + LrcPtr::new(Thread(MutCell::from(ThreadInt::New(f)))) } impl Thread { diff --git a/src/fable-library-rust/src/Char.rs b/src/fable-library-rust/src/Char.rs index 9e1c789cc..b683bcbb0 100644 --- a/src/fable-library-rust/src/Char.rs +++ b/src/fable-library-rust/src/Char.rs @@ -1,6 +1,6 @@ pub mod Char_ { use crate::NativeArray_::{array_from, Array}; - use crate::Native_::{compare, Lrc, MutCell, ToString, Vec}; + use crate::Native_::{compare, MutCell, ToString}; use crate::String_::{getCharAt, length, string, toString}; // https://docs.microsoft.com/en-us/dotnet/api/system.globalization.unicodecategory?view=net-6.0 diff --git a/src/fable-library-rust/src/FuncType.rs b/src/fable-library-rust/src/FuncType.rs index 89495fd10..41ec66e7c 100644 --- a/src/fable-library-rust/src/FuncType.rs +++ b/src/fable-library-rust/src/FuncType.rs @@ -1,4 +1,4 @@ -use crate::Native_::Lrc; +use crate::Native_::{referenceEquals, referenceHash, Lrc}; macro_rules! func { ($f:ident $(,$i:ident)*) => { @@ -6,13 +6,13 @@ macro_rules! func { #[cfg(not(feature = "enum_func"))] #[derive(Clone)] #[repr(transparent)] - pub struct $f<$($i, )*R>(Lrc R>); + pub struct $f<$($i, )*R>(Option R>>); #[cfg(feature = "enum_func")] #[derive(Clone)] pub enum $f<$($i, )*R> { - Static(fn($($i), *) -> R), - Shared(Lrc R>), + Static(fn($($i, )*) -> R), + Shared(Option R>>), } impl<$($i, )*R> core::fmt::Debug for $f<$($i, )*R> { @@ -27,15 +27,41 @@ macro_rules! func { } } + impl<$($i, )*R> core::hash::Hash for $f<$($i, )*R> { + #[inline] + fn hash(&self, state: &mut H) { + referenceHash(&*self).hash(state); + } + } + + impl<$($i, )*R> PartialEq for $f<$($i, )*R> { + #[inline] + fn eq(&self, other: &Self) -> bool { + referenceEquals(&*self, &*other) + } + } + + impl<$($i, )*R> Eq for $f<$($i, )*R> {} + #[cfg(not(feature = "enum_func"))] - impl<$($i, )*R> core::ops::Deref for $f<$($i, )*R> - where - $($i: 'static, )* - R: 'static, - { - type Target = dyn Fn($($i), *) -> R; + impl<$($i, )*R> Default for $f<$($i, )*R> { + fn default() -> Self { + $f(None) + } + } + + #[cfg(feature = "enum_func")] + impl<$($i, )*R> Default for $f<$($i, )*R> { + fn default() -> Self { + $f::Shared(None) + } + } + + #[cfg(not(feature = "enum_func"))] + impl<$($i, )*R> core::ops::Deref for $f<$($i, )*R> { + type Target = dyn Fn($($i, )*) -> R; fn deref(&self) -> &Self::Target { - self.0.deref() + self.0.as_ref().expect("Null reference exception.").as_ref() } } @@ -49,36 +75,28 @@ macro_rules! func { fn deref(&self) -> &Self::Target { match self { $f::Static(f) => f, - $f::Shared(p) => p.as_ref(), + $f::Shared(p) => p.as_ref().expect("Null reference exception.").as_ref(), } } } #[cfg(not(feature = "enum_func"))] - impl<$($i, )*R> $f<$($i, )*R> - where - $($i: 'static, )* - R: 'static, - { - pub fn from(f: fn($($i), *) -> R) -> Self { - $f(Lrc::new(f)) + impl<$($i, )*R> $f<$($i, )*R> { + pub fn from R + 'static>(f: F) -> Self { + $f(Some(Lrc::new(f) as Lrc R>)) } - pub fn new R + 'static>(f: F) -> Self { - $f(Lrc::new(f)) + pub fn new R + 'static>(f: F) -> Self { + $f(Some(Lrc::new(f) as Lrc R>)) } } #[cfg(feature = "enum_func")] - impl<$($i, )*R> $f<$($i, )*R> - where - $($i: 'static, )* - R: 'static, - { - pub fn from(f: fn($($i), *) -> R) -> Self { + impl<$($i, )*R> $f<$($i, )*R> { + pub fn from(f: fn($($i, )*) -> R) -> Self { $f::Static(f) } - pub fn new R + 'static>(f: F) -> Self { - $f::Shared(Lrc::new(f)) + pub fn new R + 'static>(f: F) -> Self { + $f::Shared(Some(Lrc::new(f) as Lrc R>)) } } diff --git a/src/fable-library-rust/src/HashMap.rs b/src/fable-library-rust/src/HashMap.rs index f265d033d..797770321 100644 --- a/src/fable-library-rust/src/HashMap.rs +++ b/src/fable-library-rust/src/HashMap.rs @@ -10,8 +10,8 @@ pub mod HashMap_ { use std::collections; use crate::NativeArray_::{array_from, Array}; - use crate::Native_::{mkRefMut, seq_to_iter, HashKey, Lrc, LrcPtr, MutCell, Seq, Vec}; - use crate::System::Collections::Generic::EqualityComparer_1; + use crate::Native_::{default_eq_comparer, mkRefMut, seq_to_iter}; + use crate::Native_::{HashKey, LrcPtr, MutCell, Seq, Vec}; use crate::System::Collections::Generic::IEqualityComparer_1; use core::fmt::{Debug, Display, Formatter, Result}; @@ -21,7 +21,7 @@ pub mod HashMap_ { #[derive(Clone)] //, Debug, Default, PartialEq, PartialOrd, Eq, Hash, Ord)] pub struct HashMap { - hash_map: Lrc>, + hash_map: LrcPtr>, comparer: LrcPtr>, } @@ -35,7 +35,7 @@ pub mod HashMap_ { // } impl core::ops::Deref for HashMap { - type Target = Lrc>; + type Target = LrcPtr>; fn deref(&self) -> &Self::Target { &self.hash_map } @@ -77,7 +77,7 @@ pub mod HashMap_ { { HashMap { hash_map: mkRefMut(collections::HashMap::new()), - comparer: EqualityComparer_1::::get_Default(), + comparer: default_eq_comparer::(), } } @@ -87,7 +87,7 @@ pub mod HashMap_ { { HashMap { hash_map: mkRefMut(collections::HashMap::with_capacity(capacity as usize)), - comparer: EqualityComparer_1::::get_Default(), + comparer: default_eq_comparer::(), } } @@ -114,7 +114,7 @@ pub mod HashMap_ { where K: Clone + Hash + PartialEq + 'static, { - from_iter(seq_to_iter(&seq), EqualityComparer_1::::get_Default()) + from_iter(seq_to_iter(&seq), default_eq_comparer::()) } pub fn new_from_enumerable_comparer( @@ -140,7 +140,7 @@ pub mod HashMap_ { K: Clone + Hash + PartialEq + 'static, { let it = a.iter().map(|tup| tup.as_ref().clone()); - from_iter(it, EqualityComparer_1::::get_Default()) + from_iter(it, default_eq_comparer::()) } pub fn isReadOnly(map: HashMap) -> bool { diff --git a/src/fable-library-rust/src/HashSet.rs b/src/fable-library-rust/src/HashSet.rs index 1d8ed593b..7b47f56b3 100644 --- a/src/fable-library-rust/src/HashSet.rs +++ b/src/fable-library-rust/src/HashSet.rs @@ -10,8 +10,8 @@ pub mod HashSet_ { use std::collections; use crate::NativeArray_::{array_from, Array}; - use crate::Native_::{mkRefMut, seq_to_iter, HashKey, Lrc, LrcPtr, MutCell, Seq, Vec}; - use crate::System::Collections::Generic::EqualityComparer_1; + use crate::Native_::{default_eq_comparer, mkRefMut, seq_to_iter}; + use crate::Native_::{HashKey, LrcPtr, MutCell, Seq, Vec}; use crate::System::Collections::Generic::IEqualityComparer_1; use core::fmt::{Debug, Display, Formatter, Result}; @@ -21,7 +21,7 @@ pub mod HashSet_ { #[derive(Clone)] //, Debug, Default, PartialEq, PartialOrd, Eq, Hash, Ord)] pub struct HashSet { - hash_set: Lrc>, + hash_set: LrcPtr>, comparer: LrcPtr>, } @@ -35,7 +35,7 @@ pub mod HashSet_ { // } impl core::ops::Deref for HashSet { - type Target = Lrc>; + type Target = LrcPtr>; fn deref(&self) -> &Self::Target { &self.hash_set } @@ -74,7 +74,7 @@ pub mod HashSet_ { { HashSet { hash_set: mkRefMut(collections::HashSet::new()), - comparer: EqualityComparer_1::::get_Default(), + comparer: default_eq_comparer::(), } } @@ -84,7 +84,7 @@ pub mod HashSet_ { { HashSet { hash_set: mkRefMut(collections::HashSet::with_capacity(capacity as usize)), - comparer: EqualityComparer_1::::get_Default(), + comparer: default_eq_comparer::(), } } @@ -109,7 +109,7 @@ pub mod HashSet_ { where T: Clone + Hash + PartialEq + 'static, { - from_iter(seq_to_iter(&seq), EqualityComparer_1::::get_Default()) + from_iter(seq_to_iter(&seq), default_eq_comparer::()) } pub fn new_from_enumerable_comparer( diff --git a/src/fable-library-rust/src/LrcPtr.rs b/src/fable-library-rust/src/LrcPtr.rs index 89531b2d6..337399204 100644 --- a/src/fable-library-rust/src/LrcPtr.rs +++ b/src/fable-library-rust/src/LrcPtr.rs @@ -1,4 +1,6 @@ use crate::Native_::{Any, Lrc}; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; use core::ops::*; // ----------------------------------------------------------- @@ -14,9 +16,11 @@ impl LrcPtr { pub fn new(value: T) -> Self { LrcPtr(Some(Lrc::new(value))) } +} +impl LrcPtr { #[inline] - pub fn null(value: T) -> Self { + pub fn null() -> Self { LrcPtr(None) } @@ -26,6 +30,12 @@ impl LrcPtr { } } +// impl Default for LrcPtr { +// fn default() -> Self { +// Self::null() +// } +// } + impl From> for LrcPtr { #[inline] fn from(value: Lrc) -> Self { @@ -77,6 +87,60 @@ impl, Idx> Index for LrcPtr { } } +// ----------------------------------------------------------- +// LrcPtr equality and comparison +// ----------------------------------------------------------- + +// impl Hash for LrcPtr { +// #[inline] +// fn hash(&self, state: &mut H) { +// self.as_ref().hash(state); +// } +// } + +// impl PartialEq for LrcPtr { +// #[inline] +// fn eq(&self, other: &Self) -> bool { +// self.as_ref().eq(other.as_ref()) +// } +// } + +// impl Eq for LrcPtr {} + +// impl PartialOrd for LrcPtr { +// #[inline] +// fn partial_cmp(&self, other: &Self) -> Option { +// self.as_ref().partial_cmp(other.as_ref()) +// } + +// #[inline] +// fn lt(&self, other: &Self) -> bool { +// self.as_ref() < other.as_ref() +// } + +// #[inline] +// fn le(&self, other: &Self) -> bool { +// self.as_ref() <= other.as_ref() +// } + +// #[inline] +// fn gt(&self, other: &Self) -> bool { +// self.as_ref() > other.as_ref() +// } + +// #[inline] +// fn ge(&self, other: &Self) -> bool { +// self.as_ref() >= other.as_ref() +// } +// } + +// impl Ord for LrcPtr { +// #[inline] +// fn cmp(&self, other: &Self) -> Ordering { +// self.as_ref().cmp(other.as_ref()) +// } +// } + // ----------------------------------------------------------- // LrcPtr operator traits // ----------------------------------------------------------- diff --git a/src/fable-library-rust/src/Map.fs b/src/fable-library-rust/src/Map.fs index 9223858bd..326ca7366 100644 --- a/src/fable-library-rust/src/Map.fs +++ b/src/fable-library-rust/src/Map.fs @@ -18,7 +18,7 @@ type MapTree<'K, 'V> = Right: Map<'K, 'V> } -and [] Map<'K, 'V> = { root: Option> } +and [] Map<'K, 'V> = { root: Option> } let inline private getRoot m = m.root diff --git a/src/fable-library-rust/src/Mutable.rs b/src/fable-library-rust/src/Mutable.rs index ecd12f97b..43d64ec40 100644 --- a/src/fable-library-rust/src/Mutable.rs +++ b/src/fable-library-rust/src/Mutable.rs @@ -80,6 +80,13 @@ mod NonSyncCell { } } + // impl Default for MutCell { + // #[inline] + // fn default() -> MutCell { + // MutCell::new(unsafe { core::mem::zeroed() }) + // } + // } + impl Clone for MutCell { #[inline] fn clone(&self) -> MutCell { diff --git a/src/fable-library-rust/src/Native.rs b/src/fable-library-rust/src/Native.rs index abfec4ce7..a2f221ac4 100644 --- a/src/fable-library-rust/src/Native.rs +++ b/src/fable-library-rust/src/Native.rs @@ -55,6 +55,7 @@ pub mod Native_ { value } + use crate::System::Collections::Generic::EqualityComparer_1; use crate::System::Collections::Generic::IEnumerable_1; use crate::System::Collections::Generic::IEqualityComparer_1; @@ -115,7 +116,7 @@ pub mod Native_ { ((h >> 32) ^ h) as i32 } - pub fn referenceHash(p: &T) -> i32 { + pub fn referenceHash(p: &T) -> i32 { getHashCode(p as *const T) } @@ -149,6 +150,16 @@ pub mod Native_ { } } + pub fn default_eq_comparer() -> LrcPtr> + where + T: Clone + Hash + PartialEq + 'static, + { + interface_cast!( + EqualityComparer_1::::get_Default(), + Lrc>, + ) + } + // ----------------------------------------------------------- // IEqualityComparer key wrapper // ----------------------------------------------------------- @@ -299,8 +310,8 @@ pub mod Native_ { // ----------------------------------------------------------- #[inline] - pub fn mkRef(x: T) -> Lrc { - Lrc::from(x) + pub fn mkRef(x: T) -> LrcPtr { + LrcPtr::new(x) } #[inline] @@ -309,7 +320,7 @@ pub mod Native_ { } #[inline] - pub fn mkRefMut(x: T) -> Lrc> { + pub fn mkRefMut(x: T) -> LrcPtr> { mkRef(mkMut(x)) } diff --git a/src/fable-library-rust/src/NativeArray.rs b/src/fable-library-rust/src/NativeArray.rs index 9faec9b9d..bf8c7650c 100644 --- a/src/fable-library-rust/src/NativeArray.rs +++ b/src/fable-library-rust/src/NativeArray.rs @@ -1,7 +1,7 @@ pub mod NativeArray_ { use crate::Global_::SR::indexOutOfBounds; use crate::Native_::{alloc, make_compare, mkRefMut, partial_compare, seq_to_iter}; - use crate::Native_::{Func1, Func2, Lrc, LrcPtr, MutCell, Seq, Vec}; + use crate::Native_::{Func1, Func2, LrcPtr, MutCell, Seq, Vec}; use crate::System::Collections::Generic::IComparer_1; // ----------------------------------------------------------- @@ -10,12 +10,12 @@ pub mod NativeArray_ { type MutArray = MutCell>; - #[repr(transparent)] #[derive(Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] - pub struct Array(Lrc>); + #[repr(transparent)] + pub struct Array(LrcPtr>); impl core::ops::Deref for Array { - type Target = Lrc>; + type Target = LrcPtr>; fn deref(&self) -> &Self::Target { &self.0 } diff --git a/src/fable-library-rust/src/Set.fs b/src/fable-library-rust/src/Set.fs index eb769a513..81442dbb9 100644 --- a/src/fable-library-rust/src/Set.fs +++ b/src/fable-library-rust/src/Set.fs @@ -17,7 +17,7 @@ type SetTree<'T> = Right: Set<'T> } -and [] Set<'T> = { root: Option> } +and [] Set<'T> = { root: Option> } type 'T set = Set<'T> diff --git a/src/fable-library-rust/src/System.fs b/src/fable-library-rust/src/System.fs index 4a7b9674c..1983735a3 100644 --- a/src/fable-library-rust/src/System.fs +++ b/src/fable-library-rust/src/System.fs @@ -17,6 +17,10 @@ type Exception(message: string) = else message + interface System.Collections.IStructuralEquatable with + member x.Equals(y, comparer) = false + member x.GetHashCode(comparer) = 0 + type InvalidOperationException(message: string) = new() = InvalidOperationException("")