Skip to content

Commit

Permalink
[Rust] Relaxed type constraints on Dictionary and HashSet (#3899)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave authored Sep 26, 2024
1 parent 49552d1 commit 3e1f4c8
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 125 deletions.
10 changes: 6 additions & 4 deletions src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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

[<AutoOpen>]
module Patterns =

Expand Down
18 changes: 12 additions & 6 deletions src/Fable.Transforms/Rust/Fable2Rust.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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 -> []
Expand Down
105 changes: 43 additions & 62 deletions src/fable-library-rust/src/HashMap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -21,10 +22,13 @@ pub mod HashMap_ {
#[derive(Clone)] //, Debug, Default, PartialEq, PartialOrd, Eq, Hash, Ord)]
pub struct HashMap<K: Clone, V: Clone> {
hash_map: Lrc<MutHashMap<K, V>>,
comparer: Option<LrcPtr<dyn IEqualityComparer_1<K>>>,
comparer: LrcPtr<dyn IEqualityComparer_1<K>>,
}

impl<K: Clone, V: Clone> Default for HashMap<K, V> {
impl<K, V: Clone> Default for HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
fn default() -> HashMap<K, V> {
new_empty()
}
Expand All @@ -49,13 +53,10 @@ pub mod HashMap_ {
}
}

fn from_iter<K, V: Clone, I: Iterator<Item = (K, V)>>(
fn from_iter<K: Clone + 'static, V: Clone, I: Iterator<Item = (K, V)>>(
iter: I,
comparer: Option<LrcPtr<dyn IEqualityComparer_1<K>>>,
) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
comparer: LrcPtr<dyn IEqualityComparer_1<K>>,
) -> HashMap<K, V> {
let it = iter.map(|(k, v)| {
let key = HashKey::new(k, comparer.clone());
(key, v)
Expand All @@ -70,17 +71,23 @@ pub mod HashMap_ {
map.iter().map(|(k, v)| (k.key.clone(), v.clone()))
}

pub fn new_empty<K: Clone, V: Clone>() -> HashMap<K, V> {
pub fn new_empty<K, V: Clone>() -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
HashMap {
hash_map: mkRefMut(collections::HashMap::new()),
comparer: None,
comparer: EqualityComparer_1::<K>::get_Default(),
}
}

pub fn new_with_capacity<K: Clone, V: Clone>(capacity: i32) -> HashMap<K, V> {
pub fn new_with_capacity<K, V: Clone>(capacity: i32) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
HashMap {
hash_map: mkRefMut(collections::HashMap::with_capacity(capacity as usize)),
comparer: None,
comparer: EqualityComparer_1::<K>::get_Default(),
}
}

Expand All @@ -89,7 +96,7 @@ pub mod HashMap_ {
) -> HashMap<K, V> {
HashMap {
hash_map: mkRefMut(collections::HashMap::new()),
comparer: Some(comparer),
comparer,
}
}

Expand All @@ -99,50 +106,41 @@ pub mod HashMap_ {
) -> HashMap<K, V> {
HashMap {
hash_map: mkRefMut(collections::HashMap::with_capacity(capacity as usize)),
comparer: Some(comparer),
comparer,
}
}

pub fn new_from_enumerable<K, V: Clone + 'static>(seq: Seq<(K, V)>) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
from_iter(seq_to_iter(&seq), None)
from_iter(seq_to_iter(&seq), EqualityComparer_1::<K>::get_Default())
}

pub fn new_from_enumerable_comparer<K, V: Clone + 'static>(
pub fn new_from_enumerable_comparer<K: Clone + 'static, V: Clone + 'static>(
seq: Seq<(K, V)>,
comparer: LrcPtr<dyn IEqualityComparer_1<K>>,
) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
from_iter(seq_to_iter(&seq), Some(comparer))
) -> HashMap<K, V> {
from_iter(seq_to_iter(&seq), comparer)
}

pub fn new_from_dictionary<K, V: Clone + 'static>(map: HashMap<K, V>) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
from_iter(to_iter(&map), None)
pub fn new_from_dictionary<K: Clone + 'static, V: Clone>(map: HashMap<K, V>) -> HashMap<K, V> {
from_iter(to_iter(&map), map.comparer.clone())
}

pub fn new_from_dictionary_comparer<K, V: Clone + 'static>(
pub fn new_from_dictionary_comparer<K: Clone + 'static, V: Clone>(
map: HashMap<K, V>,
comparer: LrcPtr<dyn IEqualityComparer_1<K>>,
) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
from_iter(to_iter(&map), Some(comparer))
) -> HashMap<K, V> {
from_iter(to_iter(&map), comparer)
}

