Skip to content

Commit 8588ba5

Browse files
committed
Support Rust 2024 language edition
1 parent 9250574 commit 8588ba5

26 files changed

+299
-127
lines changed

src/Fable.Cli/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
* [JS/TS] Add support for `CaseRules.LowerAll` on `StringEnums` (by @shayanhabibi)
13+
* [Rust] Support Rust 2024 language edition (by @ncave)
1314

1415
### Fixed
1516

src/Fable.Compiler/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
* [JS/TS] Add support for `CaseRules.LowerAll` on `StringEnums` (by @shayanhabibi)
13+
* [Rust] Support Rust 2024 language edition (by @ncave)
1314

1415
### Fixed
1516

src/Fable.Transforms/FSharp2Fable.Util.fs

+6-6
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ type FsAtt(att: FSharpAttribute) =
150150
member _.Entity = FsEnt.Ref att.AttributeType
151151
member _.ConstructorArgs = att.ConstructorArguments |> Seq.mapToList snd
152152

153-
type FsGenParam(gen: FSharpGenericParameter) =
153+
type FsGenParam(p: FSharpGenericParameter) =
154154
interface Fable.GenericParam with
155-
member _.Name = TypeHelpers.genParamName gen
156-
member _.IsMeasure = gen.IsMeasure
157-
member _.Constraints = FsGenParam.Constraints gen
155+
member _.Name = TypeHelpers.genParamName p
156+
member _.IsMeasure = p.IsMeasure
157+
member _.Constraints = FsGenParam.Constraints p
158158

159159
static member Constraint(c: FSharpGenericParameterConstraint) =
160160
if c.IsCoercesToConstraint then
@@ -203,8 +203,8 @@ type FsGenParam(gen: FSharpGenericParameter) =
203203
else
204204
None // TODO: Document these cases
205205

206-
static member Constraints(gen: FSharpGenericParameter) =
207-
gen.Constraints |> Seq.chooseToList FsGenParam.Constraint
206+
static member Constraints(p: FSharpGenericParameter) =
207+
p.Constraints |> Seq.chooseToList FsGenParam.Constraint
208208

209209
type FsParam(p: FSharpParameter, ?isNamed) =
210210
let isOptional = p.IsOptionalArg

src/Fable.Transforms/Rust/AST/Rust.AST.Helpers.fs

+14
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ module Blocks =
513513
tokens = None
514514
}
515515

516+
let mkBodyBlock (expr: Expr) : Block = [ expr |> mkExprStmt ] |> mkBlock
517+
516518
let mkExprBlock (expr: Expr) : Block =
517519
match expr.kind with
518520
| ExprKind.Block(block, None) -> block
@@ -787,6 +789,14 @@ module Exprs =
787789
let mkLabelBlockExpr name (statements: Stmt seq) : Expr =
788790
ExprKind.Block(mkBlock statements, Some(mkLabel name)) |> mkExpr
789791

792+
let mkUnsafeBlockExpr (expr: Expr) : Expr =
793+
let block = mkExprBlock expr
794+
795+
let unsafeBlock =
796+
{ block with rules = BlockCheckMode.Unsafe(UnsafeSource.UserProvided) }
797+
798+
unsafeBlock |> mkBlockExpr
799+
790800
let mkIfThenExpr ifExpr thenExpr : Expr =
791801
let thenBlock = mkSemiBlock thenExpr
792802
ExprKind.If(ifExpr, thenBlock, None) |> mkExpr
@@ -1410,6 +1420,10 @@ module Items =
14101420
let def = Defaultness.Final
14111421
ItemKind.Const(def, ty, exprOpt) |> mkItem attrs ident
14121422

1423+
let mkExternCrateItem attrs name (aliasOpt: Symbol option) : Item =
1424+
let ident = mkIdent name
1425+
ItemKind.ExternCrate(aliasOpt) |> mkItem attrs ident
1426+
14131427
let mkImplItem attrs name ty generics items ofTrait : Item =
14141428
let ident = mkIdent name
14151429

