Skip to content

Commit

Permalink
[Rust] Added basic class inheritance support (#3920)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave authored Oct 8, 2024
1 parent 61c6b36 commit 1da565b
Show file tree
Hide file tree
Showing 17 changed files with 409 additions and 219 deletions.
5 changes: 5 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

* [Rust] Added basic class inheritance support (by @ncave)
* [Rust] Added String.Replace(char, char) and test (by @ncave)

## 4.22.0 - 2024-10-02

### Added
Expand Down
16 changes: 11 additions & 5 deletions src/Fable.Transforms/FSharp2Fable.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2329,7 +2329,7 @@ module Util =
getMangledAbstractMemberName ent memb.CompiledName overloadHash
else if
// use DisplayName for getters/setters (except for Rust)
(isGetter || isSetter) && com.Options.Language <> Rust
(isGetter || isSetter) && not (com.Options.Language = Rust)
then
getMemberDisplayName memb
else
Expand Down Expand Up @@ -2399,7 +2399,12 @@ module Util =
let isPythonStaticMember =
com.Options.Language = Python && not memb.IsInstanceMember

if not info.isMangled && info.isGetter && not isPythonStaticMember then
if
not info.isMangled
&& info.isGetter
&& not isPythonStaticMember
&& not (com.Options.Language = Rust)
then
// Set the field as maybe calculated so it's not displaced by beta reduction
let kind =
Fable.FieldInfo.Create(
Expand All @@ -2410,7 +2415,7 @@ module Util =
)

Fable.Get(callee, kind, typ, r)
elif not info.isMangled && info.isSetter then
elif not info.isMangled && info.isSetter && not (com.Options.Language = Rust) then
let membType = memb.CurriedParameterGroups[0].[0].Type |> makeType Map.empty
let arg = callInfo.Args |> List.tryHead |> Option.defaultWith makeNull
Fable.Set(callee, Fable.FieldSet(info.name), membType, arg, r)
Expand Down Expand Up @@ -2578,7 +2583,7 @@ module Util =
match tryGlobalOrImportedFSharpEntity com e with
| Some expr -> Some expr
// AttachMembers classes behave the same as global/imported classes
| None when com.Options.Language <> Rust && isAttachMembersEntity com e ->
| None when not (com.Options.Language = Rust) && isAttachMembersEntity com e ->
FsEnt.Ref e |> entityIdent com |> Some
| None -> None

Expand Down Expand Up @@ -2696,7 +2701,7 @@ module Util =

/// Removes optional arguments set to None in tail position
let transformOptionalArguments
(_com: IFableCompiler)
(com: IFableCompiler)
(_ctx: Context)
(_r: SourceLocation option)
(memb: FSharpMemberOrFunctionOrValue)
Expand All @@ -2705,6 +2710,7 @@ module Util =
if
memb.CurriedParameterGroups.Count <> 1
|| memb.CurriedParameterGroups[0].Count <> (List.length args)
|| com.Options.Language = Rust // keep all optional args for Rust
then
args
else
Expand Down
10 changes: 5 additions & 5 deletions src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let private transformBaseConsCall
"Only inheriting from primary constructors is supported" |> addWarning com [] r

match makeCallFrom com ctx r Fable.Unit genArgs None baseArgs baseCons with
| Fable.Call(_baseExpr, info, t, r) ->
| Fable.Call(_baseExpr, info, t, r) when not (com.Options.Language = Rust) ->
// The baseExpr will be the exposed constructor function,
// replace with a direct reference to the entity
let baseExpr =
Expand Down Expand Up @@ -381,7 +381,7 @@ let private getImplementedSignatureInfo
&& countNonCurriedParamsForSignature sign = 1

let name =
if (isGetter || isSetter) && com.Options.Language <> Rust then
if (isGetter || isSetter) && not (com.Options.Language = Rust) then
Naming.removeGetSetPrefix sign.Name
else
sign.Name
Expand Down Expand Up @@ -778,7 +778,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) appliedGenArgs fs
&&
// The replacement only needs to happen when var.FullType = byref<fsExpr.Type>
fsExpr.Type = var.FullType.GenericArguments.[0]
&& com.Options.Language <> Rust
&& not (com.Options.Language = Rust)
then
// Getting byref value is compiled as FSharpRef op_Dereference
return Replacements.Api.getRefCell com r (List.head v.Type.Generics) v
Expand Down Expand Up @@ -1909,7 +1909,7 @@ let private transformMemberDecl
// for Rust, retain inlined functions that have [<CompiledName("...")>] attribute
elif
isInline memb
&& (Compiler.Language <> Rust || not (hasAttrib Atts.compiledName memb.Attributes))
&& not (Compiler.Language = Rust && (hasAttrib Atts.compiledName memb.Attributes))
then
[]
elif memb.IsImplicitConstructor then
Expand Down Expand Up @@ -1949,7 +1949,7 @@ let private transformMemberDecl
| _ -> transformMemberFunctionOrValue com ctx memb args body

