Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -82,6 +82,8 @@
* 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))
* Debug: rework conditional erasure, fix stepping over literals ([PR #19897](https://github.com/dotnet/fsharp/pull/19897))
* Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932))

### Changed

Expand Down
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
3 changes: 2 additions & 1 deletion 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
38 changes: 17 additions & 21 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3171,8 +3171,8 @@ and GenExprAux (cenv: cenv) (cgbuf: CodeGenBuffer) eenv expr (sequel: sequel) =
| LinearOpExpr _
| Expr.Match _ -> GenLinearExpr cenv cgbuf eenv expr sequel false id |> ignore<FakeUnit>

| Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, innerExpr) ->
if equals m range0 then
| Expr.DebugPoint(DebugPointAtLeafExpr.Yes(isHidden, m), innerExpr) ->
if isHidden then
cgbuf.EmitStartOfHiddenCode()
else
CG.EmitDebugPoint cgbuf m
Expand Down Expand Up @@ -3720,24 +3720,11 @@ and GenLinearExpr cenv cgbuf eenv expr sequel preSteps (contf: FakeUnit -> FakeU

//assert(cgbuf.GetCurrentStack() = stackAfterJoin) // REVIEW: Since gen_dtree* now sets stack, stack should be stackAfterJoin at this point...
CG.SetStack cgbuf stackAfterJoin
// If any values are left on the stack after the join then we're certainly going to do something with them
// For example, we may be about to execute a 'stloc' for
//
// let y2 = if System.DateTime.Now.Year < 2000 then 1 else 2
//
// or a 'stelem' for
//
// arr.[0] <- if System.DateTime.Now.Year > 2000 then 1 else 2
//
// In both cases, any instructions that come after this point will be falsely associated with the last branch of the control
// prior to the join point. This is base, e.g. see FSharp 1.0 bug 5155
cgbuf.EmitStartOfHiddenCode()

GenSequel cenv eenv.cloc cgbuf sequelAfterJoin
Fake))

| Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, innerExpr) ->
if equals m range0 then
| Expr.DebugPoint(DebugPointAtLeafExpr.Yes(isHidden, m), innerExpr) ->
if isHidden then
cgbuf.EmitStartOfHiddenCode()
else
CG.EmitDebugPoint cgbuf m
Expand Down Expand Up @@ -7949,8 +7936,6 @@ and GenDecisionTreeSwitch
let m = e.Range
cgbuf.SetMarkToHereIfNecessary inplabOpt

cgbuf.EmitStartOfHiddenCode()

match cases with
// optimize a test against a boolean value, i.e. the all-important if-then-else
| TCase(DecisionTreeTest.Const(Const.Bool b), successTree) :: _ ->
Expand Down Expand Up @@ -10641,10 +10626,21 @@ and CodeGenInitMethod cenv (cgbuf: CodeGenBuffer) eenv tref (codeGenInitFunc: Co
let _, body =
CodeGenMethod cenv cgbuf.mgbuf ([], eenv.staticInitializationName, eenv, 0, None, codeGenInitFunc, m)

if CheckCodeDoesSomething body.Code then
let codeDoesSomething = CheckCodeDoesSomething body.Code

// Keep the init method if it carries a visible debug point, so steppable bindings like 'let i = ()' survive.
let hasVisibleDebugPoint =
not cenv.options.localOptimizationsEnabled
&& body.Code.Instrs
|> Array.exists (function
| I_seqpoint sp -> sp.Line <> FeeFee cenv
| _ -> false)

if codeDoesSomething || hasVisibleDebugPoint then
// We are here because the module we just grabbed has an interesting static initializer
let feefee, seqpt =
if body.Code.Instrs.Length > 0 then
// Without real init code, the .cctor's FeeFee marker would just add a stray hidden sequence point.
if codeDoesSomething && body.Code.Instrs.Length > 0 then
match body.Code.Instrs[0] with
| I_seqpoint sp as i -> [ FeeFeeInstr cenv sp.Document ], [ i ]
| _ -> [], []
Expand Down
10 changes: 5 additions & 5 deletions src/Compiler/Optimize/LowerComputedCollections.fs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ let LowerComputedListOrArraySeqExpr tcVal g amap m collectorTy overallSeqExpr =
let cleanupE = BuildDisposableCleanup tcVal g infoReader m enumv

// A debug point should get emitted prior to both the evaluation of 'inp' and the call to GetEnumerator
let addForDebugPoint e = Expr.DebugPoint(DebugPointAtLeafExpr.Yes mFor, e)
let addForDebugPoint e = Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFor), e)

