Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6cfb404
Sequence points: rework `for` stepping
auduchinok Jun 4, 2026
655fdcd
Release notes
auduchinok Jun 4, 2026
29cd63c
Update baselines
auduchinok Jun 4, 2026
db1d054
Sequence points: rework conditional erasure, fix stepping over literals
auduchinok Jun 4, 2026
3d762d7
Print source in sequence point dump
auduchinok Jun 5, 2026
e1a3f86
Fantomas
auduchinok Jun 5, 2026
23d8946
Fix hasVisibleDebugPoint, update baselines
auduchinok Jun 5, 2026
aa147a5
Update baselines
auduchinok Jun 5, 2026
fd9f169
Optimizer: don't inline named functions in debug builds
auduchinok Apr 3, 2026
b5dc33a
Xlf
auduchinok Apr 7, 2026
149480b
Release notes
auduchinok Apr 7, 2026
907e4b4
Don't specialize local functions
auduchinok Apr 7, 2026
b2d836f
Remove specialized values caching
auduchinok Apr 7, 2026
7a46f1a
Fix witness passing
auduchinok Apr 8, 2026
591674c
Inline NoDynamicInvocation and some builtin functions
auduchinok Apr 9, 2026
bfa89b9
Add more tests
auduchinok Apr 9, 2026
a0bddb8
More witness fixes
auduchinok Apr 11, 2026
699a9fb
Don't check accessibility for non-inlined functions
auduchinok Apr 10, 2026
dd20e31
Fix
auduchinok Apr 12, 2026
e8fd584
Fix cross-file inline same collision
auduchinok Apr 12, 2026
7f68b8d
More SRTP
auduchinok Apr 12, 2026
7229e86
Accessibility
auduchinok Apr 13, 2026
12c326d
Fantomas
auduchinok Apr 13, 2026
622d88a
Inline when extra optimization loops
auduchinok Apr 13, 2026
f01622f
Specialize signature-hidden values
auduchinok Apr 13, 2026
e4d0964
Byref
auduchinok Apr 14, 2026
9e3f529
Add more tests
auduchinok Apr 14, 2026
f6e73c1
Another accessibility attempt
auduchinok Apr 15, 2026
cdf3bac
Fix inlined definition check
auduchinok Apr 15, 2026
e008872
Fix referencing debug builds from optimized
auduchinok Apr 15, 2026
e7051b6
Nested inline with different type args
auduchinok Apr 15, 2026
242df1e
Pickle ValInline.InlinedDefinition as ValInline.Always
auduchinok Apr 16, 2026
0b4b827
Better cross-file name collision fix
auduchinok Apr 18, 2026
33a5553
Better byref fix
auduchinok Apr 18, 2026
5e6a4a4
Better SRTP fix
auduchinok Apr 18, 2026
e546cd2
Another byref fix
auduchinok Apr 20, 2026
83e64bd
Cleanup
auduchinok Apr 21, 2026
a192cb0
Add MSBuild property
auduchinok Apr 21, 2026
4551a81
Don't inline lambdas
auduchinok Apr 21, 2026
85ac718
Rename inlineNamedFunctions to alwaysInline
auduchinok Apr 21, 2026
da63fe7
Check optimize- only
auduchinok May 13, 2026
0e371f4
Update baselines
auduchinok May 13, 2026
a2cf8d5
Update baselines
auduchinok May 14, 2026
5e967ff
StateMachineTests: enable optimizations
auduchinok Jun 1, 2026
c0b36da
Update debug baselines
auduchinok Jun 1, 2026
827475b
Update baselines
auduchinok Jun 1, 2026
9c3f449
Update baselines
auduchinok Jun 1, 2026
0d73269
Update baselines
auduchinok Jun 5, 2026
765d435
Allow inlining async
auduchinok Jun 6, 2026
c0168aa
Update baselines
auduchinok Jun 6, 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
2 changes: 2 additions & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@
* Added warning FS3884 when a function or delegate value is used as an interpolated string argument. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289))
* Symbols: add ObsoleteDiagnosticInfo ([PR #19359](https://github.com/dotnet/fsharp/pull/19359))
* Add `#version;;` directive to F# Interactive to display version and environment information. ([Issue #13307](https://github.com/dotnet/fsharp/issues/13307), [PR #19332](https://github.com/dotnet/fsharp/pull/19332))
* Debug: rework for expressions stepping ([PR #19894](https://github.com/dotnet/fsharp/pull/19894))

### Changed

* 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))
* Exception field serialization (`GetObjectData` and field-restoring constructor) is now gated behind `langversion:11` (`LanguageFeature.ExceptionFieldSerializationSupport`). With langversion ≤10, exception codegen is unchanged from pre-#19342 behavior. ([PR #19746](https://github.com/dotnet/fsharp/pull/19746))

### Breaking Changes
* Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548)
4 changes: 2 additions & 2 deletions src/Compiler/Checking/CheckIncrementalClasses.fs
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ let MakeCtorForIncrClassConstructionPhase2C(
// Extend the range of any immediate debug point to include the 'do'
let doExpr =
match doExpr with
| Expr.DebugPoint(_, innerExpr) -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes mFull, innerExpr)
| Expr.DebugPoint(_, innerExpr) -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFull), innerExpr)
| e -> e
let binder = (fun e -> mkSequential mFull doExpr e)
let isPriorToSuperInit = false
Expand Down Expand Up @@ -940,7 +940,7 @@ let MakeCtorForIncrClassConstructionPhase2C(
// Add the debug point
let inheritsExpr =
if inheritsIsVisible then
Expr.DebugPoint(DebugPointAtLeafExpr.Yes inheritsExpr.Range, inheritsExpr)
Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, inheritsExpr.Range), inheritsExpr)
else
inheritsExpr

Expand Down
24 changes: 13 additions & 11 deletions src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ let inline arbKeySelectors m =
// Flag that a debug point should get emitted prior to both the evaluation of 'rhsExpr' and the call to Using
let inline addBindDebugPoint spBind e =
match spBind with
| DebugPointAtBinding.Yes m -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, e)
| DebugPointAtBinding.Yes m -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), false, e)
| _ -> e

let inline mkSynDelay2 (e: SynExpr) = mkSynDelay (e.Range.MakeSynthetic()) e
Expand Down Expand Up @@ -1345,7 +1345,7 @@ let rec TryTranslateComputationExpression

let forCall =
match spFor with
| DebugPointAtFor.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFor, false, forCall)
| DebugPointAtFor.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFor), false, forCall)
| DebugPointAtFor.No -> forCall

translatedCtxt forCall)
Expand Down Expand Up @@ -1389,7 +1389,7 @@ let rec TryTranslateComputationExpression
// 'while' is hit just before each time the guard is called
let guardExpr =
match spWhile with
| DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr)
| DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mWhile), false, guardExpr)
| DebugPointAtWhile.No -> guardExpr

Some(
Expand Down Expand Up @@ -1419,7 +1419,7 @@ let rec TryTranslateComputationExpression
// 'while!' is hit just before each time the guard is called
let guardExpr =
match spWhile with
| DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mWhile, false, guardExpr)
| DebugPointAtWhile.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mWhile), false, guardExpr)
| DebugPointAtWhile.No -> guardExpr

let rewrittenWhileExpr =
Expand Down Expand Up @@ -1557,7 +1557,7 @@ let rec TryTranslateComputationExpression
// Put down a debug point for the 'finally'
let unwindExpr2 =
match spFinally with
| DebugPointAtFinally.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFinally, true, unwindExpr)
| DebugPointAtFinally.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFinally), true, unwindExpr)
| DebugPointAtFinally.No -> unwindExpr

if ceenv.isQuery then
Expand All @@ -1571,7 +1571,7 @@ let rec TryTranslateComputationExpression

let innerExpr =
match spTry with
| DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr)
| DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mTry), true, innerExpr)
| _ -> innerExpr

Some(
Expand Down Expand Up @@ -2308,7 +2308,7 @@ let rec TryTranslateComputationExpression

let innerExpr =
match spTry with
| DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mTry, true, innerExpr)
| DebugPointAtTry.Yes _ -> SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mTry), true, innerExpr)
| _ -> innerExpr