let private addUsedRootName (com: Compiler) name (usedRootNames: Set<string>) =
if com.Options.Language <> Rust && Set.contains name usedRootNames then
if not (com.Options.Language = Rust) && Set.contains name usedRootNames then
"Cannot have two module members with same name: " + name |> addError com [] None

Set.add name usedRootNames
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Transforms/Replacements.Api.fs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ let tryBaseConstructor (com: ICompiler) ctx (ent: EntityRef) (argTypes: Lazy<Typ
match com.Options.Language with
| Python -> Py.Replacements.tryBaseConstructor com ctx ent argTypes genArgs args
| Dart -> Dart.Replacements.tryBaseConstructor com ctx ent argTypes genArgs args
| Rust -> Rust.Replacements.tryBaseConstructor com ctx ent argTypes genArgs args
| _ -> JS.Replacements.tryBaseConstructor com ctx ent argTypes genArgs args

let makeMethodInfo (com: ICompiler) r (name: string) (parameters: (string * Type) list) (returnType: Type) =
Expand Down
22 changes: 14 additions & 8 deletions src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,23 +1065,23 @@ module Types =

let mkParenTy ty : Ty = TyKind.Paren(ty) |> mkTy

let mkRefTy nameOpt ty : Ty =
let lifetimeOpt = nameOpt |> Option.map mkLifetime
let mkRefTy (lifetimeOpt: Symbol option) ty : Ty =
let opt_lifetime = lifetimeOpt |> Option.map mkLifetime

TyKind.Rptr(
lifetimeOpt,
opt_lifetime,
{
ty = ty
mutbl = Mutability.Not
}
)
|> mkTy

let mkMutRefTy nameOpt ty : Ty =
let lifetimeOpt = nameOpt |> Option.map mkLifetime
let mkMutRefTy (lifetimeOpt: Symbol option) ty : Ty =
let opt_lifetime = lifetimeOpt |> Option.map mkLifetime

TyKind.Rptr(
lifetimeOpt,
opt_lifetime,
{
ty = ty
mutbl = Mutability.Mut
Expand Down Expand Up @@ -1331,14 +1331,20 @@ module Items =
else
item |> mkPublicAssocItem

let mkFnItem attrs name kind : Item =
let mkTyAliasAssocItem attrs name ty generics bounds : AssocItem =
let ident = mkIdent name
ItemKind.Fn kind |> mkItem attrs ident

AssocItemKind.TyAlias(Defaultness.Final, generics, mkVec bounds, Some(ty))
|> mkAssocItem attrs ident

let mkFnAssocItem attrs name kind : AssocItem =
let ident = mkIdent name
AssocItemKind.Fn kind |> mkAssocItem attrs ident

let mkFnItem attrs name kind : Item =
let ident = mkIdent name
ItemKind.Fn kind |> mkItem attrs ident

let mkUseItem attrs names kind : Item =
let mkUseTree prefix kind : UseTree =
{
Expand Down
Loading

0 comments on commit 1da565b

Please sign in to comment.