Skip to content

Commit 9d05359

Browse files
authored
Fix inlining (#17168)
1 parent 63ff188 commit 9d05359

File tree

3 files changed

+87
-15
lines changed

3 files changed

+87
-15
lines changed

src/Compiler/Optimize/Optimizer.fs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,15 +2367,7 @@ let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr =
23672367
OptimizeConst cenv env expr (c, m, ty)
23682368

23692369
| Expr.Val (v, _vFlags, m) ->
2370-
if not (v.Accessibility.IsPrivate) then
2371-
OptimizeVal cenv env expr (v, m)
2372-
else
2373-
expr,
2374-
{ TotalSize = 10
2375-
FunctionSize = 1
2376-
HasEffect = false
2377-
MightMakeCriticalTailcall=false
2378-
Info=UnknownValue }
2370+
OptimizeVal cenv env expr (v, m)
23792371

23802372

23812373
| Expr.Quote (ast, splices, isFromQueryExpression, m, ty) ->
@@ -3086,9 +3078,6 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda,
30863078
let fvs = freeInExpr CollectLocals expr
30873079
if fvs.UsesMethodLocalConstructs then
30883080
// Discarding lambda for binding because uses protected members --- TBD: Should we warn or error here
3089-
None
3090-
elif fvs.FreeLocals |> Seq.exists(fun v -> v.Accessibility.IsPrivate ) then
3091-
// Discarding lambda for binding because uses private members --- TBD: Should we warn or error here
30923081
None
30933082
else
30943083
let exprCopy = CopyExprForInlining cenv inlineIfLambda expr m
@@ -4144,10 +4133,10 @@ and OptimizeBinding cenv isRec env (TBind(vref, expr, spBind)) =
41444133
let fvs = freeInExpr CollectLocals body
41454134
if fvs.UsesMethodLocalConstructs then
41464135
// Discarding lambda for binding because uses protected members
4147-
UnknownValue
4136+
UnknownValue
41484137
elif fvs.FreeLocals.ToArray() |> Seq.fold(fun acc v -> if not acc then v.Accessibility.IsPrivate else acc) false then
41494138
// Discarding lambda for binding because uses private members
4150-
UnknownValue
4139+
UnknownValue
41514140
else
41524141
ivalue
41534142

tests/AheadOfTime/Trimming/check.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) {
4242
# error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
4343

4444
# Check net7.0 trimmed assemblies
45-
CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 285184
45+
CheckTrim -root "SelfContained_Trimming_Test" -tfm "net8.0" -outputfile "FSharp.Core.dll" -expected_len 284672
4646

4747
# Check net8.0 trimmed assemblies
4848
CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net8.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 8818176

tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ module Inlining =
1616
|> ignoreWarnings
1717
|> verifyILBaseline
1818

19+
let withRealInternalSignature realSig compilation =
20+
compilation
21+
|> withOptions [if realSig then "--realsig+" else "--realsig-" ]
22+
1923
// SOURCE=Match01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Match01.dll" # Match01.fs
2024
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"Match01_RealInternalSignatureOn.fs"|])>]
2125
let ``Match01_RealInternalSignatureOn_fs`` compilation =
@@ -139,3 +143,82 @@ let found = data |> List.contains nan
139143
}"""]
140144
#endif
141145

146+
[<InlineData(true)>] // RealSig
147+
[<InlineData(false)>] // Regular
148+
[<Theory>]
149+
let ``Inlining field with private module`` (realSig) =
150+
Fsx """
151+
module private PrivateModule =
152+
let moduleValue = 1
153+
154+
let inline getModuleValue () =
155+
moduleValue
156+
157+
[<EntryPoint>]
158+
let main argv =
159+
// [FS1118] Failed to inline the value 'getModuleValue' marked 'inline', perhaps because a recursive value was marked 'inline'
160+
// (fixed by making PrivateModule internal instead of private)
161+
PrivateModule.getModuleValue () |> ignore
162+
0
163+
"""
164+
|> withOptimize
165+
|> withRealInternalSignature realSig
166+
|> asExe
167+
|> compileAndRun
168+
|> shouldSucceed
169+
170+
[<InlineData(true)>] // RealSig
171+
[<InlineData(false)>] // Regular
172+
[<Theory>]
173+
let ``Inlining field with private class`` (realSig) =
174+
Fsx """
175+
type private FirstType () =
176+
member this.FirstMethod () = ()
177+
178+
type private SecondType () =
179+
member this.SecondMethod () =
180+
let inline callFirstMethod (first: FirstType) =
181+
first.FirstMethod ()
182+
183+
callFirstMethod (FirstType())
184+
185+
printfn $"{(SecondType ()).SecondMethod()}"
186+
"""
187+
|> withOptimize
188+
|> withRealInternalSignature realSig
189+
|> asExe
190+
|> compileAndRun
191+
|> shouldSucceed
192+
193+
[<InlineData(true)>] // RealSig
194+
[<InlineData(false)>] // Regular
195+
[<Theory>]
196+
let ``Inlining deep local functions field with private class`` (realSig) =
197+
Fsx """
198+
type private FirstType () =
199+
member this.FirstMethod () = ()
200+
201+
type private SecondType () =
202+
member this.SecondMethod () =
203+
let inline callFirstMethod (first: FirstType) =
204+
first.FirstMethod ()
205+
206+
let inline callFirstMethodDeeper (first: FirstType) =
207+
callFirstMethod (first)
208+
209+
let inline callFirstMethodMoreDeeper (first: FirstType) =
210+
callFirstMethodDeeper (first)
211+
212+
let inline callFirstMethodMostDeeply (first: FirstType) =
213+
callFirstMethodMoreDeeper (first)
214+
215+
callFirstMethodMostDeeply (FirstType())
216+
217+
printfn $"{(SecondType ()).SecondMethod()}"
218+
"""
219+
|> withOptimize
220+
|> withRealInternalSignature realSig
221+
|> asExe
222+
|> compileAndRun
223+
|> shouldSucceed
224+

0 commit comments

Comments
 (0)