Skip to content

Commit 1b50168

Browse files
authored
More ValueOption in compiler: part 2 (#16567)
* More ValueOption in complier: part 2 * Update release notes * extra optimization * extra optimization 2 * fantomas
1 parent 641d0ee commit 1b50168

File tree

14 files changed

+227
-149
lines changed

14 files changed

+227
-149
lines changed

docs/release-notes/.FSharp.Compiler.Service/8.0.300.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
* Autogenerated .Is* members for unions skipped for single-case unions. ([PR 16571](https://github.com/dotnet/fsharp/pull/16571))
1616
* `implicitCtorSynPats` in `SynTypeDefnSimpleRepr.General` is now `SynPat option` instead of `SynSimplePats option`. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
1717
* `SyntaxVisitorBase<'T>.VisitSimplePats` now takes `SynPat` instead of `SynSimplePat list`. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
18-
* Reduce allocations in compiler checking via `ValueOption` usage ([PR #16323](https://github.com/dotnet/fsharp/pull/16323))
18+
* Reduce allocations in compiler checking via `ValueOption` usage ([PR #16323](https://github.com/dotnet/fsharp/pull/16323), [PR #16567](https://github.com/dotnet/fsharp/pull/16567))
1919
* Reverted [#16348](https://github.com/dotnet/fsharp/pull/16348) `ThreadStatic` `CancellationToken` changes to improve test stability and prevent potential unwanted cancellations. ([PR #16536](https://github.com/dotnet/fsharp/pull/16536))
2020
* Refactored parenthesization API. ([PR #16461])(https://github.com/dotnet/fsharp/pull/16461))

src/Compiler/Optimize/DetupleArgs.fs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,15 @@ let DetupleRewriteStackGuardDepth = StackGuard.GetDepthOption "DetupleRewrite"
150150

151151

152152
// Merge a tyapp node and and app node.
153+
[<return: Struct>]
153154
let (|TyappAndApp|_|) e =
154155
match e with
155156
| Expr.App(f, fty, tys, args, m) ->
156157
match stripDebugPoints (stripExpr f) with
157-
| Expr.App(f2, fty2, tys2, [], m2) -> Some(f2, fty2, tys2 @ tys, args, m2)
158-
| Expr.App _ -> Some(f, fty, tys, args, m) (* has args, so not combine ty args *)
159-
| f -> Some(f, fty, tys, args, m)
160-
| _ -> None
158+
| Expr.App(f2, fty2, tys2, [], m2) -> ValueSome(f2, fty2, tys2 @ tys, args, m2)
159+
| Expr.App _ -> ValueSome(f, fty, tys, args, m) (* has args, so not combine ty args *)
160+
| f -> ValueSome(f, fty, tys, args, m)
161+
| _ -> ValueNone
161162

162163
[<AutoOpen>]
163164
module GlobalUsageAnalysis =

src/Compiler/Optimize/LowerComputedCollections.fs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,27 +230,30 @@ let (|OptionalCoerce|) expr =
230230

231231
// Making 'seq' optional means this kicks in for FSharp.Core, see TcArrayOrListComputedExpression
232232
// which only adds a 'seq' call outside of FSharp.Core
233+
[<return: Struct>]
233234
let (|OptionalSeq|_|) g amap expr =
234235
match expr with
235236
// use 'seq { ... }' as an indicator
236237
| Seq g (e, elemTy) ->
237-
Some (e, elemTy)
238+
ValueSome (e, elemTy)
238239
| _ ->
239240
// search for the relevant element type
240241
match tyOfExpr g expr with
241242
| SeqElemTy g amap expr.Range elemTy ->
242-
Some (expr, elemTy)
243-
| _ -> None
243+
ValueSome (expr, elemTy)
244+
| _ -> ValueNone
244245

246+
[<return: Struct>]
245247
let (|SeqToList|_|) g expr =
246248
match expr with
247-
| ValApp g g.seq_to_list_vref (_, [seqExpr], m) -> Some (seqExpr, m)
248-
| _ -> None
249+
| ValApp g g.seq_to_list_vref (_, [seqExpr], m) -> ValueSome (seqExpr, m)
250+
| _ -> ValueNone
249251

252+
[<return: Struct>]
250253
let (|SeqToArray|_|) g expr =
251254
match expr with
252-
| ValApp g g.seq_to_array_vref (_, [seqExpr], m) -> Some (seqExpr, m)
253-
| _ -> None
255+
| ValApp g g.seq_to_array_vref (_, [seqExpr], m) -> ValueSome (seqExpr, m)
256+
| _ -> ValueNone
254257

255258
let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
256259
// If ListCollector is in FSharp.Core then this optimization kicks in

src/Compiler/Optimize/LowerSequences.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,16 @@ let tyConfirmsToSeq g ty =
7474
tyconRefEq g tcref g.tcref_System_Collections_Generic_IEnumerable
7575
| _ -> false
7676

77+
[<return: Struct>]
7778
let (|SeqElemTy|_|) g amap m ty =
7879
match SearchEntireHierarchyOfType (tyConfirmsToSeq g) g amap m ty with
7980
| None ->
8081
// printfn "FAILED - yield! did not yield a sequence! %s" (stringOfRange m)
81-
None
82+
ValueNone
8283
| Some seqTy ->
8384
// printfn "found yield!"
8485
let inpElemTy = List.head (argsOfAppTy g seqTy)
85-
Some inpElemTy
86+
ValueSome inpElemTy
8687

8788
/// Analyze a TAST expression to detect the elaborated form of a sequence expression.
8889
/// Then compile it to a state machine represented as a TAST containing goto, return and label nodes.

src/Compiler/Optimize/LowerSequences.fsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ open FSharp.Compiler.TypedTree
99
open FSharp.Compiler.Text
1010

1111
/// Detect a 'seq<int>' type
12-
val (|SeqElemTy|_|): TcGlobals -> ImportMap -> range -> TType -> TType option
12+
[<return: Struct>]
13+
val (|SeqElemTy|_|): TcGlobals -> ImportMap -> range -> TType -> TType voption
1314

1415
val callNonOverloadedILMethod:
1516
g: TcGlobals -> amap: ImportMap -> m: range -> methName: string -> ty: TType -> args: Exprs -> Expr

src/Compiler/Optimize/LowerStateMachines.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ type LowerStateMachine(g: TcGlobals) =
377377
| None -> env2, expr2
378378

379379
// Detect a state machine with a single method override
380+
[<return: Struct>]
380381
let (|ExpandedStateMachineInContext|_|) inputExpr =
381382
// All expanded resumable code state machines e.g. 'task { .. }' begin with a bind of @builder or 'defn'
382383
let env, expr = BindResumableCodeDefinitions env.Empty inputExpr
@@ -405,9 +406,9 @@ type LowerStateMachine(g: TcGlobals) =
405406
(moveNextThisVar, moveNextExprR),
406407
(setStateMachineThisVar, setStateMachineStateVar, setStateMachineBodyR),
407408
(afterCodeThisVar, afterCodeBodyR))
408-
Some (env, remake2, moveNextBody)
409+
ValueSome (env, remake2, moveNextBody)
409410
| _ ->
410-
None
411+
ValueNone
411412

412413
// A utility to add a jump table an expression
413414
let addPcJumpTable m (pcs: int list) (pc2lab: Map<int, ILCodeLabel>) pcExpr expr =

src/Compiler/Optimize/Optimizer.fs

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -703,15 +703,17 @@ let rec stripValue = function
703703
| SizeValue(_, details) -> stripValue details (* step through SizeValue "aliases" *)
704704
| vinfo -> vinfo
705705

706+
[<return: Struct>]
706707
let (|StripConstValue|_|) ev =
707708
match stripValue ev with
708-
| ConstValue(c, _) -> Some c
709-
| _ -> None
709+
| ConstValue(c, _) -> ValueSome c
710+
| _ -> ValueNone
710711

712+
[<return: Struct>]
711713
let (|StripLambdaValue|_|) ev =
712714
match stripValue ev with
713-
| CurriedLambdaValue (id, arity, sz, expr, ty) -> Some (id, arity, sz, expr, ty)
714-
| _ -> None
715+
| CurriedLambdaValue (id, arity, sz, expr, ty) -> ValueSome (id, arity, sz, expr, ty)
716+
| _ -> ValueNone
715717

716718
let destTupleValue ev =
717719
match stripValue ev with
@@ -723,10 +725,11 @@ let destRecdValue ev =
723725
| RecdValue (_tcref, info) -> Some info
724726
| _ -> None
725727

728+
[<return: Struct>]
726729
let (|StripUnionCaseValue|_|) ev =
727730
match stripValue ev with
728-
| UnionCaseValue (c, info) -> Some (c, info)
729-
| _ -> None
731+
| UnionCaseValue (c, info) -> ValueSome (c, info)
732+
| _ -> ValueNone
730733

731734
let mkBoolVal (g: TcGlobals) n = ConstValue(Const.Bool n, g.bool_ty)
732735

@@ -1764,26 +1767,29 @@ let TryEliminateLet cenv env bind e2 m =
17641767
| None -> mkLetBind m bind e2, 0
17651768

17661769
/// Detect the application of a value to an arbitrary number of arguments
1770+
[<return: Struct>]
17671771
let rec (|KnownValApp|_|) expr =
17681772
match stripDebugPoints expr with
1769-
| Expr.Val (vref, _, _) -> Some(vref, [], [])
1770-
| Expr.App (KnownValApp(vref, typeArgs1, otherArgs1), _, typeArgs2, otherArgs2, _) -> Some(vref, typeArgs1@typeArgs2, otherArgs1@otherArgs2)
1771-
| _ -> None
1773+
| Expr.Val (vref, _, _) -> ValueSome(vref, [], [])
1774+
| Expr.App (KnownValApp(vref, typeArgs1, otherArgs1), _, typeArgs2, otherArgs2, _) -> ValueSome(vref, typeArgs1@typeArgs2, otherArgs1@otherArgs2)
1775+
| _ -> ValueNone
17721776

17731777
/// Matches boolean decision tree:
17741778
/// check single case with bool const.
1779+
[<return: Struct>]
17751780
let (|TDBoolSwitch|_|) dtree =
17761781
match dtree with
17771782
| TDSwitch(expr, [TCase (DecisionTreeTest.Const(Const.Bool testBool), caseTree )], Some defaultTree, range) ->
1778-
Some (expr, testBool, caseTree, defaultTree, range)
1783+
ValueSome (expr, testBool, caseTree, defaultTree, range)
17791784
| _ ->
1780-
None
1785+
ValueNone
17811786

17821787
/// Check target that have a constant bool value
1788+
[<return: Struct>]
17831789
let (|ConstantBoolTarget|_|) target =
17841790
match target with
1785-
| TTarget([], Expr.Const (Const.Bool b, _, _), _) -> Some b
1786-
| _ -> None
1791+
| TTarget([], Expr.Const (Const.Bool b, _, _), _) -> ValueSome b
1792+
| _ -> ValueNone
17871793

17881794
/// Is this a tree, where each decision is a two-way switch (to prevent later duplication of trees), and each branch returns or true/false,
17891795
/// apart from one branch which defers to another expression
@@ -2053,50 +2059,59 @@ let ExpandStructuralBinding cenv expr =
20532059
ExpandStructuralBindingRaw cenv e
20542060

20552061
/// Detect a query { ... }
2062+
[<return: Struct>]
20562063
let (|QueryRun|_|) g expr =
20572064
match expr with
20582065
| Expr.App (Expr.Val (vref, _, _), _, _, [_builder; arg], _) when valRefEq g vref g.query_run_value_vref ->
2059-
Some (arg, None)
2066+
ValueSome (arg, None)
20602067
| Expr.App (Expr.Val (vref, _, _), _, [ elemTy ], [_builder; arg], _) when valRefEq g vref g.query_run_enumerable_vref ->
2061-
Some (arg, Some elemTy)
2068+
ValueSome (arg, Some elemTy)
20622069
| _ ->
2063-
None
2070+
ValueNone
20642071

20652072
let (|MaybeRefTupled|) e = tryDestRefTupleExpr e
20662073

2074+
[<return: Struct>]
20672075
let (|AnyInstanceMethodApp|_|) e =
20682076
match e with
2069-
| Expr.App (Expr.Val (vref, _, _), _, tyargs, [obj; MaybeRefTupled args], _) -> Some (vref, tyargs, obj, args)
2070-
| _ -> None
2077+
| Expr.App (Expr.Val (vref, _, _), _, tyargs, [obj; MaybeRefTupled args], _) -> ValueSome (vref, tyargs, obj, args)
2078+
| _ -> ValueNone
20712079

2080+
[<return: Struct>]
20722081
let (|InstanceMethodApp|_|) g (expectedValRef: ValRef) e =
20732082
match e with
2074-
| AnyInstanceMethodApp (vref, tyargs, obj, args) when valRefEq g vref expectedValRef -> Some (tyargs, obj, args)
2075-
| _ -> None
2083+
| AnyInstanceMethodApp (vref, tyargs, obj, args) when valRefEq g vref expectedValRef -> ValueSome (tyargs, obj, args)
2084+
| _ -> ValueNone
20762085

2086+
[<return: Struct>]
20772087
let (|QuerySourceEnumerable|_|) g = function
2078-
| InstanceMethodApp g g.query_source_vref ([resTy], _builder, [res]) -> Some (resTy, res)
2079-
| _ -> None
2088+
| InstanceMethodApp g g.query_source_vref ([resTy], _builder, [res]) -> ValueSome (resTy, res)
2089+
| _ -> ValueNone
20802090

2091+
[<return: Struct>]
20812092
let (|QueryFor|_|) g = function
2082-
| InstanceMethodApp g g.query_for_vref ([srcTy;qTy;resTy;_qInnerTy], _builder, [src;selector]) -> Some (qTy, srcTy, resTy, src, selector)
2083-
| _ -> None
2093+
| InstanceMethodApp g g.query_for_vref ([srcTy;qTy;resTy;_qInnerTy], _builder, [src;selector]) -> ValueSome (qTy, srcTy, resTy, src, selector)
2094+
| _ -> ValueNone
20842095

2096+
[<return: Struct>]
20852097
let (|QueryYield|_|) g = function
2086-
| InstanceMethodApp g g.query_yield_vref ([resTy;qTy], _builder, [res]) -> Some (qTy, resTy, res)
2087-
| _ -> None
2098+
| InstanceMethodApp g g.query_yield_vref ([resTy;qTy], _builder, [res]) -> ValueSome (qTy, resTy, res)
2099+
| _ -> ValueNone
20882100

2101+
[<return: Struct>]
20892102
let (|QueryYieldFrom|_|) g = function
2090-
| InstanceMethodApp g g.query_yield_from_vref ([resTy;qTy], _builder, [res]) -> Some (qTy, resTy, res)
2091-
| _ -> None
2103+
| InstanceMethodApp g g.query_yield_from_vref ([resTy;qTy], _builder, [res]) -> ValueSome (qTy, resTy, res)
2104+
| _ -> ValueNone
20922105

2106+
[<return: Struct>]
20932107
let (|QuerySelect|_|) g = function
2094-
| InstanceMethodApp g g.query_select_vref ([srcTy;qTy;resTy], _builder, [src;selector]) -> Some (qTy, srcTy, resTy, src, selector)
2095-
| _ -> None
2108+
| InstanceMethodApp g g.query_select_vref ([srcTy;qTy;resTy], _builder, [src;selector]) -> ValueSome (qTy, srcTy, resTy, src, selector)
2109+
| _ -> ValueNone
20962110

2111+
[<return: Struct>]
20972112
let (|QueryZero|_|) g = function
2098-
| InstanceMethodApp g g.query_zero_vref ([resTy;qTy], _builder, _) -> Some (qTy, resTy)
2099-
| _ -> None
2113+
| InstanceMethodApp g g.query_zero_vref ([resTy;qTy], _builder, _) -> ValueSome (qTy, resTy)
2114+
| _ -> ValueNone
21002115

21012116
/// Look for a possible tuple and transform
21022117
let (|AnyRefTupleTrans|) e =
@@ -2105,11 +2120,12 @@ let (|AnyRefTupleTrans|) e =
21052120
| _ -> [e], (function [e] -> e | _ -> assert false; failwith "unreachable")
21062121

21072122
/// Look for any QueryBuilder.* operation and transform
2123+
[<return: Struct>]
21082124
let (|AnyQueryBuilderOpTrans|_|) g = function
21092125
| Expr.App (Expr.Val (vref, _, _) as v, vty, tyargs, [builder; AnyRefTupleTrans( src :: rest, replaceArgs) ], m) when
21102126
(match vref.ApparentEnclosingEntity with Parent tcref -> tyconRefEq g tcref g.query_builder_tcref | ParentNone -> false) ->
2111-
Some (src, (fun newSource -> Expr.App (v, vty, tyargs, [builder; replaceArgs(newSource :: rest)], m)))
2112-
| _ -> None
2127+
ValueSome (src, (fun newSource -> Expr.App (v, vty, tyargs, [builder; replaceArgs(newSource :: rest)], m)))
2128+
| _ -> ValueNone
21132129

21142130
/// If this returns "Some" then the source is not IQueryable.
21152131
// <qexprInner> :=

src/Compiler/Service/ServiceLexing.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,8 +1042,8 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, maxLength: int option, fi
10421042
false, (RQUOTE(s, raw), leftc, rightc - 1)
10431043
| INFIX_COMPARE_OP(LexFilter.TyparsCloseOp(greaters, afterOp) as opstr) ->
10441044
match afterOp with
1045-
| None -> ()
1046-
| Some tok -> delayToken (tok, leftc + greaters.Length, rightc)
1045+
| ValueNone -> ()
1046+
| ValueSome tok -> delayToken (tok, leftc + greaters.Length, rightc)
10471047

10481048
for i = greaters.Length - 1 downto 1 do
10491049
delayToken (greaters[i]false, leftc + i, rightc - opstr.Length + i + 1)

0 commit comments

Comments
 (0)