From 3e1f4c84e7007e3c01f00b7271aa9f59da23412b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0=20=D0=A3=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=97=D0=BD=D1=96!=20=D0=93=D0=B5=D1=80=D0=BE=D1=8F=D0=BC=20?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=D0=B0!?= <777696+ncave@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:06:23 +0000 Subject: [PATCH] [Rust] Relaxed type constraints on Dictionary and HashSet (#3899) --- .../Rust/AST/Rust.AST.Helpers.fs | 10 +- src/Fable.Transforms/Rust/Fable2Rust.fs | 18 ++- src/fable-library-rust/src/HashMap.rs | 105 +++++++----------- src/fable-library-rust/src/HashSet.rs | 65 +++++------ src/fable-library-rust/src/Native.rs | 20 ++-- .../src/System.Collections.Generic.fs | 11 +- 6 files changed, 104 insertions(+), 125 deletions(-) diff --git a/src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs b/src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs index 9fbe85af11..bd8d6137cc 100644 --- a/src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs +++ b/src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs @@ -383,18 +383,20 @@ module Paths = tokens = None } - let mkGenericPath (names: Symbol seq) (genArgs: GenericArgs option) : Path = + let mkGenericOffsetPath (names: Symbol seq) (genArgs: GenericArgs option) (offset: int) : Path = let len = Seq.length names let idents = mkPathIdents names let args i = - if i < len - 1 then - None - else + if i = len - 1 - offset then genArgs + else + None idents |> Seq.mapi (fun i ident -> mkPathSegment ident (args i)) |> mkPath + let mkGenericPath (names: Symbol seq) (genArgs: GenericArgs option) : Path = mkGenericOffsetPath names genArgs 0 + [] module Patterns = diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs index bad7b91857..4cc6299123 100644 --- a/src/Fable.Transforms/Rust/Fable2Rust.fs +++ b/src/Fable.Transforms/Rust/Fable2Rust.fs @@ -304,6 +304,12 @@ module TypeInfo = let parts = splitNameParts fullName mkGenericPath parts genArgsOpt + let makeStaticCallPathExpr importName membName genArgsOpt = + let fullName = importName + "::" + membName + let parts = splitNameParts fullName + let offset = 1 // genArgs position offset is one before last + mkGenericOffsetPath parts genArgsOpt offset |> mkPathExpr + let makeFullNamePathExpr fullName genArgsOpt = makeFullNamePath fullName genArgsOpt |> mkPathExpr @@ -665,12 +671,12 @@ module TypeInfo = // for constructors or static members, import just the type let selector, membName = Fable.Naming.splitLastBy "." info.Selector let importName = com.GetImportName(ctx, selector, info.Path, r) - makeFullNamePathExpr (importName + "::" + membName) genArgsOpt + makeStaticCallPathExpr importName membName genArgsOpt | Fable.LibraryImport mi when not (mi.IsInstanceMember) && not (mi.IsModuleMember) -> // for static (non-module and non-instance) members, import just the type let selector, membName = Fable.Naming.splitLastBy "::" info.Selector let importName = com.GetImportName(ctx, selector, info.Path, r) - makeFullNamePathExpr (importName + "::" + membName) genArgsOpt + makeStaticCallPathExpr importName membName genArgsOpt | _ -> // all other imports let importName = com.GetImportName(ctx, info.Selector, info.Path, r) @@ -2338,9 +2344,9 @@ module Util = mkCallExpr callee [] |> mutableGet else mkCallExpr callee args - | None, Fable.LibraryImport memberInfo -> + | None, Fable.LibraryImport mi -> let genArgsOpt = - if needGenArgs && memberInfo.IsModuleMember then + if needGenArgs && (mi.IsModuleMember || not mi.IsInstanceMember) then match typ with | Fable.Tuple _ -> transformGenArgs com ctx [ typ ] | _ -> transformGenArgs com ctx typ.Generics @@ -3678,7 +3684,7 @@ module Util = | Fable.Constraint.CoercesTo(targetType) -> match targetType with | IFormattable -> [ makeGenBound ("core" :: "fmt" :: "Display" :: []) [] ] - | IEquatable _ -> [ makeRawBound "Eq"; makeGenBound ("core" :: "hash" :: "Hash" :: []) [] ] + | IEquatable _ -> [ makeGenBound ("core" :: "hash" :: "Hash" :: []) []; makeRawBound "PartialEq" ] | Fable.DeclaredType(entRef, genArgs) -> let ent = com.GetEntity(entRef) @@ -3697,8 +3703,8 @@ module Util = | Fable.Constraint.HasComparison -> [ makeRawBound "PartialOrd" ] | Fable.Constraint.HasEquality -> [ - makeRawBound "Eq" // "PartialEq" makeGenBound ("core" :: "hash" :: "Hash" :: []) [] + makeRawBound "PartialEq" // "Eq" ] | Fable.Constraint.IsUnmanaged -> [] | Fable.Constraint.IsEnum -> [] diff --git a/src/fable-library-rust/src/HashMap.rs b/src/fable-library-rust/src/HashMap.rs index c2dee0058f..cbcb1a8eb0 100644 --- a/src/fable-library-rust/src/HashMap.rs +++ b/src/fable-library-rust/src/HashMap.rs @@ -9,9 +9,10 @@ pub mod HashMap_ { #[cfg(not(feature = "no_std"))] use std::collections; - use crate::System::Collections::Generic::IEqualityComparer_1; 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::System::Collections::Generic::IEqualityComparer_1; use core::fmt::{Debug, Display, Formatter, Result}; use core::hash::{Hash, Hasher}; @@ -21,10 +22,13 @@ pub mod HashMap_ { #[derive(Clone)] //, Debug, Default, PartialEq, PartialOrd, Eq, Hash, Ord)] pub struct HashMap { hash_map: Lrc>, - comparer: Option>>, + comparer: LrcPtr>, } - impl Default for HashMap { + impl Default for HashMap + where + K: Clone + Hash + PartialEq + 'static, + { fn default() -> HashMap { new_empty() } @@ -49,13 +53,10 @@ pub mod HashMap_ { } } - fn from_iter>( + fn from_iter>( iter: I, - comparer: Option>>, - ) -> HashMap - where - K: Clone + Hash + PartialEq + 'static, - { + comparer: LrcPtr>, + ) -> HashMap { let it = iter.map(|(k, v)| { let key = HashKey::new(k, comparer.clone()); (key, v) @@ -70,17 +71,23 @@ pub mod HashMap_ { map.iter().map(|(k, v)| (k.key.clone(), v.clone())) } - pub fn new_empty() -> HashMap { + pub fn new_empty() -> HashMap + where + K: Clone + Hash + PartialEq + 'static, + { HashMap { hash_map: mkRefMut(collections::HashMap::new()), - comparer: None, + comparer: EqualityComparer_1::::get_Default(), } } - pub fn new_with_capacity(capacity: i32) -> HashMap { + pub fn new_with_capacity(capacity: i32) -> HashMap + where + K: Clone + Hash + PartialEq + 'static, + { HashMap { hash_map: mkRefMut(collections::HashMap::with_capacity(capacity as usize)), - comparer: None, + comparer: EqualityComparer_1::::get_Default(), } } @@ -89,7 +96,7 @@ pub mod HashMap_ { ) -> HashMap { HashMap { hash_map: mkRefMut(collections::HashMap::new()), - comparer: Some(comparer), + comparer, } } @@ -99,7 +106,7 @@ pub mod HashMap_ { ) -> HashMap { HashMap { hash_map: mkRefMut(collections::HashMap::with_capacity(capacity as usize)), - comparer: Some(comparer), + comparer, } } @@ -107,34 +114,25 @@ pub mod HashMap_ { where K: Clone + Hash + PartialEq + 'static, { - from_iter(seq_to_iter(&seq), None) + from_iter(seq_to_iter(&seq), EqualityComparer_1::::get_Default()) } - pub fn new_from_enumerable_comparer( + pub fn new_from_enumerable_comparer( seq: Seq<(K, V)>, comparer: LrcPtr>, - ) -> HashMap - where - K: Clone + Hash + PartialEq + 'static, - { - from_iter(seq_to_iter(&seq), Some(comparer)) + ) -> HashMap { + from_iter(seq_to_iter(&seq), comparer) } - pub fn new_from_dictionary(map: HashMap) -> HashMap - where - K: Clone + Hash + PartialEq + 'static, - { - from_iter(to_iter(&map), None) + pub fn new_from_dictionary(map: HashMap) -> HashMap { + from_iter(to_iter(&map), map.comparer.clone()) } - pub fn new_from_dictionary_comparer( + pub fn new_from_dictionary_comparer( map: HashMap, comparer: LrcPtr>, - ) -> HashMap - where - K: Clone + Hash + PartialEq + 'static, - { - from_iter(to_iter(&map), Some(comparer)) + ) -> HashMap { + from_iter(to_iter(&map), comparer) } pub fn new_from_tuple_array(a: Array>) -> HashMap @@ -142,7 +140,7 @@ pub mod HashMap_ { K: Clone + Hash + PartialEq + 'static, { let it = a.iter().map(|tup| tup.as_ref().clone()); - from_iter(it, None) + from_iter(it, EqualityComparer_1::::get_Default()) } pub fn isReadOnly(map: HashMap) -> bool { @@ -153,10 +151,7 @@ pub mod HashMap_ { map.len() as i32 } - pub fn containsKey(map: HashMap, k: K) -> bool - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn containsKey(map: HashMap, k: K) -> bool { let key = HashKey::new(k, map.comparer.clone()); map.contains_key(&key) } @@ -165,10 +160,7 @@ pub mod HashMap_ { map.values().any(|x| x.eq(&v)) } - pub fn tryAdd(map: HashMap, k: K, v: V) -> bool - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn tryAdd(map: HashMap, k: K, v: V) -> bool { let key = HashKey::new(k, map.comparer.clone()); // map.get_mut().try_insert(key, v).is_ok() // nightly only if map.contains_key(&key) { @@ -178,10 +170,7 @@ pub mod HashMap_ { } } - pub fn add(map: HashMap, k: K, v: V) - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn add(map: HashMap, k: K, v: V) { let key = HashKey::new(k, map.comparer.clone()); match map.get_mut().insert(key, v) { Some(v) => { @@ -191,10 +180,7 @@ pub mod HashMap_ { } } - pub fn remove(map: HashMap, k: K) -> bool - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn remove(map: HashMap, k: K) -> bool { let key = HashKey::new(k, map.comparer.clone()); map.get_mut().remove(&key).is_some() } @@ -203,10 +189,7 @@ pub mod HashMap_ { map.get_mut().clear(); } - pub fn get(map: HashMap, k: K) -> V - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn get(map: HashMap, k: K) -> V { let key = HashKey::new(k, map.comparer.clone()); match map.get_mut().get(&key) { Some(v) => v.clone(), @@ -216,18 +199,16 @@ pub mod HashMap_ { } } - pub fn set(map: HashMap, k: K, v: V) - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn set(map: HashMap, k: K, v: V) { let key = HashKey::new(k, map.comparer.clone()); map.get_mut().insert(key, v); // ignore return value } - pub fn tryGetValue(map: HashMap, k: K, res: &MutCell) -> bool - where - K: Clone + Hash + PartialEq + 'static, - { + pub fn tryGetValue( + map: HashMap, + k: K, + res: &MutCell, + ) -> bool { let key = HashKey::new(k, map.comparer.clone()); match map.get_mut().get(&key) { Some(v) => { diff --git a/src/fable-library-rust/src/HashSet.rs b/src/fable-library-rust/src/HashSet.rs index d35b3f8116..7abd807e3f 100644 --- a/src/fable-library-rust/src/HashSet.rs +++ b/src/fable-library-rust/src/HashSet.rs @@ -9,9 +9,10 @@ pub mod HashSet_ { #[cfg(not(feature = "no_std"))] use std::collections; - use crate::System::Collections::Generic::IEqualityComparer_1; 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::System::Collections::Generic::IEqualityComparer_1; use core::fmt::{Debug, Display, Formatter, Result}; use core::hash::Hash; @@ -21,10 +22,13 @@ pub mod HashSet_ { #[derive(Clone)] //, Debug, Default, PartialEq, PartialOrd, Eq, Hash, Ord)] pub struct HashSet { hash_set: Lrc>, - comparer: Option>>, + comparer: LrcPtr>, } - impl Default for HashSet { + impl Default for HashSet + where + T: Clone + Hash + PartialEq + 'static, + { fn default() -> HashSet { new_empty() } @@ -49,17 +53,14 @@ pub mod HashSet_ { } } - fn from_iter>( + fn from_iter>( iter: I, - comparer: Option>>, - ) -> HashSet - where - T: Clone + Hash + PartialEq + 'static, - { + comparer: LrcPtr>, + ) -> HashSet { let it = iter.map(|v| HashKey::new(v, comparer.clone())); HashSet { hash_set: mkRefMut(collections::HashSet::from_iter(it)), - comparer: comparer.clone(), + comparer, } } @@ -67,24 +68,30 @@ pub mod HashSet_ { set.iter().map(|k| k.key.clone()) } - pub fn new_empty() -> HashSet { + pub fn new_empty() -> HashSet + where + T: Clone + Hash + PartialEq + 'static, + { HashSet { hash_set: mkRefMut(collections::HashSet::new()), - comparer: None, + comparer: EqualityComparer_1::::get_Default(), } } - pub fn new_with_capacity(capacity: i32) -> HashSet { + pub fn new_with_capacity(capacity: i32) -> HashSet + where + T: Clone + Hash + PartialEq + 'static, + { HashSet { hash_set: mkRefMut(collections::HashSet::with_capacity(capacity as usize)), - comparer: None, + comparer: EqualityComparer_1::::get_Default(), } } pub fn new_with_comparer(comparer: LrcPtr>) -> HashSet { HashSet { hash_set: mkRefMut(collections::HashSet::new()), - comparer: Some(comparer), + comparer, } } @@ -94,7 +101,7 @@ pub mod HashSet_ { ) -> HashSet { HashSet { hash_set: mkRefMut(collections::HashSet::with_capacity(capacity as usize)), - comparer: Some(comparer), + comparer, } } @@ -102,17 +109,14 @@ pub mod HashSet_ { where T: Clone + Hash + PartialEq + 'static, { - from_iter(seq_to_iter(&seq), None) + from_iter(seq_to_iter(&seq), EqualityComparer_1::::get_Default()) } - pub fn new_from_enumerable_comparer( + pub fn new_from_enumerable_comparer( seq: Seq, comparer: LrcPtr>, - ) -> HashSet - where - T: Clone + Hash + PartialEq + 'static, - { - from_iter(seq_to_iter(&seq), Some(comparer)) + ) -> HashSet { + from_iter(seq_to_iter(&seq), comparer) } pub fn isReadOnly(set: HashSet) -> bool { @@ -123,26 +127,17 @@ pub mod HashSet_ { set.len() as i32 } - pub fn contains(set: HashSet, v: T) -> bool - where - T: Clone + Hash + PartialEq + 'static, - { + pub fn contains(set: HashSet, v: T) -> bool { let key = HashKey::new(v, set.comparer.clone()); set.contains(&key) } - pub fn add(set: HashSet, v: T) -> bool - where - T: Clone + Hash + PartialEq + 'static, - { + pub fn add(set: HashSet, v: T) -> bool { let key = HashKey::new(v, set.comparer.clone()); set.get_mut().insert(key) } - pub fn remove(set: HashSet, v: T) -> bool - where - T: Clone + Hash + PartialEq + 'static, - { + pub fn remove(set: HashSet, v: T) -> bool { let key = HashKey::new(v, set.comparer.clone()); set.get_mut().remove(&key) } diff --git a/src/fable-library-rust/src/Native.rs b/src/fable-library-rust/src/Native.rs index 292fb2aed1..69c0668cef 100644 --- a/src/fable-library-rust/src/Native.rs +++ b/src/fable-library-rust/src/Native.rs @@ -156,11 +156,11 @@ pub mod Native_ { #[derive(Clone)] pub struct HashKey { pub key: T, - pub comparer: Option>>, + pub comparer: LrcPtr>, } impl HashKey { - pub fn new(key: T, comparer: Option>>) -> HashKey { + pub fn new(key: T, comparer: LrcPtr>) -> HashKey { HashKey { key, comparer } } } @@ -177,27 +177,21 @@ pub mod Native_ { } } - impl Hash for HashKey { + impl Hash for HashKey { #[inline] fn hash(&self, state: &mut H) { - match &self.comparer { - Some(comp) => comp.GetHashCode(self.key.clone()).hash(state), - None => self.key.hash(state), - } + self.comparer.GetHashCode(self.key.clone()).hash(state) } } - impl PartialEq for HashKey { + impl PartialEq for HashKey { #[inline] fn eq(&self, other: &Self) -> bool { - match &self.comparer { - Some(comp) => comp.Equals(self.key.clone(), other.key.clone()), - None => self.key.eq(&other.key), - } + self.comparer.Equals(self.key.clone(), other.key.clone()) } } - impl Eq for HashKey {} + impl Eq for HashKey {} // ----------------------------------------------------------- // Type testing diff --git a/src/fable-library-rust/src/System.Collections.Generic.fs b/src/fable-library-rust/src/System.Collections.Generic.fs index 34f0913066..d33fcedd58 100644 --- a/src/fable-library-rust/src/System.Collections.Generic.fs +++ b/src/fable-library-rust/src/System.Collections.Generic.fs @@ -2,9 +2,10 @@ namespace System.Collections.Generic open Global_ -type Comparer<'T when 'T: comparison>(comparison: 'T -> 'T -> int) = +type Comparer<'T>(comparison: 'T -> 'T -> int) = - static member Default = Comparer<'T>(LanguagePrimitives.GenericComparison) + static member get_Default<'V when 'V: comparison>() = + Comparer<'V>(LanguagePrimitives.GenericComparison) static member Create(comparison) = Comparer<'T>(comparison) @@ -13,10 +14,10 @@ type Comparer<'T when 'T: comparison>(comparison: 'T -> 'T -> int) = interface IComparer<'T> with member _.Compare(x, y) = comparison x y -type EqualityComparer<'T when 'T: equality>(equals: 'T -> 'T -> bool, getHashCode: 'T -> int) = +type EqualityComparer<'T>(equals: 'T -> 'T -> bool, getHashCode: 'T -> int) = - static member Default = - EqualityComparer<'T>(LanguagePrimitives.GenericEquality, LanguagePrimitives.GenericHash) + static member get_Default<'V when 'V: equality>() = + EqualityComparer<'V>(LanguagePrimitives.GenericEquality, LanguagePrimitives.GenericHash) static member Create(equals, getHashCode) = EqualityComparer<'T>(equals, getHashCode)