Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7b39820
Optimizer: don't inline named functions in debug builds
auduchinok Apr 3, 2026
b74663a
Xlf
auduchinok Apr 7, 2026
1b31523
Release notes
auduchinok Apr 7, 2026
d4d2252
Don't specialize local functions
auduchinok Apr 7, 2026
0d04e2a
Remove specialized values caching
auduchinok Apr 7, 2026
560a73f
Fix witness passing
auduchinok Apr 8, 2026
adf51a2
Inline NoDynamicInvocation and some builtin functions
auduchinok Apr 9, 2026
a3d60f1
Add more tests
auduchinok Apr 9, 2026
3c3c117
More witness fixes
auduchinok Apr 11, 2026
dc7ff4d
Don't check accessibility for non-inlined functions
auduchinok Apr 10, 2026
3cbd30c
Fix
auduchinok Apr 12, 2026
0dec28a
Fix cross-file inline same collision
auduchinok Apr 12, 2026
5172283
More SRTP
auduchinok Apr 12, 2026
bb103c9
Accessibility
auduchinok Apr 13, 2026
3d8e22e
Fantomas
auduchinok Apr 13, 2026
b54e232
Inline when extra optimization loops
auduchinok Apr 13, 2026
5b80d99
Specialize signature-hidden values
auduchinok Apr 13, 2026
871aa21
Byref
auduchinok Apr 14, 2026
e788de0
Add more tests
auduchinok Apr 14, 2026
caedcfb
Another accessibility attempt
auduchinok Apr 15, 2026
4bbb88d
Fix inlined definition check
auduchinok Apr 15, 2026
31c9710
Fix referencing debug builds from optimized
auduchinok Apr 15, 2026
cd5ca1c
Update baselines
auduchinok Apr 15, 2026
9279124
Nested inline with different type args
auduchinok Apr 15, 2026
900c4d9
Pickle ValInline.InlinedDefinition as ValInline.Always
auduchinok Apr 16, 2026
e930280
Better cross-file name collision fix
auduchinok Apr 18, 2026
4588314
Better byref fix
auduchinok Apr 18, 2026
2ca211c
Better SRTP fix
auduchinok Apr 18, 2026
c08a106
Another byref fix
auduchinok Apr 20, 2026
116b1f7
Update baselines
auduchinok Apr 20, 2026
e1440d3
Update baselines
auduchinok Apr 21, 2026
5ba6231
Cleanup
auduchinok Apr 21, 2026
ec8dbbe
Add MSBuild property
auduchinok Apr 21, 2026
e2ad598
Update IcedTasks, FsToolkit.ErrorHandling CI legs revisions
auduchinok Apr 21, 2026
cb2d065
Don't inline lambdas
auduchinok Apr 21, 2026
26ac104
Rename inlineNamedFunctions to alwaysInline
auduchinok Apr 21, 2026
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
8 changes: 4 additions & 4 deletions azure-pipelines-PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -859,19 +859,19 @@ stages:
useVmImage: $(LinuxMachineQueueName)
usePool: $(DncEngPublicBuildPool)
- repo: TheAngryByrd/IcedTasks
commit: 863bf91cdee93d8c4c875bb5d321dd92eb20d5a9
commit: 5453025da1cd3db8aebe9283a9ff190062a703e0
buildScript: dotnet build IcedTasks.sln -bl
displayName: IcedTasks_Build
- repo: TheAngryByrd/IcedTasks
commit: 863bf91cdee93d8c4c875bb5d321dd92eb20d5a9
commit: 5453025da1cd3db8aebe9283a9ff190062a703e0
buildScript: dotnet test IcedTasks.sln -bl
displayName: IcedTasks_Test
- repo: demystifyfp/FsToolkit.ErrorHandling
commit: 9cd957e335767df03e2fb0aa2f7b0fed782c5091
commit: a9348686498ad59eff41efe63ee2160e3902492c
buildScript: dotnet build FsToolkit.ErrorHandling.sln -bl
displayName: FsToolkit_ErrorHandling_Build
- repo: demystifyfp/FsToolkit.ErrorHandling
commit: 9cd957e335767df03e2fb0aa2f7b0fed782c5091
commit: a9348686498ad59eff41efe63ee2160e3902492c
buildScript: dotnet test FsToolkit.ErrorHandling.sln -bl
displayName: FsToolkit_ErrorHandling_Test
- repo: opentk/opentk
Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@
* Improvements in error and warning messages: new error FS3885 when `let!`/`use!` is the final expression in a computation expression; new warning FS3886 when a list literal contains a single tuple element (likely missing `;` separator); improved wording for FS0003, FS0025, FS0039, FS0072, FS0247, FS0597, FS0670, FS3082, and SRTP operator-not-in-scope hints. ([PR #19398](https://github.com/dotnet/fsharp/pull/19398))

### Breaking Changes
* Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548)
40 changes: 37 additions & 3 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ type IlxGenOptions =

/// When set to true, the IlxGen will delay generation of method bodies and generated them later in parallel (parallelized across files)
parallelIlxGenEnabled: bool

alwaysInline: bool
}

