Skip to content

Commit d14c13e

Browse files
committed
fix: [Rust] Fix float hashing
1 parent 3423b94 commit d14c13e

14 files changed

Lines changed: 478 additions & 72 deletions

File tree

src/Fable.Transforms/Rust/Fable2Rust.fs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ module TypeInfo =
579579
| Fable.Unit
580580
| Fable.Measure _
581581
| Fable.MetaType
582-
| Fable.Number((Float32 | Float64), _)
583582
| Fable.LambdaType _
584583
| Fable.DelegateType _ -> false
585584
| _ -> isTypeOfType com isHashableType isHashableEntity entNames typ
@@ -2323,7 +2322,7 @@ module Util =
23232322
exprField :: exprFields
23242323
| _ -> exprFields
23252324

2326-
let attrs = [ mkAttr "derive" (makeDerivedFrom com ent) ]
2325+
let attrs = [ mkAttr "derive" (makeDerivedFrom com ctx ent) ]
23272326
let generics = makeGenerics com ctx genArgs
23282327
let genParams = FSharp2Fable.Util.getGenParamTypes genArgs
23292328

@@ -4143,9 +4142,9 @@ module Util =
41434142
| Fable.Constraint.IsReferenceType -> [ makeImportBound com ctx "Native" "NullableRef" ]
41444143
| Fable.Constraint.HasDefaultConstructor -> []
41454144
| Fable.Constraint.HasAllowsRefStruct -> []
4146-
| Fable.Constraint.HasComparison -> [ makeRawBound "PartialOrd" ]
4147-
| Fable.Constraint.HasEquality ->
4148-
[ makeGenBound ("core" :: "hash" :: "Hash" :: []) []; makeRawBound "PartialEq" ]
4145+
| Fable.Constraint.HasComparison ->
4146+
[ makeImportBound com ctx "Native" "Hashable"; makeRawBound "PartialOrd" ]
4147+
| Fable.Constraint.HasEquality -> [ makeImportBound com ctx "Native" "Hashable"; makeRawBound "PartialEq" ]
41494148
| Fable.Constraint.IsUnmanaged -> []
41504149
| Fable.Constraint.IsDelegate _ -> []
41514150
| Fable.Constraint.IsEnum _ -> []
@@ -4532,7 +4531,7 @@ module Util =
45324531
let fnItem = mkFnAssocItem attrs name fnKind
45334532
fnItem
45344533

4535-
let makeDerivedFrom com (ent: Fable.Entity) =
4534+
let makeDerivedFrom com ctx (ent: Fable.Entity) =
45364535
let isCopyable = false //ent |> isCopyableEntity com Set.empty
45374536
let isCloneable = true //ent |> isCloneableEntity com Set.empty
45384537
let isPrintable = ent |> isPrintableEntity com Set.empty
@@ -4552,7 +4551,7 @@ module Util =
45524551
if isDefaultable then
45534552
rawIdent "Default"
45544553
if isHashable then
4555-
rawIdent "Hash"
4554+
getLibraryImportName com ctx "Native" "Hashable"
45564555
if isEquatable then
45574556
rawIdent "PartialEq"
45584557
if isComparable then
@@ -4601,7 +4600,7 @@ module Util =
46014600
)
46024601

46034602
let attrs = transformAttributes com ctx ent.Attributes decl.XmlDoc
4604-
let attrs = attrs @ [ mkAttr "derive" (makeDerivedFrom com ent) ]
4603+
let attrs = attrs @ [ mkAttr "derive" (makeDerivedFrom com ctx ent) ]
46054604
let enumItem = mkEnumItem attrs entName variants generics
46064605
enumItem
46074606

@@ -4641,7 +4640,7 @@ module Util =
46414640
let fields = List.append fields phantomFields
46424641

46434642
let attrs = transformAttributes com ctx ent.Attributes decl.XmlDoc
4644-
let attrs = attrs @ [ mkAttr "derive" (makeDerivedFrom com ent) ]
4643+
let attrs = attrs @ [ mkAttr "derive" (makeDerivedFrom com ctx ent) ]
46454644
let structItem = mkStructItem attrs entName fields generics
46464645
structItem
46474646

