Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rust] Relaxed type constraints on Dictionary and HashSet #3899

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading