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] Fixed derived traits mapping #3947

Merged
merged 1 commit into from
Oct 28, 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
4 changes: 4 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Fixed

* [Rust] Fixed derived traits mapping (by @ncave)

## 4.23.0 - 2024-10-28

### Added
Expand Down
76 changes: 48 additions & 28 deletions src/Fable.Transforms/Rust/Fable2Rust.fs
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,12 @@ module TypeInfo =
// TODO: more unprintable types?
| _ -> hasTypeOfType com isNonPrintableType isNonPrintableEntity entNames typ

let isNonPrintableEntity com entNames (ent: Fable.Entity) = false
// || (hasFieldOfType com isNonPrintableType entNames ent)
let isNonPrintableEntity com entNames (ent: Fable.Entity) =
ent.IsInterface || (hasFieldOfType com isNonPrintableType entNames ent)

let isNonDefaultableType (com: IRustCompiler) entNames typ =
match typ with
// TODO: more undefaultable types?
// | Fable.LambdaType _
// | Fable.DelegateType _ -> true
| _ -> hasTypeOfType com isNonDefaultableType isNonDefaultableEntity entNames typ

let isNonDefaultableEntity com entNames (ent: Fable.Entity) =
Expand All @@ -470,7 +468,8 @@ module TypeInfo =
| _ -> hasTypeOfType com isNonCopyableType isNonCopyableEntity entNames typ

let isNonCopyableEntity com entNames (ent: Fable.Entity) =
not ent.IsValueType
ent.IsInterface
|| not ent.IsValueType
|| (hasMutableFields com ent)
|| (hasFieldOfType com isNonCopyableType entNames ent)

Expand All @@ -488,8 +487,9 @@ module TypeInfo =
| _ -> hasTypeOfType com isNonEquatableType isNonEquatableEntity entNames typ

let isNonEquatableEntity com entNames (ent: Fable.Entity) =
ent.IsInterface || not (FSharp2Fable.Util.hasStructuralEquality ent)
// || (hasFieldOfType com isNonEquatableType entNames ent)
ent.IsInterface
|| not (FSharp2Fable.Util.hasStructuralEquality ent)
|| (hasFieldOfType com isNonEquatableType entNames ent)

let isNonComparableType (com: IRustCompiler) entNames typ =
match typ with
Expand Down Expand Up @@ -3897,15 +3897,24 @@ module Util =
let defaultTypeBounds =
[
mkTypeTraitGenericBound [ rawIdent "Clone" ] None
// mkTypeTraitGenericBound [ rawIdent "Send" ] None
// mkTypeTraitGenericBound [ rawIdent "Sync" ] None
mkLifetimeGenericBound "'static" //TODO: add it only when needed
]

let makeDefaultTypeBounds com ctx =
// let importName = getLibraryImportName com ctx "Native" "IObject"
// let objectBound = mkTypeTraitGenericBound [ importName ] None
// objectBound :: defaultTypeBounds
defaultTypeBounds

let makeGenericParams com ctx (genParams: Fable.GenericParam list) =
genParams
|> List.filter (fun p -> not p.IsMeasure)
|> List.map (fun p ->
let typeBounds = makeTypeBounds com ctx p.Name p.Constraints
mkGenericParamFromName [] p.Name (typeBounds @ defaultTypeBounds)
let typeBounds = typeBounds @ (makeDefaultTypeBounds com ctx)
mkGenericParamFromName [] p.Name typeBounds
)

let makeGenericParamsFromArgs com ctx (genArgs: Fable.Type list) =
Expand All @@ -3914,7 +3923,8 @@ module Util =
function
| Fable.GenericParam(name, isMeasure, constraints) when not isMeasure ->
let typeBounds = makeTypeBounds com ctx name constraints
mkGenericParamFromName [] name (typeBounds @ defaultTypeBounds) |> Some
let typeBounds = typeBounds @ (makeDefaultTypeBounds com ctx)
mkGenericParamFromName [] name typeBounds |> Some
| _ -> None
)

Expand Down Expand Up @@ -4052,7 +4062,8 @@ module Util =
// | Fable.DeclaredType(entRef, genArgs) :: _ ->
// let entName = getEntityFullName com ctx entRef
// let memberItem = makeMemberItem com ctx true (decl, memb)
// [ memberItem ] |> makeTraitImpls com ctx entName genArgs None
// let implItem = [ memberItem ] |> makeTraitImpl com ctx entName genArgs None
// [ implItem ]
// | _ -> []

let transformModuleFunction (com: IRustCompiler) ctx (memb: Fable.MemberFunctionOrValue) (decl: Fable.MemberDecl) =
Expand Down Expand Up @@ -4254,7 +4265,8 @@ module Util =
fnItem

let makeDerivedFrom com (ent: Fable.Entity) =
// let isCopyable = not (ent |> isNonCopyableEntity com Set.empty)
let isCopyable = false //not (ent |> isNonCopyableEntity com Set.empty)
let isCloneable = true //not (ent |> isNonCloneableEntity com Set.empty)
let isPrintable = not (ent |> isNonPrintableEntity com Set.empty)
let isDefaultable = not (ent |> isNonDefaultableEntity com Set.empty)
let isHashable = not (ent |> isNonHashableEntity com Set.empty)
Expand All @@ -4263,9 +4275,10 @@ module Util =