src/Fable.Transforms/Rust/AST/Rust.AST.State.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ open type Macros
1111
module ast = Fable.Transforms.Rust.AST.Types
1212
module token = Fable.Transforms.Rust.AST.Types.token
1313
module kw = Fable.Transforms.Rust.AST.Symbols.kw
14-
module sym = Fable.Transforms.Rust.AST.Symbols.sym
14+
// module sym = Fable.Transforms.Rust.AST.Symbols.sym
1515
module pp = Fable.Transforms.Rust.AST.Pretty
1616
module parser = Fable.Transforms.Rust.AST.Parser
1717

src/Fable.Transforms/Rust/AST/Rust.AST.Symbols.fs

+92-32
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ module Fable.Transforms.Rust.AST.Symbols
55
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
66
// this should be rarely necessary though if the keywords are kept in alphabetic order.
77
module kw =
8-
// Special reserved identifiers used internally for elided lifetimes
9-
// unnamed method parameters crate root module error recovery etc.
8+
// Special reserved identifiers used internally for elided lifetimes,
9+
// unnamed method parameters, crate root module, error recovery etc.
1010
let Empty = ""
1111
let PathRoot = "{{root}}"
1212
let DollarCrate = "$crate"
@@ -64,24 +64,31 @@ module kw =
6464
let Yield = "yield"
6565

6666
// Edition-specific keywords that are used in stable Rust.
67-
let Async = "async" // >= 2018 Edition only
68-
let Await = "await" // >= 2018 Edition only
69-
let Dyn = "dyn" // >= 2018 Edition only
67+
let Async = "async" // >= 2018 Edition only
68+
let Await = "await" // >= 2018 Edition only
69+
let Dyn = "dyn" // >= 2018 Edition only
7070

7171
// Edition-specific keywords that are used in unstable Rust or reserved for future use.
72-
let Try = "try" // >= 2018 Edition only
72+
let Gen = "gen" // >= 2024 Edition only
73+
let Try = "try" // >= 2018 Edition only
7374

74-
// Special lifetime names
75+
// "Lifetime keywords" =regular keywords with a leading `'`.
7576
let UnderscoreLifetime = "'_"
7677
let StaticLifetime = "'static"
7778

78-
// Weak keywords have special meaning only in specific contexts.
79+
// Weak keywords, have special meaning only in specific contexts.
7980
let Auto = "auto"
81+
let Builtin = "builtin"
8082
let Catch = "catch"
8183
let Default = "default"
8284
let MacroRules = "macro_rules"
8385
let Raw = "raw"
86+
let Reuse = "reuse"
87+
let ContractEnsures = "contract_ensures"
88+
let ContractRequires = "contract_requires"
89+
let Safe = "safe"
8490
let Union = "union"
91+
let Yeet = "yeet"
8592

8693
let RustKeywords =
8794
[
@@ -149,74 +156,127 @@ module kw =
149156
Dyn
150157

151158
// Edition-specific keywords that are used in unstable Rust or reserved for future use.
159+
Gen
152160
Try
153161

154-
// Special lifetime names
162+
// "Lifetime keywords"
155163
UnderscoreLifetime
156164
StaticLifetime
157165

158166
// Weak keywords have special meaning only in specific contexts.
159167
Auto
168+
Builtin
160169
Catch
161170
Default
162171
MacroRules
163172
Raw
173+
Reuse
174+
ContractEnsures
175+
ContractRequires
176+
Safe
164177
Union
178+
Yeet
165179
]
166180