let callExpr =
Expand Down Expand Up @@ -2345,7 +2345,7 @@ let rec TryTranslateComputationExpression
if IsControlFlowExpression synYieldExpr then
yieldFromCall
else
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFull, false, yieldFromCall)
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFull), false, yieldFromCall)

Some(translatedCtxt yieldFromCall)

Expand Down Expand Up @@ -2374,7 +2374,7 @@ let rec TryTranslateComputationExpression
if IsControlFlowExpression synReturnExpr then
returnFromCall
else
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFull, false, returnFromCall)
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFull), false, returnFromCall)

Some(translatedCtxt returnFromCall)

Expand All @@ -2393,7 +2393,7 @@ let rec TryTranslateComputationExpression
if IsControlFlowExpression synYieldOrReturnExpr then
yieldOrReturnCall
else
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes mFull, false, yieldOrReturnCall)
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFull), false, yieldOrReturnCall)

Some(translatedCtxt yieldOrReturnCall)

Expand Down Expand Up @@ -2704,7 +2704,9 @@ and TranslateComputationExpressionBind
and convertSimpleReturnToExpr (ceenv: ComputationExpressionContext<'a>) comp varSpace innerComp =
match innerComp with
| SynExpr.YieldOrReturn((false, _), returnExpr, m, _) ->
let returnExpr = SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnExpr)
let returnExpr =
SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), false, returnExpr)

Some(returnExpr, None)

