From 2986355c8cc002146bf0a482a154daf166e384a8 Mon Sep 17 00:00:00 2001 From: ncave <777696+ncave@users.noreply.github.com> Date: Fri, 16 Sep 2022 18:13:16 -0700 Subject: [PATCH] [TypeScript] Some interface annotations --- src/Fable.Transforms/Dart/Replacements.fs | 6 +- src/Fable.Transforms/FSharp2Fable.Util.fs | 4 +- src/Fable.Transforms/Fable2Babel.fs | 74 +++++++++++---- src/Fable.Transforms/Python/Fable2Python.fs | 4 +- src/Fable.Transforms/Python/Replacements.fs | 5 +- src/Fable.Transforms/Replacements.Util.fs | 4 +- src/Fable.Transforms/Replacements.fs | 4 +- src/Fable.Transforms/ReplacementsInject.fs | 96 ++++++++++---------- src/Fable.Transforms/Rust/Fable2Rust.fs | 77 ++++++++-------- src/Fable.Transforms/Rust/Replacements.fs | 2 +- src/Fable.Transforms/Transforms.Util.fs | 5 +- src/fable-library/Array.fs | 4 +- src/fable-library/BigInt/z.fs | 2 +- src/fable-library/Global.fs | 2 +- src/fable-library/List.fs | 16 ++-- src/fable-library/Map.fs | 2 +- src/fable-library/MutableMap.fs | 2 +- src/fable-library/MutableSet.fs | 2 +- src/fable-library/Seq.fs | 8 +- src/fable-library/Set.fs | 2 +- src/fable-library/Types.ts | 4 +- src/fable-library/Util.ts | 51 ++++++----- src/tools/InjectProcessor/InjectProcessor.fs | 4 +- 23 files changed, 212 insertions(+), 168 deletions(-) diff --git a/src/Fable.Transforms/Dart/Replacements.fs b/src/Fable.Transforms/Dart/Replacements.fs index 3d588cada6..41a1a3547c 100644 --- a/src/Fable.Transforms/Dart/Replacements.fs +++ b/src/Fable.Transforms/Dart/Replacements.fs @@ -554,9 +554,9 @@ let injectArg (com: ICompiler) (ctx: Context) r moduleName methName (genArgs: Ty List.tryItem injectGenArgIndex genArgs |> Option.bind (fun genArg -> match injectType with - | Types.comparer -> + | Types.icomparerGeneric -> args @ [makeComparer com ctx genArg] |> Some - | Types.equalityComparerGeneric -> + | Types.iequalityComparerGeneric -> args @ [makeEqualityComparer com ctx genArg] |> Some | Types.adder -> args @ [makeGenericAdder com ctx genArg] |> Some @@ -604,7 +604,7 @@ let tryReplacedEntityRef (com: Compiler) entFullName = | Naming.EndsWith "Enumerator" _ -> makeIdentExpr "Iterator" |> Some | Types.icomparable | Types.icomparableGeneric -> makeIdentExpr "Comparable" |> Some - | Types.idisposable | Types.adder | Types.averager | Types.comparer | Types.equalityComparerGeneric -> + | Types.idisposable | Types.adder | Types.averager | Types.icomparerGeneric | Types.iequalityComparerGeneric -> let entFullName = entFullName[entFullName.LastIndexOf(".") + 1..] let entFullName = match entFullName.IndexOf("`") with diff --git a/src/Fable.Transforms/FSharp2Fable.Util.fs b/src/Fable.Transforms/FSharp2Fable.Util.fs index a0f223a8c1..aa0d6ed687 100644 --- a/src/Fable.Transforms/FSharp2Fable.Util.fs +++ b/src/Fable.Transforms/FSharp2Fable.Util.fs @@ -2001,8 +2001,8 @@ module Util = | "System.IObserver`1" | Types.ienumerableGeneric // These are used for injections - | Types.comparer - | Types.equalityComparerGeneric -> false + | Types.icomparerGeneric + | Types.iequalityComparerGeneric -> false | Types.icomparable -> false | Types.icomparableGeneric -> com.Options.Language <> Dart | _ -> true diff --git a/src/Fable.Transforms/Fable2Babel.fs b/src/Fable.Transforms/Fable2Babel.fs index cfb9512db6..fa884f126c 100644 --- a/src/Fable.Transforms/Fable2Babel.fs +++ b/src/Fable.Transforms/Fable2Babel.fs @@ -409,13 +409,13 @@ module Annotation = | Fable.Tuple(genArgs,_) -> makeTupleTypeAnnotation com ctx genArgs | Fable.Array(genArg, kind) -> makeArrayTypeAnnotation com ctx genArg kind | Fable.List genArg -> makeListTypeAnnotation com ctx genArg - | Replacements.Util.Builtin kind -> makeBuiltinTypeAnnotation com ctx kind + | Fable.GenericParam(name=name) -> makeSimpleTypeAnnotation com ctx name | Fable.LambdaType(argType, returnType) -> ([argType], returnType) ||> FableTransforms.uncurryLambdaType ||> makeFunctionTypeAnnotation com ctx typ | Fable.DelegateType(argTypes, returnType) -> makeFunctionTypeAnnotation com ctx typ argTypes returnType - | Fable.GenericParam(name=name) -> makeSimpleTypeAnnotation com ctx name + | Replacements.Util.Builtin kind -> makeBuiltinTypeAnnotation com ctx kind | Fable.DeclaredType(ent, genArgs) -> makeEntityTypeAnnotation com ctx ent genArgs | Fable.AnonymousRecordType(fieldNames, genArgs, _isStruct) -> @@ -490,29 +490,67 @@ module Annotation = let makeFunctionTypeAnnotation com ctx _typ argTypes returnType = let funcTypeParams = - argTypes + match argTypes with + | [Fable.Unit] -> [] + | _ -> argTypes |> List.mapi (fun i argType -> FunctionTypeParam.functionTypeParam( Identifier.identifier("arg" + (string i)), typeAnnotation com ctx argType)) |> List.toArray + let ctx = { ctx with IsParamType = true }; let genParams = Util.getGenericTypeParams ctx (argTypes @ [returnType]) let returnType = typeAnnotation com ctx returnType let typeParamDecl = makeTypeParamDecl com ctx genParams TypeAnnotationInfo.functionTypeAnnotation(funcTypeParams, returnType, ?typeParameters=typeParamDecl) - let makeEntityTypeAnnotation com ctx (ent: Fable.EntityRef) genArgs = - match ent.FullName with - | Types.ienumerableGeneric -> - makeNativeTypeAnnotation com ctx genArgs "IterableIterator" + let makeInterfaceTypeAnnotation com ctx (entRef: Fable.EntityRef) genArgs = + match entRef.FullName with + | Types.icollection + -> makeImportTypeAnnotation com ctx [Fable.Any] "Util" "ICollection" + | Types.icollectionGeneric + -> makeImportTypeAnnotation com ctx genArgs "Util" "ICollection" + // | Types.idictionary + // | Types.ireadonlydictionary + | Types.idisposable + -> makeImportTypeAnnotation com ctx genArgs "Util" "IDisposable" + | Types.ienumerable + -> makeNativeTypeAnnotation com ctx [Fable.Any] "Iterable" + | Types.ienumerableGeneric + -> makeNativeTypeAnnotation com ctx genArgs "Iterable" + // -> makeImportTypeAnnotation com ctx genArgs "Util" "IEnumerable" + | Types.ienumerator + -> makeImportTypeAnnotation com ctx [Fable.Any] "Util" "IEnumerator" + | Types.ienumeratorGeneric + -> makeImportTypeAnnotation com ctx genArgs "Util" "IEnumerator" + | Types.icomparable + -> makeImportTypeAnnotation com ctx [Fable.Any] "Util" "IComparable" + | Types.icomparableGeneric + | Types.iStructuralComparable + -> makeImportTypeAnnotation com ctx genArgs "Util" "IComparable" + | Types.iequatableGeneric + | Types.iStructuralEquatable + -> makeImportTypeAnnotation com ctx genArgs "Util" "IEquatable" + | Types.icomparer + -> makeImportTypeAnnotation com ctx [Fable.Any] "Util" "IComparer" + | Types.icomparerGeneric + -> makeImportTypeAnnotation com ctx genArgs "Util" "IComparer" + | Types.iequalityComparerGeneric + -> makeImportTypeAnnotation com ctx genArgs "Util" "IEqualityComparer" + | _ -> + // TODO: add more interfaces + AnyTypeAnnotation + + let makeEntityTypeAnnotation com ctx (entRef: Fable.EntityRef) genArgs = + match entRef.FullName with | Types.result -> makeUnionTypeAnnotation com ctx genArgs | entName when entName.StartsWith(Types.choiceNonGeneric) -> makeUnionTypeAnnotation com ctx genArgs | _ -> - let ent = com.GetEntity(ent) + let ent = com.GetEntity(entRef) if ent.IsInterface then - AnyTypeAnnotation // TODO: + makeInterfaceTypeAnnotation com ctx entRef genArgs else match Lib.tryJsConstructor com ctx ent with | Some entRef -> @@ -594,7 +632,7 @@ module Util = type NamedTailCallOpportunity(_com: Compiler, ctx, name, args: Fable.Ident list) = // Capture the current argument values to prevent delayed references from getting corrupted, // for that we use block-scoped ES2015 variable declarations. See #681, #1859 - let argIds = discardUnitArg args |> List.map (fun arg -> + let argIds = args |> discardUnitArg |> List.map (fun arg -> getUniqueNameInDeclarationScope ctx (arg.Name + "_mut")) interface ITailCallOpportunity with member _.Label = name @@ -2098,23 +2136,25 @@ module Util = let transformAttachedProperty (com: IBabelCompiler) ctx (info: Fable.MemberFunctionOrValue) (memb: Fable.MemberDecl) = let isStatic = not info.IsInstance let kind = if info.IsGetter then ClassGetter else ClassSetter - let args, body, _returnType, _typeParamDecl = + let args, body, returnType, _typeParamDecl = getMemberArgsAndBody com ctx (Attached isStatic) false memb.Args memb.Body let key, computed = memberFromName memb.Name - ClassMember.classMethod(kind, key, args, body, computed_=computed, ``static``=isStatic) + ClassMember.classMethod(kind, key, args, body, computed_=computed, ``static``=isStatic, + ?returnType=returnType) //, ?typeParameters=typeParamDecl) |> Array.singleton let transformAttachedMethod (com: IBabelCompiler) ctx (info: Fable.MemberFunctionOrValue) (memb: Fable.MemberDecl) = let isStatic = not info.IsInstance - let makeMethod name args body = + let makeMethod name args body returnType _typeParamDecl = let key, computed = memberFromName name - ClassMember.classMethod(ClassFunction, key, args, body, computed_=computed, ``static``=isStatic) - let args, body, _returnType, _typeParamDecl = + ClassMember.classMethod(ClassFunction, key, args, body, computed_=computed, ``static``=isStatic, + ?returnType=returnType) //, ?typeParameters=typeParamDecl) + let args, body, returnType, typeParamDecl = getMemberArgsAndBody com ctx (Attached isStatic) info.HasSpread memb.Args memb.Body [| - yield makeMethod memb.Name args body + yield makeMethod memb.Name args body returnType typeParamDecl if info.FullName = "System.Collections.Generic.IEnumerable.GetEnumerator" then - yield makeMethod "Symbol.iterator" [||] (enumerator2iterator com ctx) + yield makeMethod "Symbol.iterator" [||] (enumerator2iterator com ctx) None None |] let transformUnion (com: IBabelCompiler) ctx (ent: Fable.Entity) (entName: string) classMembers = diff --git a/src/Fable.Transforms/Python/Fable2Python.fs b/src/Fable.Transforms/Python/Fable2Python.fs index b12ae7c5d0..0453b9f0f4 100644 --- a/src/Fable.Transforms/Python/Fable2Python.fs +++ b/src/Fable.Transforms/Python/Fable2Python.fs @@ -851,12 +851,12 @@ module Annotation = | Types.icomparable, _ -> libValue com ctx "util" "IComparable", [] | Types.iStructuralEquatable, _ -> libValue com ctx "util" "IStructuralEquatable", [] | Types.iStructuralComparable, _ -> libValue com ctx "util" "IStructuralComparable", [] - | Types.comparer, _ -> + | Types.icomparerGeneric, _ -> let resolved, stmts = resolveGenerics com ctx genArgs repeatedGenerics fableModuleAnnotation com ctx "util" "IComparer_1" resolved, stmts | Types.equalityComparer, _ -> libValue com ctx "util" "IEqualityComparer", [] - | Types.equalityComparerGeneric, _ -> + | Types.iequalityComparerGeneric, _ -> let resolved, stmts = stdlibModuleTypeHint com ctx "typing" "Any" [] fableModuleAnnotation com ctx "util" "IEqualityComparer_1" [ resolved ], stmts | Types.ienumerator, _ -> diff --git a/src/Fable.Transforms/Python/Replacements.fs b/src/Fable.Transforms/Python/Replacements.fs index 5b0e67fac0..57ad4ecd62 100644 --- a/src/Fable.Transforms/Python/Replacements.fs +++ b/src/Fable.Transforms/Python/Replacements.fs @@ -486,7 +486,6 @@ let structuralHash (com: ICompiler) r (arg: Expr) = | BclDateTimeOffset) -> "dateHash" | DeclaredType (ent, _) -> let ent = com.GetEntity(ent) - if not ent.IsInterface then "safeHash" else @@ -769,8 +768,8 @@ let injectArg (com: ICompiler) (ctx: Context) r moduleName methName (genArgs: Ty | None -> fail () | Some genArg -> match injectType with - | Types.comparer -> args @ [ makeComparer com ctx genArg ] - | Types.equalityComparerGeneric -> args @ [ makeEqualityComparer com ctx genArg ] + | Types.icomparerGeneric -> args @ [ makeComparer com ctx genArg ] + | Types.iequalityComparerGeneric -> args @ [ makeEqualityComparer com ctx genArg ] | Types.arrayCons -> match genArg with // We don't have a module for ResizeArray so let's assume the kind is MutableArray diff --git a/src/Fable.Transforms/Replacements.Util.fs b/src/Fable.Transforms/Replacements.Util.fs index badc5bcf62..bd91381a6e 100644 --- a/src/Fable.Transforms/Replacements.Util.fs +++ b/src/Fable.Transforms/Replacements.Util.fs @@ -414,7 +414,7 @@ let (|IDictionary|IEqualityComparer|Other|) = function | DeclaredType(ent,_) -> match ent.FullName with | Types.idictionary -> IDictionary - | Types.equalityComparerGeneric -> IEqualityComparer + | Types.iequalityComparerGeneric -> IEqualityComparer | _ -> Other | _ -> Other @@ -422,7 +422,7 @@ let (|IEnumerable|IEqualityComparer|Other|) = function | DeclaredType(ent,_) -> match ent.FullName with | Types.ienumerableGeneric -> IEnumerable - | Types.equalityComparerGeneric -> IEqualityComparer + | Types.iequalityComparerGeneric -> IEqualityComparer | _ -> Other | _ -> Other diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs index a7c2871cc7..88bd612e62 100644 --- a/src/Fable.Transforms/Replacements.fs +++ b/src/Fable.Transforms/Replacements.fs @@ -689,9 +689,9 @@ let injectArg (com: ICompiler) (ctx: Context) r moduleName methName (genArgs: Ty | None -> fail() | Some genArg -> match injectType with - | Types.comparer -> + | Types.icomparerGeneric -> args @ [makeComparer com ctx genArg] - | Types.equalityComparerGeneric -> + | Types.iequalityComparerGeneric -> args @ [makeEqualityComparer com ctx genArg] | Types.arrayCons -> match genArg with diff --git a/src/Fable.Transforms/ReplacementsInject.fs b/src/Fable.Transforms/ReplacementsInject.fs index 07a3587b72..6beee1c64b 100644 --- a/src/Fable.Transforms/ReplacementsInject.fs +++ b/src/Fable.Transforms/ReplacementsInject.fs @@ -15,8 +15,8 @@ let fableReplacementsModules = "mapFoldBack", (Types.arrayCons, 2) "concat", (Types.arrayCons, 0) "collect", (Types.arrayCons, 1) - "indexOf", (Types.equalityComparerGeneric, 0) - "contains", (Types.equalityComparerGeneric, 0) + "indexOf", (Types.iequalityComparerGeneric, 0) + "contains", (Types.iequalityComparerGeneric, 0) "singleton", (Types.arrayCons, 0) "initialize", (Types.arrayCons, 0) "replicate", (Types.arrayCons, 0) @@ -26,21 +26,21 @@ let fableReplacementsModules = "skipWhile", (Types.arrayCons, 0) "take", (Types.arrayCons, 0) "takeWhile", (Types.arrayCons, 0) - "removeInPlace", (Types.equalityComparerGeneric, 0) + "removeInPlace", (Types.iequalityComparerGeneric, 0) "partition", (Types.arrayCons, 0) "choose", (Types.arrayCons, 1) - "sortInPlaceBy", (Types.comparer, 1) - "sortInPlace", (Types.comparer, 0) - "sort", (Types.comparer, 0) - "sortBy", (Types.comparer, 1) - "sortDescending", (Types.comparer, 0) - "sortByDescending", (Types.comparer, 1) + "sortInPlaceBy", (Types.icomparerGeneric, 1) + "sortInPlace", (Types.icomparerGeneric, 0) + "sort", (Types.icomparerGeneric, 0) + "sortBy", (Types.icomparerGeneric, 1) + "sortDescending", (Types.icomparerGeneric, 0) + "sortByDescending", (Types.icomparerGeneric, 1) "sum", ("Fable.Core.IGenericAdder`1", 0) "sumBy", ("Fable.Core.IGenericAdder`1", 1) - "maxBy", (Types.comparer, 1) - "max", (Types.comparer, 0) - "minBy", (Types.comparer, 1) - "min", (Types.comparer, 0) + "maxBy", (Types.icomparerGeneric, 1) + "max", (Types.icomparerGeneric, 0) + "minBy", (Types.icomparerGeneric, 1) + "min", (Types.icomparerGeneric, 0) "average", ("Fable.Core.IGenericAverager`1", 0) "averageBy", ("Fable.Core.IGenericAverager`1", 1) "transpose", (Types.arrayCons, 0) @@ -49,57 +49,57 @@ let fableReplacementsModules = "updateAt", (Types.arrayCons, 0) ] "List", Map [ - "contains", (Types.equalityComparerGeneric, 0) - "sort", (Types.comparer, 0) - "sortBy", (Types.comparer, 1) - "sortDescending", (Types.comparer, 0) - "sortByDescending", (Types.comparer, 1) + "contains", (Types.iequalityComparerGeneric, 0) + "sort", (Types.icomparerGeneric, 0) + "sortBy", (Types.icomparerGeneric, 1) + "sortDescending", (Types.icomparerGeneric, 0) + "sortByDescending", (Types.icomparerGeneric, 1) "sum", ("Fable.Core.IGenericAdder`1", 0) "sumBy", ("Fable.Core.IGenericAdder`1", 1) - "maxBy", (Types.comparer, 1) - "max", (Types.comparer, 0) - "minBy", (Types.comparer, 1) - "min", (Types.comparer, 0) + "maxBy", (Types.icomparerGeneric, 1) + "max", (Types.icomparerGeneric, 0) + "minBy", (Types.icomparerGeneric, 1) + "min", (Types.icomparerGeneric, 0) "average", ("Fable.Core.IGenericAverager`1", 0) "averageBy", ("Fable.Core.IGenericAverager`1", 1) ] "Seq", Map [ - "contains", (Types.equalityComparerGeneric, 0) - "sort", (Types.comparer, 0) - "sortBy", (Types.comparer, 1) - "sortDescending", (Types.comparer, 0) - "sortByDescending", (Types.comparer, 1) + "contains", (Types.iequalityComparerGeneric, 0) + "sort", (Types.icomparerGeneric, 0) + "sortBy", (Types.icomparerGeneric, 1) + "sortDescending", (Types.icomparerGeneric, 0) + "sortByDescending", (Types.icomparerGeneric, 1) "sum", ("Fable.Core.IGenericAdder`1", 0) "sumBy", ("Fable.Core.IGenericAdder`1", 1) - "maxBy", (Types.comparer, 1) - "max", (Types.comparer, 0) - "minBy", (Types.comparer, 1) - "min", (Types.comparer, 0) + "maxBy", (Types.icomparerGeneric, 1) + "max", (Types.icomparerGeneric, 0) + "minBy", (Types.icomparerGeneric, 1) + "min", (Types.icomparerGeneric, 0) "average", ("Fable.Core.IGenericAverager`1", 0) "averageBy", ("Fable.Core.IGenericAverager`1", 1) ] "Seq2", Map [ - "distinct", (Types.equalityComparerGeneric, 0) - "distinctBy", (Types.equalityComparerGeneric, 1) - "except", (Types.equalityComparerGeneric, 0) - "countBy", (Types.equalityComparerGeneric, 1) - "groupBy", (Types.equalityComparerGeneric, 1) + "distinct", (Types.iequalityComparerGeneric, 0) + "distinctBy", (Types.iequalityComparerGeneric, 1) + "except", (Types.iequalityComparerGeneric, 0) + "countBy", (Types.iequalityComparerGeneric, 1) + "groupBy", (Types.iequalityComparerGeneric, 1) ] "Set", Map [ - "FSharpSet__Map", (Types.comparer, 1) - "singleton", (Types.comparer, 0) - "unionMany", (Types.comparer, 0) - "empty", (Types.comparer, 0) - "map", (Types.comparer, 1) - "ofList", (Types.comparer, 0) - "ofArray", (Types.comparer, 0) - "ofSeq", (Types.comparer, 0) + "FSharpSet__Map", (Types.icomparerGeneric, 1) + "singleton", (Types.icomparerGeneric, 0) + "unionMany", (Types.icomparerGeneric, 0) + "empty", (Types.icomparerGeneric, 0) + "map", (Types.icomparerGeneric, 1) + "ofList", (Types.icomparerGeneric, 0) + "ofArray", (Types.icomparerGeneric, 0) + "ofSeq", (Types.icomparerGeneric, 0) ] "Map", Map [ - "ofList", (Types.comparer, 0) - "ofSeq", (Types.comparer, 0) - "ofArray", (Types.comparer, 0) - "empty", (Types.comparer, 0) + "ofList", (Types.icomparerGeneric, 0) + "ofSeq", (Types.icomparerGeneric, 0) + "ofArray", (Types.icomparerGeneric, 0) + "empty", (Types.icomparerGeneric, 0) ] ] diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs index 41648182b1..8cee00f743 100644 --- a/src/Fable.Transforms/Rust/Fable2Rust.fs +++ b/src/Fable.Transforms/Rust/Fable2Rust.fs @@ -645,15 +645,24 @@ module TypeInfo = let transformGuidType com ctx: Rust.Ty = transformImportType com ctx [] "Guid" "Guid" - let transformDateTimeType com ctx: Rust.Ty = - transformImportType com ctx [] "DateTime" "DateTime" - let transformTimeSpanType com ctx: Rust.Ty = transformImportType com ctx [] "TimeSpan" "TimeSpan" + let transformDateTimeType com ctx: Rust.Ty = + transformImportType com ctx [] "DateTime" "DateTime" + let transformDateTimeOffsetType com ctx: Rust.Ty = transformImportType com ctx [] "DateTimeOffset" "DateTimeOffset" + let transformDateOnlyType com ctx: Rust.Ty = + transformImportType com ctx [] "DateTime" "DateOnly" + + let transformTimeOnlyType com ctx: Rust.Ty = + transformImportType com ctx [] "DateTime" "TimeOnly" + + let transformTimerType com ctx: Rust.Ty = + transformImportType com ctx [] "DateTime" "Timer" + let transformAsyncType com ctx genArg: Rust.Ty = transformImportType com ctx [genArg] "Async" "Async" @@ -877,6 +886,27 @@ module TypeInfo = let transformStringType com ctx: Rust.Ty = transformImportType com ctx [] "String" "string" + let transformBuiltinType com ctx typ kind: Rust.Ty = + match kind with + | Replacements.Util.BclGuid -> transformGuidType com ctx + | Replacements.Util.BclTimeSpan -> transformTimeSpanType com ctx + | Replacements.Util.BclDateTime -> transformDateTimeType com ctx + | Replacements.Util.BclDateTimeOffset -> transformDateTimeOffsetType com ctx + | Replacements.Util.BclDateOnly -> transformDateOnlyType com ctx + | Replacements.Util.BclTimeOnly -> transformTimeOnlyType com ctx + | Replacements.Util.BclTimer -> transformTimerType com ctx + | Replacements.Util.BclHashSet(genArg) -> transformHashSetType com ctx genArg + | Replacements.Util.BclDictionary(k, v) -> transformHashMapType com ctx [k; v] + | Replacements.Util.FSharpSet(genArg) -> transformSetType com ctx genArg + | Replacements.Util.FSharpMap(k, v) -> transformMapType com ctx [k; v] + | Replacements.Util.BclKeyValuePair(k, v) -> transformTupleType com ctx true [k; v] + | Replacements.Util.FSharpResult(ok, err) -> transformResultType com ctx [ok; err] + | Replacements.Util.FSharpChoice genArgs -> transformChoiceType com ctx genArgs + | Replacements.Util.FSharpReference(genArg) -> + if isInRefType com typ + then transformType com ctx genArg + else transformRefCellType com ctx genArg + let transformType (com: IRustCompiler) ctx (typ: Fable.Type): Rust.Ty = let ty = match typ with @@ -925,44 +955,13 @@ module TypeInfo = | Some ifc -> transformInterfaceType com ctx ifc.Entity [Fable.Any] | _ -> failwith "Cannot find IEnumerator interface, should not happen." + // built-in types + | Replacements.Util.Builtin kind -> + transformBuiltinType com ctx typ kind + // other declared types | Fable.DeclaredType(entRef, genArgs) -> - match entRef.FullName, genArgs with - | Replacements.Util.BuiltinEntity kind -> - match kind with - | Replacements.Util.BclDateOnly - | Replacements.Util.BclTimeOnly - | Replacements.Util.BclTimer - -> transformDeclaredType com ctx entRef genArgs - | Replacements.Util.BclGuid -> transformGuidType com ctx - | Replacements.Util.BclDateTime -> transformDateTimeType com ctx - | Replacements.Util.BclTimeSpan -> transformTimeSpanType com ctx - | Replacements.Util.BclDateTimeOffset -> transformDateTimeOffsetType com ctx - | Replacements.Util.BclHashSet(genArg) -> transformHashSetType com ctx genArg - | Replacements.Util.BclDictionary(k, v) -> transformHashMapType com ctx [k; v] - | Replacements.Util.FSharpSet(genArg) -> transformSetType com ctx genArg - | Replacements.Util.FSharpMap(k, v) -> transformMapType com ctx [k; v] - | Replacements.Util.BclKeyValuePair(k, v) -> transformTupleType com ctx true [k; v] - | Replacements.Util.FSharpResult(ok, err) -> transformResultType com ctx [ok; err] - | Replacements.Util.FSharpChoice genArgs -> transformChoiceType com ctx genArgs - | Replacements.Util.FSharpReference(genArg) -> - if isInRefType com typ - then transformType com ctx genArg - else transformRefCellType com ctx genArg - | _ -> - transformDeclaredType com ctx entRef genArgs - - // // let generics = generics |> List.map (transformTypeInfo com ctx r genMap) |> List.toArray - // // Check if the entity is actually declared in JS code - // if ent.IsInterface - // || FSharp2Fable.Util.isErasedOrStringEnumEntity ent - // || FSharp2Fable.Util.isGlobalOrImportedEntity ent - // || FSharp2Fable.Util.isReplacementCandidate ent then - // genericEntity ent.FullName generics - // else - // let reflectionMethodExpr = FSharp2Fable.Util.entityIdentWithSuffix com ent Naming.reflectionSuffix - // let callee = com.TransformExpr(ctx, reflectionMethodExpr) - // Expression.callExpression(callee, generics) + transformDeclaredType com ctx entRef genArgs match shouldBeRefCountWrapped com ctx typ with | Some Lrc -> ty |> makeLrcTy com ctx diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs index 0f978bb4ee..139d4173b0 100644 --- a/src/Fable.Transforms/Rust/Replacements.fs +++ b/src/Fable.Transforms/Rust/Replacements.fs @@ -702,7 +702,7 @@ let makeGenericAverager (com: ICompiler) ctx t = // | None -> fail() // | Some(_,genArg) -> // match injectType with -// | Types.comparer -> +// | Types.icomparerGeneric -> // args @ [makeComparer com ctx genArg] // | Types.equalityComparer -> // args @ [makeEqualityComparer com ctx genArg] diff --git a/src/Fable.Transforms/Transforms.Util.fs b/src/Fable.Transforms/Transforms.Util.fs index 32ff74a981..c575fa7fc0 100644 --- a/src/Fable.Transforms/Transforms.Util.fs +++ b/src/Fable.Transforms/Transforms.Util.fs @@ -119,6 +119,7 @@ module Types = let [] iequatableGeneric = "System.IEquatable`1" let [] icomparableGeneric = "System.IComparable`1" let [] icomparable = "System.IComparable" + let [] icomparer = "System.Collections.IComparer" let [] iStructuralEquatable = "System.Collections.IStructuralEquatable" let [] iStructuralComparable = "System.Collections.IStructuralComparable" let [] idisposable = "System.IDisposable" @@ -133,8 +134,8 @@ module Types = let [] equalityComparer = "System.Collections.IEqualityComparer" // Types compatible with Inject attribute (fable library) - let [] comparer = "System.Collections.Generic.IComparer`1" - let [] equalityComparerGeneric = "System.Collections.Generic.IEqualityComparer`1" + let [] icomparerGeneric = "System.Collections.Generic.IComparer`1" + let [] iequalityComparerGeneric = "System.Collections.Generic.IEqualityComparer`1" let [] arrayCons = "Array.Cons`1" let [] adder = "Fable.Core.IGenericAdder`1" let [] averager = "Fable.Core.IGenericAverager`1" diff --git a/src/fable-library/Array.fs b/src/fable-library/Array.fs index 74ad3c28db..406429ec11 100644 --- a/src/fable-library/Array.fs +++ b/src/fable-library/Array.fs @@ -330,7 +330,7 @@ let tryFind (predicate: 'T -> bool) (array: 'T[]): 'T option = let findIndex (predicate: 'T -> bool) (array: 'T[]): int = match findIndexImpl predicate array with | index when index > -1 -> index - | _ -> indexNotFound() + | _ -> indexNotFound(); -1 let tryFindIndex (predicate: 'T -> bool) (array: 'T[]): int option = match findIndexImpl predicate array with @@ -378,7 +378,7 @@ let findLastIndex predicate (array: _[]) = let findIndexBack predicate (array: _[]) = let rec loop i = - if i < 0 then indexNotFound() + if i < 0 then indexNotFound(); -1 elif predicate array.[i] then i else loop (i - 1) loop (array.Length - 1) diff --git a/src/fable-library/BigInt/z.fs b/src/fable-library/BigInt/z.fs index 3d57444b37..86e3cca503 100644 --- a/src/fable-library/BigInt/z.fs +++ b/src/fable-library/BigInt/z.fs @@ -113,7 +113,7 @@ namespace BigInt member x.StructuredDisplayString = x.ToString() interface Fable.Core.IJsonSerializable with - member this.toJSON(_key) = + member this.toJSON() = this.ToString() |> box interface System.IComparable with diff --git a/src/fable-library/Global.fs b/src/fable-library/Global.fs index 5dd705e569..fa75cff177 100644 --- a/src/fable-library/Global.fs +++ b/src/fable-library/Global.fs @@ -13,7 +13,7 @@ type Symbol_wellknown = abstract ``Symbol.toStringTag``: string type IJsonSerializable = - abstract toJSON: key: string -> obj + abstract toJSON: unit -> obj namespace global diff --git a/src/fable-library/List.fs b/src/fable-library/List.fs index 0e334ec9f9..83b8d864b7 100644 --- a/src/fable-library/List.fs +++ b/src/fable-library/List.fs @@ -21,7 +21,7 @@ type LinkedList<'T when 'T: comparison> = member xs.IsEmpty = xs.tail.IsNone member xs.Length = - let rec loop i xs = + let rec loop i (xs: 'T list) = match xs.tail with | None -> i | Some t -> loop (i + 1) t @@ -38,7 +38,7 @@ type LinkedList<'T when 'T: comparison> = | Some t -> t member xs.Item with get (index) = - let rec loop i xs = + let rec loop i (xs: 'T list) = match xs.tail with | None -> invalidArg "index" SR.indexOutOfBounds | Some t -> @@ -54,7 +54,7 @@ type LinkedList<'T when 'T: comparison> = then true else let ys = other :?> 'T list - let rec loop xs ys = + let rec loop (xs: 'T list) (ys: 'T list) = match xs.tail, ys.tail with | None, None -> true | None, Some _ -> false @@ -77,13 +77,13 @@ type LinkedList<'T when 'T: comparison> = loop 0 0 xs interface IJsonSerializable with - member this.toJSON(_key) = + member this.toJSON() = Helpers.arrayFrom(this) |> box interface System.IComparable with member xs.CompareTo(other: obj) = let ys = other :?> 'T list - let rec loop xs ys = + let rec loop (xs: 'T list) (ys: 'T list) = match xs.tail, ys.tail with | None, None -> 0 | None, Some _ -> -1 @@ -128,7 +128,7 @@ and List<'T> when 'T: comparison = LinkedList<'T> // [] // module List = -let inline indexNotFound() = raise (System.Collections.Generic.KeyNotFoundException(SR.keyNotFoundAlt)) +let indexNotFound() = raise (System.Collections.Generic.KeyNotFoundException(SR.keyNotFoundAlt)) let empty () = List.Empty @@ -413,7 +413,7 @@ let tryFindIndex f xs: int option = let findIndex f xs: int = match tryFindIndex f xs with | Some x -> x - | None -> indexNotFound() + | None -> indexNotFound(); -1 let tryFindIndexBack f xs: int option = xs |> toArray |> Array.tryFindIndexBack f @@ -421,7 +421,7 @@ let tryFindIndexBack f xs: int option = let findIndexBack f xs: int = match tryFindIndexBack f xs with | Some x -> x - | None -> indexNotFound() + | None -> indexNotFound(); -1 let tryItem n (xs: 'T list) = let rec loop i (xs: 'T list) = diff --git a/src/fable-library/Map.fs b/src/fable-library/Map.fs index c864bccb25..140a894bc7 100644 --- a/src/fable-library/Map.fs +++ b/src/fable-library/Map.fs @@ -705,7 +705,7 @@ type Map<[]'Key, [ box interface IEnumerable> with diff --git a/src/fable-library/MutableMap.fs b/src/fable-library/MutableMap.fs index 8fea7c0a22..6e9856a12d 100644 --- a/src/fable-library/MutableMap.fs +++ b/src/fable-library/MutableMap.fs @@ -83,7 +83,7 @@ type MutableMap<'Key, 'Value when 'Key: equality>(pairs: KeyValuePair<'Key, 'Val // Native JS Map (used for primitive keys) doesn't work with `JSON.stringify` but // let's add `toJSON` for consistency with the types within fable-library. interface Fable.Core.IJsonSerializable with - member this.toJSON(_key) = + member this.toJSON() = Helpers.arrayFrom(this) |> box diff --git a/src/fable-library/MutableSet.fs b/src/fable-library/MutableSet.fs index f2e2385b2f..4eff8c9a76 100644 --- a/src/fable-library/MutableSet.fs +++ b/src/fable-library/MutableSet.fs @@ -70,7 +70,7 @@ type MutableSet<'T when 'T: equality>(items: 'T seq, comparer: IEqualityComparer // Native JS Set (used for primitive keys) doesn't work with `JSON.stringify` but // let's add `toJSON` for consistency with the types within fable-library. interface Fable.Core.IJsonSerializable with - member this.toJSON(_key) = + member this.toJSON() = Helpers.arrayFrom(this) |> box diff --git a/src/fable-library/Seq.fs b/src/fable-library/Seq.fs index 271d017bad..c32e34461c 100644 --- a/src/fable-library/Seq.fs +++ b/src/fable-library/Seq.fs @@ -92,7 +92,7 @@ module Enumerator = // let dispose() = () // fromFunctions current next dispose - let cast (e: System.Collections.IEnumerator): IEnumerator<'T> = + let cast (e: IEnumerator<'T>): IEnumerator<'T> = let current() = unbox<'T> e.Current let next() = e.MoveNext() let dispose() = @@ -267,7 +267,7 @@ let generateIndexed create compute dispose = let append (xs: seq<'T>) (ys: seq<'T>) = concat [| xs; ys |] -let cast (xs: System.Collections.IEnumerable) = +let cast (xs: IEnumerable<'T>) = mkSeq (fun () -> checkNonNull "source" xs xs.GetEnumerator() @@ -408,7 +408,7 @@ let tryFindIndex predicate (xs: seq<'T>) = let findIndex predicate (xs: seq<'T>) = match tryFindIndex predicate xs with | Some x -> x - | None -> indexNotFound() + | None -> indexNotFound(); -1 let tryFindIndexBack predicate (xs: seq<'T>) = xs @@ -418,7 +418,7 @@ let tryFindIndexBack predicate (xs: seq<'T>) = let findIndexBack predicate (xs: seq<'T>) = match tryFindIndexBack predicate xs with | Some x -> x - | None -> indexNotFound() + | None -> indexNotFound(); -1 let fold (folder: 'State -> 'T -> 'State) (state: 'State) (xs: seq<'T>) = use e = ofSeq xs diff --git a/src/fable-library/Set.fs b/src/fable-library/Set.fs index b6fe31aa58..e874e0607d 100644 --- a/src/fable-library/Set.fs +++ b/src/fable-library/Set.fs @@ -775,7 +775,7 @@ type Set<[]'T when 'T: comparison >(comparer:IComparer<'T member _.``Symbol.toStringTag`` = "FSharpSet" interface IJsonSerializable with - member this.toJSON(_key) = + member this.toJSON() = Helpers.arrayFrom(this) |> box interface System.IComparable with diff --git a/src/fable-library/Types.ts b/src/fable-library/Types.ts index 29a25bdb7e..9bc188c514 100644 --- a/src/fable-library/Types.ts +++ b/src/fable-library/Types.ts @@ -1,4 +1,4 @@ -import { IComparable, IEquatable, combineHashCodes, compare, compareArrays, equalArrays, equals, sameConstructor, numberHash, structuralHash } from "./Util.js"; +import { IComparable, IEquatable, IHashable, combineHashCodes, compare, compareArrays, equalArrays, equals, sameConstructor, numberHash, structuralHash } from "./Util.js"; // This type is only used internally for .ts files in the library // F# Result type is in Choice.fs @@ -153,7 +153,7 @@ function recordCompareTo(self: T, other: T) { } } -export abstract class Record implements IEquatable, IComparable { +export abstract class Record implements IEquatable, IComparable, IHashable { toJSON() { return recordToJSON(this); } toString() { return recordToString(this); } GetHashCode() { return recordGetHashCode(this); } diff --git a/src/fable-library/Util.ts b/src/fable-library/Util.ts index ff320a023a..13fab92f10 100644 --- a/src/fable-library/Util.ts +++ b/src/fable-library/Util.ts @@ -20,10 +20,13 @@ export interface IComparable extends IEquatable { } export interface IEquatable { - GetHashCode(): number; Equals(x: T): boolean; } +export interface IHashable { + GetHashCode(): number; +} + export interface IDisposable { Dispose(): void; } @@ -47,28 +50,32 @@ export interface ICollection { Remove(item: T): boolean; } +export function isArrayLike(x: T | ArrayLike | Iterable): x is T[] { + return Array.isArray(x) || ArrayBuffer.isView(x); +} + export function isIterable(x: T | ArrayLike | Iterable): x is Iterable { return x != null && typeof x === "object" && Symbol.iterator in x; } -export function isArrayLike(x: T | ArrayLike | Iterable): x is T[] { - return Array.isArray(x) || ArrayBuffer.isView(x); +export function isEnumerable(x: T | Iterable): x is IEnumerable { + return x != null && typeof (x as IEnumerable).GetEnumerator === "function" } -function isComparer(x: T | IComparer): x is IComparer { - return typeof (x as IComparer).Compare === "function"; +export function isComparer(x: T | IComparer): x is IComparer { + return x != null && typeof (x as IComparer).Compare === "function"; } -function isComparable(x: T | IComparable): x is IComparable { - return typeof (x as IComparable).CompareTo === "function"; +export function isComparable(x: T | IComparable): x is IComparable { + return x != null && typeof (x as IComparable).CompareTo === "function"; } -function isEquatable(x: T | IEquatable): x is IEquatable { - return typeof (x as IEquatable).Equals === "function"; +export function isEquatable(x: T | IEquatable): x is IEquatable { + return x != null && typeof (x as IEquatable).Equals === "function"; } -function isHashable(x: T | IEquatable): x is IEquatable { - return typeof (x as IEquatable).GetHashCode === "function"; +export function isHashable(x: T | IHashable): x is IHashable { + return x != null && typeof (x as IHashable).GetHashCode === "function"; } export function isDisposable(x: T | IDisposable): x is IDisposable { @@ -86,8 +93,8 @@ export function sameConstructor(x: T, y: T) { } export interface IEnumerator extends IDisposable { - ["System.Collections.Generic.IEnumerator`1.get_Current"](): T | undefined; - ["System.Collections.IEnumerator.get_Current"](): T | undefined; + ["System.Collections.Generic.IEnumerator`1.get_Current"](): T; + ["System.Collections.IEnumerator.get_Current"](): T; ["System.Collections.IEnumerator.MoveNext"](): boolean; ["System.Collections.IEnumerator.Reset"](): void; Dispose(): void; @@ -98,7 +105,7 @@ export interface IEnumerable extends Iterable { } export class Enumerator implements IEnumerator { - private current?: T; + private current: any; // : T; constructor(private iter: Iterator) { } public ["System.Collections.Generic.IEnumerator`1.get_Current"]() { return this.current; @@ -119,10 +126,9 @@ export class Enumerator implements IEnumerator { } } -export function getEnumerator(o: Iterable): IEnumerator { - return typeof (o as any).GetEnumerator === "function" - ? (o as IEnumerable).GetEnumerator() - : new Enumerator(o[Symbol.iterator]()); +export function getEnumerator(e: IEnumerable | Iterable): IEnumerator { + if (isEnumerable(e)) { return e.GetEnumerator(); } + else { return new Enumerator(e[Symbol.iterator]()); } } export function toIterator(en: IEnumerator): Iterator { @@ -293,9 +299,7 @@ export function physicalHash(x: T): number { } export function identityHash(x: T): number { - if (x == null) { - return 0; - } else if (isHashable(x)) { + if (isHashable(x)) { return x.GetHashCode(); } else { return physicalHash(x); @@ -352,8 +356,9 @@ export function fastStructuralHash(x: T): number { } // Intended for declared types that may or may not implement GetHashCode -export function safeHash(x: IEquatable | undefined): number { - return x == null ? 0 : isHashable(x) ? x.GetHashCode() : numberHash(ObjectRef.id(x)); +export function safeHash(x: IHashable | undefined): number { + // return x == null ? 0 : isHashable(x) ? x.GetHashCode() : numberHash(ObjectRef.id(x)); + return identityHash(x); } export function equalArraysWith(x: ArrayLike, y: ArrayLike, eq: (x: T, y: T) => boolean): boolean { diff --git a/src/tools/InjectProcessor/InjectProcessor.fs b/src/tools/InjectProcessor/InjectProcessor.fs index 949fc1cf4d..b248136ddb 100644 --- a/src/tools/InjectProcessor/InjectProcessor.fs +++ b/src/tools/InjectProcessor/InjectProcessor.fs @@ -8,8 +8,8 @@ open FSharp.Compiler.Symbols let typeAliases = Map [ - "System.Collections.Generic.IComparer`1", "comparer" - "System.Collections.Generic.IEqualityComparer`1", "equalityComparerGeneric" + "System.Collections.Generic.IComparer`1", "icomparerGeneric" + "System.Collections.Generic.IEqualityComparer`1", "iequalityComparerGeneric" "Native.Cons`1", "arrayCons" ]