167181
let RustPrelude =
168182
[
169-
"Copy"
183+
// Re-exported core operators
170184
"Send"
171185
"Sized"
172186
"Sync"
173187
"Unpin"
174-
"drop"
175188
"Drop"
176189
"Fn"
177190
"FnMut"
178191
"FnOnce"
179-
"Box"
180-
"ToOwned"
181-
"Clone"
182-
"PartialEq"
183-
"PartialOrd"
184-
"Eq"
185-
"Ord"
186-
"AsRef"
192+
"AsyncFn"
193+
"AsyncFnMut"
194+
"AsyncFnOnce"
195+
196+
// Re-exported types and traits
187197
"AsMut"
188-
"Into"
198+
"AsRef"
189199
"From"
190-
"Default"
191-
"Iterator"
192-
"Extend"
193-
"IntoIterator"
200+
"Into"
194201
"DoubleEndedIterator"
195202
"ExactSizeIterator"
203+
"Extend"
204+
"IntoIterator"
205+
"Iterator"
196206
"Option"
197-
"Some"
198207
"None"
208+
"Some"
199209
"Result"
200-
"Ok"
201210
"Err"
211+
"Ok"
212+
213+
// derive macros
214+
"Clone"
215+
"Copy"
216+
// "Debug"
217+
"Default"
218+
"Eq"
219+
// "Hash"
220+
"Ord"
221+
"PartialEq"
222+
"PartialOrd"
223+
224+
// items from the alloc crate
225+
"ToOwned"
226+
"Box"
202227
"String"
203228
"ToString"
204-
"TryFrom"
205-
"TryInto"
206229
"Vec"
207-
"FromIterator"
230+
231+
// // Re-exported functions
232+
// "drop"
233+
// "align_of"
234+
// "align_of_val"
235+
// "size_of"
236+
// "size_of_val"
237+
238+
// // Re-exported built-in macros
239+
// "assert"
240+
// "cfg"
241+
// "column"
242+
// "compile_error"
243+
// "concat"
244+
// "concat_idents"
245+
// "env"
246+
// "file"
247+
// "format_args"
248+
// "format_args_nl"
249+
// "include"
250+
// "include_bytes"
251+
// "include_str"
252+
// "line"
253+
// "log_syntax"
254+
// "module_path"
255+
// "option_env"
256+
// "stringify"
257+
// "trace_macros"
258+
259+
// "alloc_error_handler"
260+
// "bench"
261+
// "derive"
262+
// "global_allocator"
263+
// "test"
264+
// "test_case"
265+
208266
]
209267