/// Compilation environment for compiling a fragment of an assembly
Expand Down Expand Up @@ -5682,8 +5684,13 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp

| None ->

// If witnesses are available, we should now always find trait witnesses in scope
assert not generateWitnesses
// When alwaysInline is true, all trait calls should be resolved via witnesses in scope.
// When alwaysInline is false, inline functions are kept as calls rather than inlined.
// Their witness arguments may contain TraitCall operations for constraints that were resolved
// without a witness (e.g., when the constraint is satisfied by a known concrete type).
// In such cases, generateWitnesses can be true (because other witnesses are in scope) but
// the specific trait's witness is not found. Fall through to the constraint solver to resolve it.
assert (not generateWitnesses || not cenv.options.alwaysInline)

let exprOpt =
CommitOperationResult(ConstraintSolver.CodegenWitnessExprForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs)
Expand Down Expand Up @@ -7132,7 +7139,19 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames
let cloName =
// Ensure that we have an g.CompilerGlobalState
assert (g.CompilerGlobalState |> Option.isSome)
g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, expr.Range, uniq)
// The closure name counter is keyed by (basicName, fileIndex). When an expression is copied
// from another file (e.g. specializing an inline function body across files), its ranges
// still point at the original file, so its closures fall into a different counter bucket
// than closures minted for the current file. Since all these closures live under the same
// enclosing type, that can produce two closures with the same final name. Bucket the counter
// by the enclosing type's file while keeping expr.Range's StartLine for the displayed name.
let nameRange =
if expr.Range.FileIndex = eenv.cloc.Range.FileIndex then
expr.Range
else
Range.mkFileIndexRange eenv.cloc.Range.FileIndex expr.Range.Start expr.Range.End

g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, nameRange, uniq)

let ilCloTypeRef = NestedTypeRefForCompLoc eenv.cloc cloName

Expand Down Expand Up @@ -7190,6 +7209,21 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames

let cloFreeTyvars = cloFreeTyvars.FreeTypars |> Zset.elements

// When generating witnesses, witness types may reference type variables that appear
// only in SRTP constraints of the captured type variables (e.g. 'b in 'a : (member M: unit -> 'b)).
// Include those so they are available when generating witness field types.
let cloFreeTyvars =
if ComputeGenerateWitnesses g eenv then
let extra =
GetTraitWitnessInfosOfTypars g 0 cloFreeTyvars
|> List.collect (fun w ->
(freeInType CollectTyparsNoCaching (GenWitnessTy g w)).FreeTypars
|> Zset.elements)

(cloFreeTyvars @ extra) |> List.distinctBy (fun tp -> tp.Stamp)
else
cloFreeTyvars

let eenvinner = eenv |> EnvForTypars cloFreeTyvars