let spInAsWhile = match spIn with DebugPointAtInOrTo.Yes m -> DebugPointAtWhile.Yes m | DebugPointAtInOrTo.No -> DebugPointAtWhile.No

Expand Down Expand Up @@ -289,7 +289,7 @@ module List =
match body with
| Expr.Let(TBind(v, rhs, DebugPointAtBinding.Yes spBind), innerBody, m, flags) ->
let bodyForAdd = Expr.Let(TBind(v, rhs, DebugPointAtBinding.NoneAtInvisible), innerBody, m, flags)
Expr.DebugPoint(DebugPointAtLeafExpr.Yes spBind, mkCallCollectorAdd tcVal g reader mBody collector bodyForAdd)
Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, spBind), mkCallCollectorAdd tcVal g reader mBody collector bodyForAdd)
| _ ->
mkCallCollectorAdd tcVal g reader mIn collector body

Expand Down Expand Up @@ -342,7 +342,7 @@ module List =
match body with
| Some (loopVal, body) ->
mkInvisibleLet m loopVal loopVar
(Expr.DebugPoint (DebugPointAtLeafExpr.Yes mFor, mkCallCollectorAdd tcVal g reader mBody collector body))
(Expr.DebugPoint (DebugPointAtLeafExpr.Yes(false, mFor), mkCallCollectorAdd tcVal g reader mBody collector body))
| None ->
mkCallCollectorAdd tcVal g reader mBody collector loopVar)

Expand Down Expand Up @@ -447,7 +447,7 @@ module Array =
)

// Add a debug point at the `for`, before anything gets evaluated.
Expr.DebugPoint (DebugPointAtLeafExpr.Yes mFor, mapping)
Expr.DebugPoint (DebugPointAtLeafExpr.Yes(false, mFor), mapping)
)

/// Whether to check for overflow when converting a value to a native int.
Expand Down Expand Up @@ -508,7 +508,7 @@ module Array =

match body with
| Some (loopVal, body) ->
mkInvisibleLet mBody loopVal loopVar (Expr.DebugPoint (DebugPointAtLeafExpr.Yes mFor, mkStore body))
mkInvisibleLet mBody loopVal loopVar (Expr.DebugPoint (DebugPointAtLeafExpr.Yes(false, mFor), mkStore body))
| None ->
mkStore loopVar)

Expand Down
8 changes: 4 additions & 4 deletions src/Compiler/Optimize/LowerSequences.fs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ let ConvertSequenceExprToObject g amap overallExpr =
let (TBind(v, e, sp)) = bind
let addDebugPoint e =
match sp with
| DebugPointAtBinding.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, e)
| DebugPointAtBinding.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), e)
| _ -> e
let vref = mkLocalValRef v
{ resBody with
Expand Down Expand Up @@ -262,7 +262,7 @@ let ConvertSequenceExprToObject g amap overallExpr =
// body ]]

// A debug point should get emitted prior to both the evaluation of 'inp' and the call to GetEnumerator
let addForDebugPoint e = Expr.DebugPoint(DebugPointAtLeafExpr.Yes mFor, e)
let addForDebugPoint e = Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, mFor), e)

// The 'in' debug point is put back into the TypedTree at the right place for SeqWhile
let mIn = match spIn with DebugPointAtInOrTo.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.While) | DebugPointAtInOrTo.No -> mIn
Expand Down Expand Up @@ -293,11 +293,11 @@ let ConvertSequenceExprToObject g amap overallExpr =
let asyncVars = unionFreeVars res1.asyncVars (freeInExpr CollectLocals compensation)
let addTryDebugPoint e =
match spTry with
| DebugPointAtTry.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, e)
| DebugPointAtTry.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), e)
| _ -> e
let addFinallyDebugPoint e =
match spFinally with
| DebugPointAtFinally.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, e)
| DebugPointAtFinally.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), e)
| _ -> e
Some { phase2 = (fun (pcVar, _currv, _, pcMap as ctxt) ->
let generate1, dispose1, checkDispose1 = res1.phase2 ctxt
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Optimize/LowerStateMachines.fs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ let RepresentBindingAsStateVar g (bind: Binding) (resBody: StateMachineConversio
let (TBind(v, e, sp)) = bind
let addDebugPoint innerExpr =
match sp with
| DebugPointAtBinding.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes m, innerExpr)
| DebugPointAtBinding.Yes m -> Expr.DebugPoint(DebugPointAtLeafExpr.Yes(false, m), innerExpr)
| _ -> innerExpr
let vref = mkLocalValRef v
{ resBody with
Expand Down
Loading
Loading