src/Fable.Transforms/Rust/Replacements.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,13 @@ let referenceHash (com: ICompiler) ctx r (arg: Expr) =
445445
| Boolean
446446
| Char
447447
| String
448-
| Number _ -> Helper.LibCall(com, "Native", "getHashCode", Int32.Number, [ arg ], ?loc = r)
448+
| Number _ -> Helper.InstanceCall(arg, "getHashCode", Int32.Number, [], [], [], ?loc = r)
449449
| _ -> Helper.LibCall(com, "Native", "referenceHash", Int32.Number, [ makeRef arg ], ?loc = r)
450450

451451
let getHashCode (com: ICompiler) ctx r (arg: Expr) =
452452
match arg.Type with
453453
| HasReferenceEquality com _ -> referenceHash com ctx r arg
454-
| _ -> Helper.LibCall(com, "Native", "getHashCode", Int32.Number, [ arg ], ?loc = r)
454+
| _ -> Helper.InstanceCall(arg, "getHashCode", Int32.Number, [], [], [], ?loc = r)
455455

456456
let objectHash (com: ICompiler) ctx r (arg: Expr) =
457457
match arg.Type with

src/fable-library-rust/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ default = ["bigint", "datetime", "decimal", "enum_func", "enum_string", "guid",
2323
chrono = { version = "0.4", optional = true }
2424
futures = { version = "0.3", features = ["executor", "thread-pool"], default-features = false, optional = true }
2525
futures-timer = { version = "3.0", optional = true }
26+
hashable = { version = "0.1", path = "vendored/hashable" }
2627
hashbrown = { version = "0.17", optional = true }
2728
num-bigint = { version = "0.4", optional = true }
2829
num-integer = { version = "0.1", optional = true }
2930
num-traits = { version = "0.2", optional = true }
3031
rand = { version = "0.10", features = ["std_rng"], default-features = false, optional = true }
3132
regex = { version = "1.12", optional = true }
32-
rust_decimal = { version = "1.41", features = ["maths"], default-features = false, optional = true }
33+
rust_decimal = { version = "1.42", features = ["maths"], default-features = false, optional = true }
3334
startup = { version = "0.1", path = "vendored/startup", optional = true }
3435

3536
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

src/fable-library-rust/src/DateOnly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub mod DateOnly_ {
1010
use chrono::{DateTime as CDateTime, Datelike, Months, NaiveDate, NaiveTime, ParseResult};
1111

1212
#[repr(transparent)]
13-
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
13+
#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd)]
1414
pub struct DateOnly(NaiveDate);
1515

1616
impl core::fmt::Display for DateOnly {

src/fable-library-rust/src/Decimal.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ pub mod Decimal_ {
1414
pub const MaxValue: decimal = Decimal::MAX;
1515
pub const MinValue: decimal = Decimal::MIN;
1616

17-
// pub fn getHashCode(x: decimal) = x.GetHashCode()
1817
pub fn equals(x: decimal, y: decimal) -> bool { x.eq(&y) }
1918
pub fn compareTo(x: decimal, y: decimal) -> i32 { compare(&x, &y) }
2019

src/fable-library-rust/src/HashMap.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub mod HashMap_ {
1111

1212
use crate::NativeArray_::{array_from, Array};
1313
use crate::Native_::{default_eq_comparer, seq_to_iter};
14-
use crate::Native_::{HashKey, LrcPtr, MutCell, Seq, Vec};
14+
use crate::Native_::{HashKey, Hashable, LrcPtr, MutCell, Seq, Vec};
1515
use crate::System::Collections::Generic::IEqualityComparer_1;
1616

1717
use core::fmt::{Debug, Display, Formatter, Result};
@@ -71,14 +71,14 @@ pub mod HashMap_ {
7171

7272
pub fn new_empty<K, V: Clone>() -> HashMap<K, V>
7373
where
74-
K: Clone + Hash + PartialEq + 'static,
74+
K: Clone + Hashable + PartialEq + 'static,
7575
{
7676
make_hash_map(collections::HashMap::new(), default_eq_comparer::<K>())
7777
}
7878

7979
pub fn new_with_capacity<K, V: Clone>(capacity: i32) -> HashMap<K, V>
8080
where
81-
K: Clone + Hash + PartialEq + 'static,
81+
K: Clone + Hashable + PartialEq + 'static,
8282
{
8383
make_hash_map(
8484
collections::HashMap::with_capacity(capacity as usize),
@@ -104,7 +104,7 @@ pub mod HashMap_ {
104104

105105
pub fn new_from_enumerable<K, V: Clone + 'static>(seq: Seq<(K, V)>) -> HashMap<K, V>
106106
where
107-
K: Clone + Hash + PartialEq + 'static,
107+
K: Clone + Hashable + PartialEq + 'static,
108108
{
109109
from_iter(seq_to_iter(seq), default_eq_comparer::<K>())
110110
}
@@ -129,7 +129,7 @@ pub mod HashMap_ {
129129

130130
pub fn new_from_tuple_array<K, V: Clone>(a: Array<LrcPtr<(K, V)>>) -> HashMap<K, V>
131131
where
132-
K: Clone + Hash + PartialEq + 'static,
132+
K: Clone + Hashable + PartialEq + 'static,
133133
{
134134
let it = a.iter().map(|tup| tup.as_ref().clone());
135135
from_iter(it, default_eq_comparer::<K>())

src/fable-library-rust/src/HashSet.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub mod HashSet_ {
1212
use crate::Global_::SR::indexOutOfBounds;
1313
use crate::NativeArray_::{array_from, Array};
1414
use crate::Native_::{default_eq_comparer, seq_to_iter};
15-
use crate::Native_::{HashKey, LrcPtr, MutCell, Seq, Vec};
15+
use crate::Native_::{HashKey, Hashable, LrcPtr, MutCell, Seq, Vec};
1616
use crate::System::Collections::Generic::IEqualityComparer_1;
1717

1818
use core::fmt::{Debug, Display, Formatter, Result};
@@ -78,14 +78,14 @@ pub mod HashSet_ {
7878

7979
pub fn new_empty<T>() -> HashSet<T>
8080
where
81-
T: Clone + Hash + PartialEq + 'static,
81+
T: Clone + Hashable + PartialEq + 'static,
8282
{
8383
make_hash_set(collections::HashSet::new(), default_eq_comparer::<T>())
8484
}
8585

8686
pub fn new_with_capacity<T>(capacity: i32) -> HashSet<T>
8787
where
88-
T: Clone + Hash + PartialEq + 'static,
88+
T: Clone + Hashable + PartialEq + 'static,
8989
{
9090
make_hash_set(
9191
collections::HashSet::with_capacity(capacity as usize),
@@ -109,7 +109,7 @@ pub mod HashSet_ {
109109

110110
pub fn new_from_enumerable<T>(seq: Seq<T>) -> HashSet<T>
111111
where
112-
T: Clone + Hash + PartialEq + 'static,
112+
T: Clone + Hashable + PartialEq + 'static,
113113
{
114114
from_iter(seq_to_iter(seq), default_eq_comparer::<T>())
115115
}
@@ -204,7 +204,7 @@ pub mod HashSet_ {
204204
if destIndex < 0 || count < 0 || count > set_len || destIndex + count > dest_len {
205205
panic!("{}", indexOutOfBounds());
206206
}
207-
let mut dest = dest.get_mut();
207+
let dest = dest.get_mut();
208208
let it = to_iter(&set).take(count as usize);
209209
for (offset, item) in it.enumerate() {
210210
dest[destIndex as usize + offset] = item;

src/fable-library-rust/src/Interop.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod ListExt {
22
// use core::ops::Deref;
3-
use crate::List_::{cons, empty, isEmpty, reverse, List};
4-
use crate::Native_::{seq_to_iter, NullableRef, Vec};
3+
use crate::List_::{List, cons, empty, isEmpty, reverse};
4+
use crate::Native_::{NullableRef, Vec, seq_to_iter};
55
use crate::Seq_::ofList;
66

77
impl<T: Clone> List<T> {
@@ -75,12 +75,12 @@ pub mod ListExt {
7575
}
7676

7777
pub mod SetExt {
78-
use crate::Native_::{make_compare, seq_to_iter, Func2, NullableRef, Vec};
79-
use crate::Set_::{add, compareTo, empty, equals, isEmpty, toSeq, Set};
78+
use crate::Native_::{Func2, Hashable, NullableRef, Vec, make_compare, seq_to_iter};
79+
use crate::Set_::{Set, add, compareTo, empty, equals, isEmpty, toSeq};
8080
use core::cmp::Ordering;
8181
use core::hash::{Hash, Hasher};
8282

83-
impl<T: Clone + PartialOrd> Set<T> {
83+
impl<T: Clone + Hashable + PartialOrd> Set<T> {
8484
//todo - non-consuming iter by ref
8585
// pub fn iter<'a>(&self) -> impl Iterator<Item = & 'a T> {
8686
// let s = toSeq(self.clone());
@@ -105,34 +105,34 @@ pub mod SetExt {
105105
}
106106
}
107107

108-
impl<T: Clone + PartialOrd> PartialEq for Set<T> {
108+
impl<T: Clone + Hashable + PartialOrd> PartialEq for Set<T> {
109109
fn eq(&self, other: &Self) -> bool {
110110
equals(self.clone(), other.clone())
111111
}
112112
}
113113

114-
impl<T: Clone + PartialOrd> Eq for Set<T> {}
114+
impl<T: Clone + Hashable + PartialOrd> Eq for Set<T> {}
115115

116-
impl<T: Clone + PartialOrd + Hash> Hash for Set<T> {
116+
impl<T: Clone + Hashable + PartialOrd + Hash> Hash for Set<T> {
117117
fn hash<H: Hasher>(&self, state: &mut H) {
118118
let s = toSeq(self.clone());
119119
seq_to_iter(s).for_each(|x| x.hash(state))
120120
}
121121
}
122122

123-
impl<T: Clone + PartialOrd> PartialOrd for Set<T> {
123+
impl<T: Clone + Hashable + PartialOrd> PartialOrd for Set<T> {
124124
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
125125
Some(make_compare(Func2::from(compareTo))(self, other))
126126
}
127127
}
128128

129-
impl<T: Clone + PartialOrd> Ord for Set<T> {
129+
impl<T: Clone + Hashable + PartialOrd> Ord for Set<T> {
130130
fn cmp(&self, other: &Self) -> Ordering {
131131
make_compare(Func2::from(compareTo))(self, other)
132132
}
133133
}
134134

135-
impl<T: Clone + PartialOrd> From<Vec<T>> for Set<T> {
135+
impl<T: Clone + Hashable + PartialOrd> From<Vec<T>> for Set<T> {
136136
fn from(vec: Vec<T>) -> Self {
137137
let mut set = empty();
138138
for v in vec.iter() {
@@ -142,7 +142,7 @@ pub mod SetExt {
142142
}
143143
}
144144

145-
impl<T: Clone + PartialOrd> From<&Vec<T>> for Set<T> {
145+
impl<T: Clone + Hashable + PartialOrd> From<&Vec<T>> for Set<T> {
146146
fn from(vec: &Vec<T>) -> Self {
147147
let mut set = empty();
148148
for v in vec.iter() {
@@ -152,7 +152,7 @@ pub mod SetExt {
152152
}
153153
}
154154

155-
impl<T: Clone + PartialOrd> FromIterator<T> for Set<T> {
155+
impl<T: Clone + Hashable + PartialOrd> FromIterator<T> for Set<T> {
156156
fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
157157
let mut set = empty();
158158
for v in iter.into_iter() {
@@ -162,20 +162,20 @@ pub mod SetExt {
162162
}
163163
}
164164

165-
impl<T: Clone + PartialOrd> Into<Vec<T>> for Set<T> {
165+
impl<T: Clone + Hashable + PartialOrd> Into<Vec<T>> for Set<T> {
166166
fn into(self) -> Vec<T> {
167167
self.into_iter().collect()
168168
}
169169
}
170170
}
171171

172172
pub mod MapExt {
173-
use crate::Map_::{add, compareTo, empty, equals, isEmpty, iterate, toSeq, Map};
174-
use crate::Native_::{make_compare, seq_to_iter, Func2, NullableRef, Vec};
173+
use crate::Map_::{Map, add, compareTo, empty, equals, isEmpty, iterate, toSeq};
174+
use crate::Native_::{Func2, Hashable, NullableRef, Vec, make_compare, seq_to_iter};
175175
use core::cmp::Ordering;
176176
use core::hash::{Hash, Hasher};
177177

178-
impl<K: Clone + PartialOrd, V: Clone> Map<K, V> {
178+
impl<K: Clone + Hashable + PartialOrd, V: Clone> Map<K, V> {
179179
//todo - non-consuming iter by ref
180180
// pub fn iter<'a>(&self) -> impl Iterator<Item = (& 'a K, & 'a V)> {
181181
// let s = toSeq(self.clone());
@@ -188,7 +188,7 @@ pub mod MapExt {
188188
}
189189
}
190190

191-
impl<K: Clone + PartialOrd, V: Clone> NullableRef for Map<K, V> {
191+
impl<K: Clone + Hashable + PartialOrd, V: Clone> NullableRef for Map<K, V> {
192192
#[inline]
193193
fn null() -> Self {
194194
empty()
@@ -200,34 +200,34 @@ pub mod MapExt {
200200
}
201201
}
202202

203-
impl<K: Clone + PartialOrd, V: Clone + PartialOrd> PartialEq for Map<K, V> {
203+
impl<K: Clone + Hashable + PartialOrd, V: Clone + Hashable + PartialOrd> PartialEq for Map<K, V> {
204204
fn eq(&self, other: &Self) -> bool {
205205
equals(self.clone(), other.clone())
206206
}
207207
}
208208

209-
impl<K: Clone + PartialOrd, V: Clone + PartialOrd> Eq for Map<K, V> {}
209+
impl<K: Clone + Hashable + PartialOrd, V: Clone + Hashable + PartialOrd> Eq for Map<K, V> {}
210210

211-
impl<K: Clone + PartialOrd + Hash, V: Clone + Hash> Hash for Map<K, V> {
211+
impl<K: Clone + Hashable + PartialOrd + Hash, V: Clone + Hash> Hash for Map<K, V> {
212212
fn hash<H: Hasher>(&self, state: &mut H) {
213213
let s = toSeq(self.clone());
214214
seq_to_iter(s).for_each(|kvp| kvp.hash(state))
215215
}
216216
}
217217

218-
impl<K: Clone + PartialOrd, V: Clone + PartialOrd> PartialOrd for Map<K, V> {
218+
impl<K: Clone + Hashable + PartialOrd, V: Clone + Hashable + PartialOrd> PartialOrd for Map<K, V> {
219219
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
220220
Some(make_compare(Func2::from(compareTo))(self, other))
221221
}
222222
}
223223

224-
impl<K: Clone + PartialOrd, V: Clone + PartialOrd> Ord for Map<K, V> {
224+
impl<K: Clone + Hashable + PartialOrd, V: Clone + Hashable + PartialOrd> Ord for Map<K, V> {
225225
fn cmp(&self, other: &Self) -> Ordering {
226226
make_compare(Func2::from(compareTo))(self, other)
227227
}
228228
}
229229

230-
impl<K: Clone + PartialOrd, V: Clone> From<&Vec<(K, V)>> for Map<K, V> {
230+
impl<K: Clone + Hashable + PartialOrd, V: Clone> From<&Vec<(K, V)>> for Map<K, V> {
231231
fn from(vec: &Vec<(K, V)>) -> Self {
232232
let mut map: Map<K, V> = empty();
233233
for (i, (k, v)) in vec.iter().rev().enumerate() {
@@ -237,7 +237,7 @@ pub mod MapExt {
237237
}
238238
}
239239

240-
impl<K: Clone + PartialOrd, V: Clone> FromIterator<(K, V)> for Map<K, V> {
240+
impl<K: Clone + Hashable + PartialOrd, V: Clone> FromIterator<(K, V)> for Map<K, V> {
241241
fn from_iter<U: IntoIterator<Item = (K, V)>>(iter: U) -> Self {
242242
let mut map: Map<K, V> = empty();
243243
for (k, v) in iter.into_iter() {
@@ -247,7 +247,7 @@ pub mod MapExt {
247247
}
248248
}
249249

250-
impl<K: Clone + PartialOrd, V: Clone> Into<Vec<(K, V)>> for Map<K, V> {
250+
impl<K: Clone + Hashable + PartialOrd, V: Clone> Into<Vec<(K, V)>> for Map<K, V> {
251251
fn into(self) -> Vec<(K, V)> {
252252
self.into_iter().collect()
253253
}

0 commit comments

Comments
 (0)