pub fn new_from_tuple_array<K, V: Clone>(a: Array<LrcPtr<(K, V)>>) -> HashMap<K, V>
where
K: Clone + Hash + PartialEq + 'static,
{
let it = a.iter().map(|tup| tup.as_ref().clone());
from_iter(it, None)
from_iter(it, EqualityComparer_1::<K>::get_Default())
}

pub fn isReadOnly<K: Clone, V: Clone>(map: HashMap<K, V>) -> bool {
Expand All @@ -153,10 +151,7 @@ pub mod HashMap_ {
map.len() as i32
}

pub fn containsKey<K, V: Clone>(map: HashMap<K, V>, k: K) -> bool
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn containsKey<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, k: K) -> bool {
let key = HashKey::new(k, map.comparer.clone());
map.contains_key(&key)
}
Expand All @@ -165,10 +160,7 @@ pub mod HashMap_ {
map.values().any(|x| x.eq(&v))
}

pub fn tryAdd<K, V: Clone>(map: HashMap<K, V>, k: K, v: V) -> bool
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn tryAdd<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, 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) {
Expand All @@ -178,10 +170,7 @@ pub mod HashMap_ {
}
}

pub fn add<K, V: Clone>(map: HashMap<K, V>, k: K, v: V)
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn add<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, k: K, v: V) {
let key = HashKey::new(k, map.comparer.clone());
match map.get_mut().insert(key, v) {
Some(v) => {
Expand All @@ -191,10 +180,7 @@ pub mod HashMap_ {
}
}

pub fn remove<K, V: Clone>(map: HashMap<K, V>, k: K) -> bool
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn remove<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, k: K) -> bool {
let key = HashKey::new(k, map.comparer.clone());
map.get_mut().remove(&key).is_some()
}
Expand All @@ -203,10 +189,7 @@ pub mod HashMap_ {
map.get_mut().clear();
}

pub fn get<K, V: Clone>(map: HashMap<K, V>, k: K) -> V
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn get<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, k: K) -> V {
let key = HashKey::new(k, map.comparer.clone());
match map.get_mut().get(&key) {
Some(v) => v.clone(),
Expand All @@ -216,18 +199,16 @@ pub mod HashMap_ {
}
}

pub fn set<K, V: Clone>(map: HashMap<K, V>, k: K, v: V)
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn set<K: Clone + 'static, V: Clone>(map: HashMap<K, V>, k: K, v: V) {
let key = HashKey::new(k, map.comparer.clone());
map.get_mut().insert(key, v); // ignore return value
}

pub fn tryGetValue<K, V: Clone>(map: HashMap<K, V>, k: K, res: &MutCell<V>) -> bool
where
K: Clone + Hash + PartialEq + 'static,
{
pub fn tryGetValue<K: Clone + 'static, V: Clone>(
map: HashMap<K, V>,
k: K,
res: &MutCell<V>,
) -> bool {
let key = HashKey::new(k, map.comparer.clone());
match map.get_mut().get(&key) {
Some(v) => {
Expand Down
Loading

0 comments on commit 3e1f4c8

Please sign in to comment.