From eab37c5e271d32069f54e4958f29590588ea3281 Mon Sep 17 00:00:00 2001 From: ncave <777696+ncave@users.noreply.github.com> Date: Mon, 30 Sep 2024 00:53:36 -0700 Subject: [PATCH] [Rust] Improved member lookup --- src/Fable.Transforms/FSharp2Fable.Util.fs | 6 +- src/Fable.Transforms/FSharp2Fable.fs | 6 +- src/Fable.Transforms/Rust/Fable2Rust.fs | 132 +++++++++++----------- 3 files changed, 75 insertions(+), 69 deletions(-) diff --git a/src/Fable.Transforms/FSharp2Fable.Util.fs b/src/Fable.Transforms/FSharp2Fable.Util.fs index 11fbe4840..e03de5f1b 100644 --- a/src/Fable.Transforms/FSharp2Fable.Util.fs +++ b/src/Fable.Transforms/FSharp2Fable.Util.fs @@ -1645,6 +1645,7 @@ module TypeHelpers = (com: IFableCompiler) (ent: FSharpEntity) (compiledName: string) + (isInstance: bool) (argTypes: Fable.Type[] option) = let entRef = FsEnt.Ref ent @@ -1653,7 +1654,7 @@ module TypeHelpers = |> Option.bind (fun ent -> match ent with | :? FsEnt as entity -> - entity.TryFindMember(compiledName, isInstance = true, ?argTypes = argTypes, requireDispatchSlot = true) + entity.TryFindMember(compiledName, isInstance, ?argTypes = argTypes, requireDispatchSlot = true) | _ -> None ) @@ -2799,7 +2800,8 @@ module Util = entity |> tryFindBaseEntity (fun ent -> - tryFindAbstractMember com ent memb.CompiledName paramTypes |> Option.isSome + tryFindAbstractMember com ent memb.CompiledName memb.IsInstanceMember paramTypes + |> Option.isSome ) |> Option.defaultValue entity | _ -> entity diff --git a/src/Fable.Transforms/FSharp2Fable.fs b/src/Fable.Transforms/FSharp2Fable.fs index 7455937e8..419be7a2a 100644 --- a/src/Fable.Transforms/FSharp2Fable.fs +++ b/src/Fable.Transforms/FSharp2Fable.fs @@ -322,6 +322,7 @@ let private getImplementedSignatureInfo nonMangledNameConflicts (implementingEntity: FSharpEntity option) (sign: FSharpAbstractSignature) + isInstance = let implementingEntityFields = HashSet<_>() @@ -347,7 +348,7 @@ let private getImplementedSignatureInfo else None - tryFindAbstractMember com ent sign.Name paramTypes + tryFindAbstractMember com ent sign.Name isInstance paramTypes |> Option.map (fun m -> ent, m) ) |> Option.map (fun (ent, memb) -> @@ -424,7 +425,7 @@ let private transformObjExpr let r = makeRangeFrom over.Body let info = - getImplementedSignatureInfo com ctx r nonMangledNameConflicts None signature + getImplementedSignatureInfo com ctx r nonMangledNameConflicts None signature true let ctx, args = bindMemberArgs com ctx over.CurriedParameterGroups let! body = transformExpr com ctx [] over.Body @@ -1832,6 +1833,7 @@ let private transformImplementedSignature com.NonMangledAttachedMemberConflicts (Some implementingEntity) signature + memb.IsInstanceMember com.AddAttachedMember( entFullName, diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs index 6d936c8b8..8aa7bc441 100644 --- a/src/Fable.Transforms/Rust/Fable2Rust.fs +++ b/src/Fable.Transforms/Rust/Fable2Rust.fs @@ -2043,6 +2043,24 @@ module Util = // | None, _ -> // None + let getDeclMember (com: IRustCompiler) (decl: Fable.MemberDecl) = + decl.ImplementedSignatureRef + |> Option.defaultValue decl.MemberRef + |> com.GetMember + + let getDistinctInterfaceMembers (com: IRustCompiler) (ent: Fable.Entity) = + assert (ent.IsInterface) + + FSharp2Fable.Util.getInterfaceMembers com ent + |> Seq.filter (fun (ifc, memb) -> not memb.IsProperty) + |> Seq.distinctBy (fun (ifc, memb) -> memb.CompiledName) // skip inherited overwrites + + let getInterfaceMemberNames (com: IRustCompiler) (entRef: Fable.EntityRef) = + let ent = com.GetEntity(entRef) + + getDistinctInterfaceMembers com ent + |> Seq.map (fun (ifc, memb) -> memb.FullName) + |> Set.ofSeq let makeObjectExprMemberDecl (com: IRustCompiler) ctx (memb: Fable.ObjectExprMember) = let capturedIdents = getCapturedIdents com ctx (Some memb.Name) memb.Args memb.Body @@ -2141,11 +2159,12 @@ module Util = let ctx = { ctx with ScopedEntityGenArgs = getEntityGenParamNames ent } + let memberNames = getInterfaceMemberNames com entRef + let memberItems = members - |> List.map (fun decl -> decl, com.GetMember(decl.MemberRef)) - |> List.filter (fun (d, m) -> isInterfaceMember com entRef m) - |> List.distinctBy (fun (d, m) -> Fable.Naming.splitLast m.CompiledName) + |> List.map (fun decl -> decl, getDeclMember com decl) + |> List.filter (fun (d, m) -> Set.contains m.FullName memberNames) |> List.map (makeMemberItem com ctx false) |> makeInterfaceTraitImpls com ctx entName genParams entRef genArgs @@ -4058,25 +4077,6 @@ module Util = let fnItem = mkFnAssocItem attrs name fnKind fnItem - let isInterfaceMember (com: IRustCompiler) (entRef: Fable.EntityRef) (memb: Fable.MemberFunctionOrValue) = - let ent = com.GetEntity(entRef) - assert (ent.IsInterface) - - match memb.DeclaringEntity with - | Some declEntRef -> - let declEnt = com.GetEntity(declEntRef) - - if declEnt.IsInterface then - ent.AllInterfaces |> Seq.exists (fun ifc -> ifc.Entity = declEntRef) - else - // if declaring entity is not an interface, the interface is in the member.CompiledName - let ifcName, membName = Fable.Naming.splitLastBy "." memb.CompiledName - let ifcName, _ = Fable.Naming.splitFirstBy "<" ifcName // trim the generics - - ent.AllInterfaces - |> Seq.exists (fun ifc -> ifc.Entity.FullName.StartsWith(ifcName)) - | None -> false - let makeDerivedFrom com (ent: Fable.Entity) = let isCopyable = ent |> isCopyableEntity com Set.empty let isPrintable = ent |> isPrintableEntity com Set.empty @@ -4272,12 +4272,7 @@ module Util = fnItem let makeInterfaceItems (com: IRustCompiler) ctx hasBody typeName (ent: Fable.Entity) = - assert (ent.IsInterface) - - ent - |> FSharp2Fable.Util.getInterfaceMembers com - |> Seq.filter (fun (ifc, memb) -> memb.IsDispatchSlot) // TODO: is that needed? - |> Seq.distinctBy (fun (ifc, memb) -> Fable.Naming.splitLast memb.CompiledName) // skip inherited overwrites + getDistinctInterfaceMembers com ent |> Seq.map (fun (ifc, memb) -> let ifcEnt = com.GetEntity(ifc.Entity) let ifcTyp = Fable.DeclaredType(ifc.Entity, ifc.GenericArgs) @@ -4536,16 +4531,16 @@ module Util = let implItem = mkImplItem [] "" ty generics memberItems ofTrait [ implItem ] - let objectMemberNames = - set - [ - "Equals" - "GetHashCode" - "GetType" - "ToString" - // "MemberwiseClone" - // "ReferenceEquals" - ] + // let objectMemberNames = + // set + // [ + // // "Equals" + // // "GetHashCode" + // // "MemberwiseClone" + // // "ReferenceEquals" + // "GetType" + // "ToString" + // ] let ignoredInterfaceNames = set [ Types.ienumerable; Types.ienumerator ] @@ -4576,17 +4571,21 @@ module Util = let ctx = { ctx with ScopedEntityGenArgs = getEntityGenParamNames ent } // to filter out compiler-generated exception equality - let isNotExceptionMember (_m: Fable.MemberFunctionOrValue) = not (ent.IsFSharpExceptionDeclaration) - - let isNonInterfaceMember (m: Fable.MemberFunctionOrValue) = - m.IsConstructor - || (not ent.IsInterface && not m.IsOverrideOrExplicitInterfaceImplementation) - || (not ent.IsInterface && Set.contains m.CompiledName objectMemberNames) - - let nonInterfaceMembers, interfaceMembers = + let isNotExceptionMember (_memb: Fable.MemberFunctionOrValue) = not (ent.IsFSharpExceptionDeclaration) + + let isInterfaceMember (memb: Fable.MemberFunctionOrValue) = + memb.IsDispatchSlot + && (memb.DeclaringEntity + |> Option.bind com.TryGetEntity + |> Option.map (fun ent -> ent.IsInterface) + |> Option.defaultValue false) + // || memb.IsOverrideOrExplicitInterfaceImplementation) + // && not (Set.contains memb.CompiledName objectMemberNames) + + let interfaceMembers, nonInterfaceMembers = classDecl.AttachedMembers - |> List.map (fun decl -> decl, com.GetMember(decl.MemberRef)) - |> List.partition (snd >> isNonInterfaceMember) + |> List.map (fun decl -> decl, getDeclMember com decl) + |> List.partition (snd >> isInterfaceMember) let nonInterfaceImpls = let memberItems = @@ -4603,14 +4602,13 @@ module Util = let implItem = mkImplItem [] "" self_ty generics memberItems None [ implItem ] - let nonInterfaceMemberNames = - nonInterfaceMembers |> List.map (fun (d, m) -> d.Name) |> Set.ofList - let displayTraitImpls = if ent.IsInterface then [] else - let hasToString = Set.contains "ToString" nonInterfaceMemberNames + let hasToString = + nonInterfaceMembers |> List.exists (fun (d, m) -> m.CompiledName = "ToString") + makeDisplayTraitImpls com ctx self_ty genArgs hasToString let operatorTraitImpls = @@ -4618,19 +4616,23 @@ module Util = |> List.choose (makeOpTraitImpls com ctx ent entType self_ty genArgTys) let interfaceTraitImpls = - getAllInterfaces ent - |> List.collect (fun ifc -> - let memberItems = - interfaceMembers - |> List.filter (fun (d, m) -> isInterfaceMember com ifc.Entity m) - |> List.distinctBy (fun (d, m) -> Fable.Naming.splitLast m.CompiledName) - |> List.map (makeMemberItem com ctx false) - - if List.isEmpty memberItems then - [] - else - makeInterfaceTraitImpls com ctx entName genArgs ifc.Entity ifc.GenericArgs memberItems - ) + if List.isEmpty interfaceMembers then + [] + else + getAllInterfaces ent + |> List.collect (fun ifc -> + let memberNames = getInterfaceMemberNames com ifc.Entity + + let memberItems = + interfaceMembers + |> List.filter (fun (d, m) -> Set.contains m.FullName memberNames) + |> List.map (makeMemberItem com ctx false) + + if List.isEmpty memberItems then + [] + else + makeInterfaceTraitImpls com ctx entName genArgs ifc.Entity ifc.GenericArgs memberItems + ) nonInterfaceImpls @ displayTraitImpls @ operatorTraitImpls @ interfaceTraitImpls