268+
(*
269+
210270
// Pre-interned symbols that can be referred to with `rustc_span::sym::*`.
211271
//
212272
// The symbol is the stringified identifier unless otherwise specified, in
213273
// which case the name should mention the non-identifier punctuation.
214-
// E.g. `sym::proc_dash_macro` represents "proc-macro", and it shouldn't be
274+
// E.g. `sym::proc_dash_macro` represents "proc-macro" and it shouldn't be
215275
// called `sym::proc_macro` because then it's easy to mistakenly think it
216276
// represents "proc_macro".
217277
//
218278
// As well as the symbols listed, there are symbols for the strings
219-
// "0", "1", ..., "9", which are accessible via `sym::integer`.
279+
// "0" "1" ..., "9" which are accessible via `sym::integer`.
220280
//
221281
// The proc macro will abort if symbols are not in alphabetical order (as
222282
// defined by `impl Ord for str`) or if any symbols are duplicated. Vim
@@ -1426,7 +1486,7 @@ module sym =
14261486
let xmm_reg = "xmm_reg"
14271487
let ymm_reg = "ymm_reg"
14281488
let zmm_reg = "zmm_reg"
1429-
1489+
*)
14301490
(*
14311491
14321492
type Symbol with

src/Fable.Transforms/Rust/Fable2Rust.fs

+10-5
Original file line numberDiff line numberDiff line change
@@ -3563,7 +3563,7 @@ module Util =
35633563

35643564
let fnBody = strBody |> Seq.map mkEmitSemiStmt |> mkBlock |> Some
35653565

3566-
let attrs = []
3566+
let attrs = [ mkAttr "cfg" [ "not(feature = \"no_std\")" ] ]
35673567
let fnDecl = mkFnDecl [] VOID_RETURN_TY
35683568
let fnKind = mkFnKind DEFAULT_FN_HEADER fnDecl NO_GENERICS fnBody
35693569
let fnItem = mkFnItem attrs "main" fnKind
@@ -4125,8 +4125,13 @@ module Util =
41254125
let returnType = memb.ReturnParameter.Type
41264126
transformFunc com ctx parameters returnType (Some memb.FullName) decl.Args decl.Body
41274127

4128+
let isUnsafe =
4129+
memb.Attributes |> Seq.exists (fun a -> a.Entity.FullName = Atts.rustUnsafe)
4130+
41284131
let fnBodyBlock =
4129-
if decl.Body.Type = Fable.Unit then
4132+
if isUnsafe then
4133+
fnBody |> mkUnsafeBlockExpr |> mkBodyBlock
4134+
else if decl.Body.Type = Fable.Unit then
41304135
mkSemiBlock fnBody
41314136
else
41324137
mkExprBlock fnBody
@@ -5403,9 +5408,8 @@ module Compiler =
54035408
let topAttrs =
54045409
[
54055410
if isLastFileInProject com then
5406-
// adds "no_std" for fable library crate if feature is enabled
5407-
if isFableLibrary com then
5408-
mkInnerAttr "cfg_attr" [ "feature = \"no_std\""; "no_std" ]
5411+
// adds "no_std" to crate if feature is enabled
5412+
mkInnerAttr "cfg_attr" [ "feature = \"no_std\""; "no_std" ]
54095413

54105414
// TODO: make some of those conditional on compiler options
54115415
mkInnerAttr "allow" [ "dead_code" ]
@@ -5419,6 +5423,7 @@ module Compiler =
54195423
mkInnerAttr "allow" [ "unused_parens" ]
54205424
mkInnerAttr "allow" [ "unused_variables" ]
54215425
mkInnerAttr "allow" [ "unused_assignments" ]
5426+
mkInnerAttr "allow" [ "unused_unsafe" ]
54225427

54235428
// these require nightly
54245429
// mkInnerAttr "feature" ["stmt_expr_attributes"]

src/fable-library-dart/List.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,9 @@ let foldBack2<'T1, 'T2, 'State> (folder: 'T1 -> 'T2 -> 'State -> 'State) (xs: 'T
262262
// fold2 (fun acc x y -> folder x y acc) state (reverse xs) (reverse ys)
263263
Array.foldBack2 folder (toArray xs) (toArray ys) state
264264

265-
let unfold<'T, 'State> (gen: 'State -> ('T * 'State) option) (state: 'State) =
265+
let unfold<'T, 'State> (generator: 'State -> ('T * 'State) option) (state: 'State) =
266266
let rec loop acc (node: 'T list) =
267-
match gen acc with
267+
match generator acc with
268268
| None -> node
269269
| Some(x, acc) -> loop acc (node.AppendConsNoTail x)
270270

src/fable-library-py/fable_library/List.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,9 @@ let foldBack2<'T1, 'T2, 'State> (folder: 'T1 -> 'T2 -> 'State -> 'State) (xs: 'T
285285
// fold2 (fun acc x y -> folder x y acc) state (reverse xs) (reverse ys)
286286
Array.foldBack2 folder (toArray xs) (toArray ys) state
287287

288-
let unfold (gen: 'State -> ('T * 'State) option) (state: 'State) =
288+
let unfold (generator: 'State -> ('T * 'State) option) (state: 'State) =
289289
let rec loop acc (node: 'T list) =
290-
match gen acc with
290+
match generator acc with
291291
| None -> node
292292
| Some(x, acc) -> loop acc (node.AppendConsNoTail x)
293293

src/fable-library-rust/Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "fable_library_rust"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2024"
55

66
[features]
77
atomic = []
@@ -22,7 +22,7 @@ default = ["bigint", "datetime", "decimal", "enum_func", "enum_string", "guid",
2222
chrono = { version = "0.4", optional = true }
2323
futures = { version = "0.3", features = ["executor", "thread-pool"], default-features = false, optional = true }
2424
futures-timer = { version = "3.0", optional = true }
25-
hashbrown = { version = "0.14", optional = true }
25+
hashbrown = { version = "0.15", optional = true }
2626
num-bigint = { version = "0.4", optional = true }
2727
num-integer = { version = "0.1", optional = true }
2828
num-traits = { version = "0.2", optional = true }
@@ -31,7 +31,7 @@ rust_decimal = { version = "1.36", features = ["maths"], default-features = fals
3131
startup = { version = "0.1", path = "vendored/startup", optional = true }
3232

3333
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
34-
uuid = { version = "1.13", features = ["v4"], default-features = false, optional = true }
34+
uuid = { version = "1.14", features = ["v4"], default-features = false, optional = true }
3535

3636
[target.'cfg(target_arch = "wasm32")'.dependencies]
37-
uuid = { version = "1.13", features = ["v4", "js"], default-features = false, optional = true }
37+
uuid = { version = "1.14", features = ["v4", "js"], default-features = false, optional = true }

0 commit comments

Comments
 (0)