let ilCloTyInner =
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/CodeGen/IlxGen.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type internal IlxGenOptions =

/// When set to true, the IlxGen will delay generation of method bodies and generate them later in parallel (parallelized across files)
parallelIlxGenEnabled: bool

/// Indicates if inline functions are being inlined or emitted as calls
alwaysInline: bool
}

/// The results of the ILX compilation of one fragment of an assembly
Expand Down
12 changes: 12 additions & 0 deletions src/Compiler/Driver/CompilerConfig.fs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,8 @@ type TcConfigBuilder =

mutable strictIndentation: bool option

mutable alwaysInline: bool option

mutable exename: string option

// If true - the compiler will copy FSharp.Core.dll along the produced binaries
Expand Down Expand Up @@ -853,6 +855,7 @@ type TcConfigBuilder =
dumpSignatureData = false
realsig = false
strictIndentation = None
alwaysInline = None
compilationMode = TcGlobals.CompilationMode.Unset
}

Expand Down Expand Up @@ -1253,6 +1256,15 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
member _.fsiMultiAssemblyEmit = data.fsiMultiAssemblyEmit
member _.FxResolver = data.FxResolver
member _.strictIndentation = data.strictIndentation

member _.alwaysInline =
data.alwaysInline
|> Option.defaultValue (
not data.debuginfo
|| data.optSettings.LocalOptimizationsEnabled
|| data.extraOptimizationIterations > 0
)

member _.primaryAssembly = data.primaryAssembly
member _.noFeedback = data.noFeedback
member _.stackReserveSize = data.stackReserveSize
Expand Down
4 changes: 4 additions & 0 deletions src/Compiler/Driver/CompilerConfig.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,8 @@ type TcConfigBuilder =

mutable strictIndentation: bool option

mutable alwaysInline: bool option

mutable exename: string option

mutable copyFSharpCore: CopyFSharpCoreFlag
Expand Down Expand Up @@ -814,6 +816,8 @@ type TcConfig =

member strictIndentation: bool option

member alwaysInline: bool

member GetTargetFrameworkDirectories: unit -> string list

/// Get the loaded sources that exist and issue a warning for the ones that don't
Expand Down
8 changes: 8 additions & 0 deletions src/Compiler/Driver/CompilerOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,14 @@ let languageFlags tcConfigB =
None,
Some(FSComp.SR.optsStrictIndentation (formatOptionSwitch (Option.defaultValue false tcConfigB.strictIndentation)))
)

CompilerOption(
"always-inline",
tagNone,
OptionSwitch(fun switch -> tcConfigB.alwaysInline <- Some(switch = OptionSwitch.On)),
None,
Some(FSComp.SR.optsAlwaysInline ())
)
]

// OptionBlock: Advanced user options
Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/Driver/OptimizeInputs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ let ApplyAllOptimizations
// Only do abstractBigTargets in the first phase, and only when TLR is on.
abstractBigTargets = tcConfig.doTLR
reportingPhase = true
alwaysInline = tcConfig.alwaysInline
}

// Only do these two steps in the first phase.
Expand Down Expand Up @@ -578,6 +579,7 @@ let GenerateIlxCode
isInteractiveItExpr = isInteractiveItExpr
alwaysCallVirt = tcConfig.alwaysCallVirt
parallelIlxGenEnabled = tcConfig.parallelIlxGen
alwaysInline = tcConfig.alwaysInline
}

ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs)
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,7 @@ optsSetLangVersion,"Specify language version such as 'latest' or 'preview'."
optsDisableLanguageFeature,"Disable a specific language feature by name."
optsSupportedLangVersions,"Supported language versions:"
optsStrictIndentation,"Override indentation rules implied by the language version (%s by default)"
optsAlwaysInline,"Always inline 'inline' functions"
nativeResourceFormatError,"Stream does not begin with a null resource and is not in '.RES' format."
nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed."
formatDashItem," - %s"
Expand Down
Loading
Loading