| SynExpr.Match(spMatch, expr, clauses, m, trivia) ->
Expand Down
21 changes: 11 additions & 10 deletions src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3103,7 +3103,7 @@ let BuildPossiblyConditionalMethodCall (cenv: cenv) env isMutable m isProp minfo
if shouldEraseCall then
// Methods marked with 'Conditional' must return 'unit'
UnifyTypes cenv env m g.unit_ty (minfo.GetFSharpReturnType(cenv.amap, m, minst))
mkUnit g m, g.unit_ty
Expr.DebugPoint(DebugPointAtLeafExpr.Yes(isHidden = true, range = m), mkUnit g m), g.unit_ty
else
#if !NO_TYPEPROVIDERS
match minfo with
Expand Down Expand Up @@ -5903,6 +5903,7 @@ and TcNonControlFlowExpr (env: TcEnv) f =
let res2 =
match res with
| IfThenElseExpr _ -> res
| Expr.DebugPoint(DebugPointAtLeafExpr.Yes(isHidden = true), _) -> res
| _ -> mkDebugPoint res.Range res
res2, tpenv
else
Expand Down Expand Up @@ -8270,8 +8271,8 @@ and TcForEachExpr cenv overallTy env tpenv (seqExprOnly, isFromSource, synPat, s
let mEnumExpr = synEnumExpr.Range
let mFor = match spFor with DebugPointAtFor.Yes mStart -> mStart | DebugPointAtFor.No -> mEnumExpr
let mIn = match spIn with DebugPointAtInOrTo.Yes mStart -> mStart | DebugPointAtInOrTo.No -> mBodyExpr
let spEnumExpr = DebugPointAtBinding.Yes mEnumExpr
let spForBind = match spFor with DebugPointAtFor.Yes m -> DebugPointAtBinding.Yes m | DebugPointAtFor.No -> DebugPointAtBinding.NoneAtSticky
let spEnumExpr = match spFor with DebugPointAtFor.Yes _ -> DebugPointAtBinding.Yes mEnumExpr | DebugPointAtFor.No -> DebugPointAtBinding.NoneAtSticky
let spForBind = match spFor with DebugPointAtFor.Yes _ -> DebugPointAtBinding.Yes(unionRanges mFor mPat) | DebugPointAtFor.No -> DebugPointAtBinding.NoneAtInvisible
let spInAsWhile = match spIn with DebugPointAtInOrTo.Yes m -> DebugPointAtWhile.Yes m | DebugPointAtInOrTo.No -> DebugPointAtWhile.No

// Check the expression being enumerated
Expand All @@ -8295,10 +8296,10 @@ and TcForEachExpr cenv overallTy env tpenv (seqExprOnly, isFromSource, synPat, s
let elemTy = destArrayTy g enumExprTy

// Evaluate the array index lookup
let bodyExprFixup elemVar bodyExpr = mkInvisibleLet mIn elemVar (mkLdelem g mIn elemTy arrExpr idxExpr) bodyExpr
let bodyExprFixup elemVar bodyExpr = mkLet spForBind mFor elemVar (mkLdelem g mIn elemTy arrExpr idxExpr) bodyExpr

// Evaluate the array expression once and put it in arrVar
let overallExprFixup overallExpr = mkLet spForBind mFor arrVar enumExpr overallExpr
let overallExprFixup overallExpr = mkLet spEnumExpr mEnumExpr arrVar enumExpr overallExpr

// Ask for a loop over integers for the given range
(elemTy, bodyExprFixup, overallExprFixup, Choice2Of3 (idxVar, mkZero g mFor, mkDecr g mFor (mkLdlen g mFor arrExpr)))
Expand All @@ -8316,12 +8317,12 @@ and TcForEachExpr cenv overallTy env tpenv (seqExprOnly, isFromSource, synPat, s
// Evaluate the span index lookup
let bodyExprFixup elemVar bodyExpr =
let elemAddrVar, _ = mkCompGenLocal mIn "addr" elemAddrTy
let e = mkInvisibleLet mIn elemVar (mkAddrGet mIn (mkLocalValRef elemAddrVar)) bodyExpr
let e = mkLet spForBind mFor elemVar (mkAddrGet mIn (mkLocalValRef elemAddrVar)) bodyExpr
let getItemCallExpr, _ = BuildMethodCall tcVal g cenv.amap PossiblyMutates mWholeExpr true getItemMethInfo ValUseFlag.NormalValUse [] [ spanExpr ] [ idxExpr ] None
mkInvisibleLet mIn elemAddrVar getItemCallExpr e

// Evaluate the span expression once and put it in spanVar
let overallExprFixup overallExpr = mkLet spForBind mFor spanVar enumExpr overallExpr
let overallExprFixup overallExpr = mkLet spEnumExpr mEnumExpr spanVar enumExpr overallExpr

let getLengthCallExpr, _ = BuildMethodCall tcVal g cenv.amap PossiblyMutates mWholeExpr true getLengthMethInfo ValUseFlag.NormalValUse [] [ spanExpr ] [] None

Expand Down Expand Up @@ -8410,13 +8411,13 @@ and TcForEachExpr cenv overallTy env tpenv (seqExprOnly, isFromSource, synPat, s
| Choice3Of3(enumerableVar, enumeratorVar, _, getEnumExpr, _, guardExpr, currentExpr) ->

// This compiled for must be matched EXACTLY by CompiledForEachExpr
mkLet spForBind mFor enumerableVar enumExpr
(mkLet spEnumExpr mFor enumeratorVar getEnumExpr
mkLet spEnumExpr mEnumExpr enumerableVar enumExpr
(mkInvisibleLet mFor enumeratorVar getEnumExpr
(mkTryFinally g
(mkWhile g
(spInAsWhile,
WhileLoopForCompiledForEachExprMarker, guardExpr,
mkInvisibleLet mIn elemVar currentExpr bodyExpr,
mkLet spForBind mIn elemVar currentExpr bodyExpr,
mFor),
BuildDisposableCleanup cenv env mWholeExpr enumeratorVar,
mFor, g.unit_ty, DebugPointAtTry.No, DebugPointAtFinally.No)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT

Some(resultExpr, tpenv)

| SynExpr.YieldOrReturn(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnKeyword = m }) ->
| SynExpr.YieldOrReturn(flags = (isYield, _); expr = synYieldExpr; range = m) ->
let env = { env with eIsControlFlow = false }
let genResultTy = NewInferenceType g

Expand All @@ -404,7 +404,7 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
if IsControlFlowExpression synYieldExpr then
resultExpr
else
mkDebugPoint synYieldExpr.Range resultExpr
mkDebugPoint m resultExpr

Some(resultExpr, tpenv)

Expand Down
Loading
Loading