let derivedFrom =
[
rawIdent "Clone"
// if isCopyable then
// rawIdent "Copy"
if isCopyable then
rawIdent "Copy"
if isCloneable then
rawIdent "Clone"
if isPrintable then
rawIdent "Debug"
if isDefaultable then
Expand Down Expand Up @@ -4515,9 +4528,7 @@ module Util =
let traitItem =
let assocItems = makeInterfaceItems com ctx false typeName ent
let generics = makeGenerics com ctx genArgs
// let sendBound = mkTypeTraitGenericBound [ rawIdent "Send" ] None
// let syncBound = mkTypeTraitGenericBound [ rawIdent "Sync" ] None
let traitBounds = [] // [ sendBound; syncBound ]
let traitBounds = [] // (makeDefaultTypeBounds com ctx)
let attrs = transformAttributes com ctx ent.Attributes decl.XmlDoc
mkTraitItem attrs entName assocItems traitBounds generics

Expand All @@ -4526,7 +4537,7 @@ module Util =
let memberItems = makeInterfaceItems com ctx true typeName ent
let genArgsOpt = transformGenArgs com ctx genArgs
let traitBound = mkTypeTraitGenericBound [ entName ] genArgsOpt
let typeBounds = traitBound :: defaultTypeBounds
let typeBounds = traitBound :: (makeDefaultTypeBounds com ctx)
let typeParam = mkGenericParamFromName [] typeName typeBounds
let genParams = makeGenericParamsFromArgs com ctx genArgs
let generics = typeParam :: genParams |> mkGenerics
Expand Down Expand Up @@ -4614,10 +4625,11 @@ module Util =
let ofTrait = mkTraitRef path |> Some
let assocItems = [ tyItem; fnItem ]

assocItems |> makeTraitImpls com ctx entName genArgs ofTrait
let implItem = assocItems |> makeTraitImpl com ctx entName genArgs ofTrait
[ implItem ]
| _ -> []

let makeDisplayTraitImpls com ctx entName genArgs hasToString =
let makeDisplayTraitImpls com ctx entName genArgs hasToString hasDebug =
// expected output:
// impl core::fmt::Display for {self_ty} {
// fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
Expand Down Expand Up @@ -4649,10 +4661,16 @@ module Util =
let fnKind = mkFnKind DEFAULT_FN_HEADER fnDecl NO_GENERICS fnBody
let fnItem = mkFnAssocItem [] "fmt" fnKind

let path = mkGenericPath ("core" :: "fmt" :: "Display" :: []) None
let ofTrait = mkTraitRef path |> Some
let makeItem fmtTrait =
let path = mkGenericPath ("core" :: "fmt" :: fmtTrait :: []) None
let ofTrait = mkTraitRef path |> Some
let implItem = [ fnItem ] |> makeTraitImpl com ctx entName genArgs ofTrait
implItem

[ fnItem ] |> makeTraitImpls com ctx entName genArgs ofTrait
if hasDebug then
[ makeItem "Debug"; makeItem "Display" ]
else
[ makeItem "Display" ]

let op_impl_map =
Map
Expand Down Expand Up @@ -4757,21 +4775,22 @@ module Util =

[ ctorItem ]

let makeTraitImpls (com: IRustCompiler) ctx entName genArgs ofTrait memberItems =
let makeTraitImpl (com: IRustCompiler) ctx entName genArgs ofTrait memberItems =
let nameParts = entName |> splitNameParts
let genArgsOpt = transformGenArgs com ctx genArgs
let traitBound = mkTypeTraitGenericBound nameParts genArgsOpt
let self_ty = mkTraitTy [ traitBound ]
let generics = makeGenerics com ctx genArgs
let implItem = mkImplItem [] "" self_ty generics memberItems ofTrait
[ implItem ]
implItem

let makeInterfaceTraitImpls (com: IRustCompiler) ctx entName genArgs ifcEntRef ifcGenArgs memberItems =
let ifcFullName = getEntityFullName com ctx ifcEntRef
let ifcGenArgsOpt = transformGenArgs com ctx ifcGenArgs
let path = makeFullNamePath ifcFullName ifcGenArgsOpt
let ofTrait = mkTraitRef path |> Some
memberItems |> makeTraitImpls com ctx entName genArgs ofTrait
let implItem = memberItems |> makeTraitImpl com ctx entName genArgs ofTrait
[ implItem ]

// let objectMemberNames =
// set
Expand Down Expand Up @@ -4838,7 +4857,8 @@ module Util =
if List.isEmpty memberItems then
[]
else
memberItems |> makeTraitImpls com ctx entName genArgs None
let implItem = memberItems |> makeTraitImpl com ctx entName genArgs None
[ implItem ]

let baseTypeOpt =
if isObjectExpr then
Expand All @@ -4855,7 +4875,7 @@ module Util =
let hasToString =
nonInterfaceMembers |> List.exists (fun (d, m) -> m.CompiledName = "ToString")

makeDisplayTraitImpls com ctx entName genParams hasToString
makeDisplayTraitImpls com ctx entName genParams hasToString false

let operatorTraitImpls =
nonInterfaceMembers |> makeOpTraitImpls com ctx ent entName genArgs
Expand Down
3 changes: 3 additions & 0 deletions src/fable-library-rust/src/Native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ pub mod Native_ {
use core::fmt::{Debug, Display, Formatter, Result};
use core::hash::{BuildHasher, Hash, Hasher};

// default object trait
// pub trait IObject: Clone + Debug + 'static {}

// -----------------------------------------------------------
// Helpers
// -----------------------------------------------------------
Expand Down
Loading