Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1799aaf
make attribute targets mismatches a warning and not an error.
edgarfgp Apr 23, 2025
55507e9
release notes
edgarfgp Apr 23, 2025
1738018
update tests
edgarfgp Apr 23, 2025
65f5bb6
Merge branch 'main' into fix-attr-targets
edgarfgp Apr 24, 2025
0c97b9d
Merge branch 'main' into fix-attr-targets
edgarfgp Apr 27, 2025
6f2b706
update baselines
edgarfgp Apr 29, 2025
e8f1bb0
Merge branch 'main' into fix-attr-targets
edgarfgp Apr 29, 2025
75d8f5e
Update baselines
edgarfgp Apr 29, 2025
4f2e97e
Merge branch 'fix-attr-targets' of github.com:edgarfgp/fsharp into fi…
edgarfgp Apr 29, 2025
63be5d5
Merge branch 'main' into fix-attr-targets
edgarfgp Apr 30, 2025
4248f2a
Move attribute form logic to an AP
edgarfgp Apr 30, 2025
cc96217
Merge branch 'main' into fix-attr-targets
edgarfgp May 1, 2025
e270b88
Merge branch 'main' into fix-attr-targets
edgarfgp May 1, 2025
e0cc65a
Merge branch 'main' into fix-attr-targets
edgarfgp May 2, 2025
1e29d58
Merge branch 'main' into fix-attr-targets
edgarfgp May 5, 2025
1470bf9
Merge branch 'main' into fix-attr-targets
edgarfgp May 6, 2025
8988215
Merge branch 'main' into fix-attr-targets
edgarfgp May 7, 2025
74712e8
Merge branch 'main' into fix-attr-targets
edgarfgp May 12, 2025
967c4a9
Merge branch 'main' of github.com:edgarfgp/fsharp
edgarfgp May 13, 2025
a30cef4
Merge branch 'dotnet:main' into main
edgarfgp May 22, 2025
5fa0480
Merge branch 'dotnet:main' into main
edgarfgp May 24, 2025
15e3d34
Merge branch 'dotnet:main' into main
edgarfgp May 29, 2025
b7ffcf8
Merge branch 'dotnet:main' into main
edgarfgp Jun 6, 2025
5bde641
Merge branch 'dotnet:main' into main
edgarfgp Jul 26, 2025
0f7c23c
Merge branch 'dotnet:main' into main
edgarfgp Jul 29, 2025
6a6843c
Merge branch 'dotnet:main' into main
edgarfgp Aug 4, 2025
d11dd4a
Merge branch 'dotnet:main' into main
edgarfgp Aug 4, 2025
30fc9a2
Merge branch 'dotnet:main' into main
edgarfgp Aug 5, 2025
835d645
Unify let, let!, use, use! LetOrUse AST representation.
edgarfgp Aug 5, 2025
6dcde2e
Fix computation expression pattern matching order
edgarfgp Aug 6, 2025
77aff92
Merge branch 'main' into unify-let-or-use-2
edgarfgp Aug 6, 2025
670aab8
format
edgarfgp Aug 7, 2025
a862ad1
release notes
edgarfgp Aug 7, 2025
cfb3d09
ILVerify
edgarfgp Aug 7, 2025
918f3e6
Fix computation expression pattern matching order
edgarfgp Aug 7, 2025
fcef811
update baselines
edgarfgp Aug 7, 2025
4d57d09
Fix SynPat shouldBeParenthesizedInContext
edgarfgp Aug 7, 2025
af8bf5a
Merge branch 'unify-let-or-use-2' of github.com:edgarfgp/fsharp into …
edgarfgp Aug 7, 2025
d3bac4a
Update SynPat.fs
edgarfgp Aug 7, 2025
0ceae7b
Attempt to fix editor test
edgarfgp Aug 8, 2025
2181367
Merge branch 'unify-let-or-use-2' of github.com:edgarfgp/fsharp into …
edgarfgp Aug 8, 2025
ca1c516
Simplify mkLetExpression
edgarfgp Aug 8, 2025
47429e6
one more test
edgarfgp Aug 8, 2025
a9f08ae
Add comments to explain the meaning of the new flags
edgarfgp Aug 8, 2025
121a373
Update to always use named fields
edgarfgp Aug 8, 2025
b1ed90b
document isFromSource
edgarfgp Aug 8, 2025
2f268f9
Rename isComputed to isBang
edgarfgp Aug 8, 2025
815c51b
Merge branch 'dotnet:main' into main
edgarfgp Aug 11, 2025
b57b244
Merge branch 'main' into unify-let-or-use-2
edgarfgp Aug 11, 2025
f6fa86e
update baselines
edgarfgp Aug 11, 2025
f1a2727
Release notes: add migration guidance
edgarfgp Aug 11, 2025
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
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/10.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

### Changed
* Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645))
* Unify `let`, `let!`, `use` and `use!` AST representation. ([PR #18825](https://github.com/dotnet/fsharp/pull/18825))

### Breaking Changes

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckRecordSyntaxHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,4 @@ let BindOriginalRecdExpr (withExpr: SynExpr * BlockSeparator) mkRecdExpr =
None,
SynBindingTrivia.Zero)

SynExpr.LetOrUse(false, false, [ binding ], mkRecdExpr (Some withExpr), mOrigExprSynth, SynExprLetOrUseTrivia.Zero)
SynExpr.LetOrUse(false, false, false, false, [ binding ], mkRecdExpr (Some withExpr), mOrigExprSynth, SynExprLetOrUseTrivia.Zero)
218 changes: 133 additions & 85 deletions src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ open FSharp.Compiler.NameResolution
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.Syntax
open FSharp.Compiler.SyntaxTrivia
open FSharp.Compiler.Xml
open FSharp.Compiler.SyntaxTreeOps
open FSharp.Compiler.Text
open FSharp.Compiler.Text.Range
Expand Down Expand Up @@ -856,29 +857,33 @@ let (|OptionalSequential|) e =
[<return: Struct>]
let (|ExprAsUseBang|_|) expr =
match expr with
| SynExpr.LetOrUseBang(
bindDebugPoint = spBind
| SynExpr.LetOrUse(
isUse = true
isFromSource = isFromSource
pat = pat
rhs = rhsExpr
andBangs = andBangs
isComputed = true
bindings = bindings
body = innerComp
trivia = { LetOrUseKeyword = mBind }) -> ValueSome(spBind, isFromSource, pat, rhsExpr, andBangs, innerComp, mBind)
trivia = { LetOrUseKeyword = mBind }) ->
match bindings with
| SynBinding(debugPoint = spBind; headPat = pat; expr = rhsExpr) :: andBangs ->
ValueSome(spBind, isFromSource, pat, rhsExpr, andBangs, innerComp, mBind)
| _ -> ValueNone
| _ -> ValueNone

[<return: Struct>]
let (|ExprAsLetBang|_|) expr =
match expr with
| SynExpr.LetOrUseBang(
bindDebugPoint = spBind
| SynExpr.LetOrUse(
isUse = false
isFromSource = isFromSource
pat = letPat
rhs = letRhsExpr
andBangs = andBangBindings
isComputed = true
bindings = bindings
body = innerComp
trivia = { LetOrUseKeyword = mBind }) -> ValueSome(spBind, isFromSource, letPat, letRhsExpr, andBangBindings, innerComp, mBind)
trivia = { LetOrUseKeyword = mBind }) ->
match bindings with
| SynBinding(debugPoint = spBind; headPat = letPat; expr = letRhsExpr) :: andBangBindings ->
ValueSome(spBind, isFromSource, letPat, letRhsExpr, andBangBindings, innerComp, mBind)
| _ -> ValueNone
| _ -> ValueNone

// "cexpr; cexpr" is treated as builder.Combine(cexpr1, cexpr1)
Expand Down Expand Up @@ -1392,19 +1397,26 @@ let rec TryTranslateComputationExpression

let setCondExpr = SynExpr.Set(SynExpr.Ident idCond, SynExpr.Ident idFirst, mGuard)

let bindCondExpr =
SynExpr.LetOrUseBang(
DebugPointAtBinding.NoneAtSticky,
false,
true,
patFirst,
guardExpr,
[],
setCondExpr,
mGuard,
SynExprLetOrUseTrivia.Zero
let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = patFirst,
returnInfo = None,
expr = guardExpr,
range = guardExpr.Range,
debugPoint = DebugPointAtBinding.NoneAtSticky,
trivia = SynBindingTrivia.Zero
)

let bindCondExpr =
SynExpr.LetOrUse(false, false, true, true, [ binding ], setCondExpr, mGuard, SynExprLetOrUseTrivia.Zero)

let whileExpr =
SynExpr.While(
DebugPointAtWhile.No,
Expand All @@ -1420,19 +1432,26 @@ let rec TryTranslateComputationExpression
mOrig
)

SynExpr.LetOrUse(false, false, [ condBinding ], whileExpr, mGuard, SynExprLetOrUseTrivia.Zero)
SynExpr.LetOrUse(false, false, false, false, [ condBinding ], whileExpr, mGuard, SynExprLetOrUseTrivia.Zero)

let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = patFirst,
returnInfo = None,
expr = guardExpr,
range = guardExpr.Range,
debugPoint = DebugPointAtBinding.NoneAtSticky,
trivia = SynBindingTrivia.Zero
)

SynExpr.LetOrUseBang(
DebugPointAtBinding.NoneAtSticky,
false,
true,
patFirst,
guardExpr,
[],
body,
mGuard,
SynExprLetOrUseTrivia.Zero
)
SynExpr.LetOrUse(false, false, true, true, [ binding ], body, mGuard, SynExprLetOrUseTrivia.Zero)

TryTranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace rewrittenWhileExpr translatedCtxt

Expand Down Expand Up @@ -1620,23 +1639,30 @@ let rec TryTranslateComputationExpression
| DebugPointAtSequential.SuppressStmt -> DebugPointAtBinding.Yes m
| DebugPointAtSequential.SuppressNeither -> DebugPointAtBinding.Yes m

let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = SynPat.Const(SynConst.Unit, rhsExpr.Range),
returnInfo = None,
expr = rhsExpr,
range = rhsExpr.Range,
debugPoint = sp,
trivia = SynBindingTrivia.Zero
)

Some(
TranslateComputationExpression
ceenv
CompExprTranslationPass.Initial
q
varSpace
(SynExpr.LetOrUseBang(
sp,
false,
true,
SynPat.Const(SynConst.Unit, rhsExpr.Range),
rhsExpr,
[],
innerComp2,
m,
SynExprLetOrUseTrivia.Zero
))
(SynExpr.LetOrUse(false, false, true, true, [ binding ], innerComp2, m, SynExprLetOrUseTrivia.Zero))
translatedCtxt
)

Expand Down Expand Up @@ -1704,7 +1730,7 @@ let rec TryTranslateComputationExpression
)

// 'let binds in expr'
| SynExpr.LetOrUse(isRec, false, binds, innerComp, m, trivia) ->
| SynExpr.LetOrUse(isRec, false, isFromSource, false, binds, innerComp, m, trivia) ->

// For 'query' check immediately
if ceenv.isQuery then
Expand Down Expand Up @@ -1737,12 +1763,13 @@ let rec TryTranslateComputationExpression

Some(
TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill ->
translatedCtxt (SynExpr.LetOrUse(isRec, false, binds, holeFill, m, trivia)))
translatedCtxt (SynExpr.LetOrUse(isRec, false, isFromSource, false, binds, holeFill, m, trivia)))
)

// 'use x = expr in expr'
| SynExpr.LetOrUse(
isUse = true
isComputed = false
bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ]
body = innerComp
trivia = { LetOrUseKeyword = mBind }) ->
Expand Down Expand Up @@ -2365,17 +2392,24 @@ and ConsumeCustomOpClauses
// Rebind using either for ... or let!....
let rebind =
if maintainsVarSpaceUsingBind then
SynExpr.LetOrUseBang(
DebugPointAtBinding.NoneAtLet,
false,
false,
intoPat,
dataCompAfterOp,
[],
contExpr,
intoPat.Range,
SynExprLetOrUseTrivia.Zero
)
let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = intoPat,
returnInfo = None,
expr = dataCompAfterOp,
range = dataCompAfterOp.Range,
debugPoint = DebugPointAtBinding.NoneAtLet,
trivia = SynBindingTrivia.Zero
)

SynExpr.LetOrUse(false, false, false, true, [ binding ], contExpr, intoPat.Range, SynExprLetOrUseTrivia.Zero)
else
SynExpr.ForEach(
DebugPointAtFor.No,
Expand Down Expand Up @@ -2406,17 +2440,24 @@ and ConsumeCustomOpClauses
// Rebind using either for ... or let!....
let rebind =
if lastUsesBind then
SynExpr.LetOrUseBang(
DebugPointAtBinding.NoneAtLet,
false,
false,
varSpacePat,
dataCompPrior,
[],
compClausesExpr,
compClausesExpr.Range,
SynExprLetOrUseTrivia.Zero
)
let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = varSpacePat,
returnInfo = None,
expr = dataCompPrior,
range = dataCompPrior.Range,
debugPoint = DebugPointAtBinding.NoneAtLet,
trivia = SynBindingTrivia.Zero
)

SynExpr.LetOrUse(false, false, false, true, [ binding ], compClausesExpr, compClausesExpr.Range, SynExprLetOrUseTrivia.Zero)
else
SynExpr.ForEach(
DebugPointAtFor.No,
Expand Down Expand Up @@ -2546,11 +2587,11 @@ and convertSimpleReturnToExpr (ceenv: ComputationExpressionContext<'a>) comp var
| Some elseExprOpt ->
Some(SynExpr.IfThenElse(guardExpr, thenExpr, elseExprOpt, spIfToThen, isRecovery, mIfToEndOfElseBranch, trivia), None)

| SynExpr.LetOrUse(isRec, false, binds, innerComp, m, trivia) ->
| SynExpr.LetOrUse(isRec, false, isFromSource, false, binds, innerComp, m, trivia) ->
match convertSimpleReturnToExpr ceenv comp varSpace innerComp with
| None -> None
| Some(_, Some _) -> None
| Some(innerExpr, None) -> Some(SynExpr.LetOrUse(isRec, false, binds, innerExpr, m, trivia), None)
| Some(innerExpr, None) -> Some(SynExpr.LetOrUse(isRec, false, isFromSource, false, binds, innerExpr, m, trivia), None)

| OptionalSequential(CustomOperationClause ceenv (nm, _, _, mClause, _), _) when customOperationMaintainsVarSpaceUsingBind ceenv nm ->

Expand Down Expand Up @@ -2591,8 +2632,8 @@ and isSimpleExpr ceenv comp =
&& (match elseCompOpt with
| None -> true
| Some c -> isSimpleExpr ceenv c)
| SynExpr.LetOrUse(body = innerComp) -> isSimpleExpr ceenv innerComp
| SynExpr.LetOrUseBang _ -> false
| SynExpr.LetOrUse(isComputed = false; body = innerComp) -> isSimpleExpr ceenv innerComp
| SynExpr.LetOrUse(isComputed = true) -> false
| SynExpr.Match(clauses = clauses) ->
clauses
|> List.forall (fun (SynMatchClause(resultExpr = innerComp)) -> isSimpleExpr ceenv innerComp)
Expand Down Expand Up @@ -2649,17 +2690,24 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir
| _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m, SynExprYieldOrReturnTrivia.Zero)

let letBangBind =
SynExpr.LetOrUseBang(
DebugPointAtBinding.NoneAtDo,
false,
false,
SynPat.Const(SynConst.Unit, mUnit),
rhsExpr,
[],
bodyExpr,
m,
SynExprLetOrUseTrivia.Zero
)
let binding =
SynBinding(
accessibility = None,
kind = SynBindingKind.Normal,
isInline = false,
isMutable = false,
attributes = [],
xmlDoc = PreXmlDoc.Empty,
valData = SynInfo.emptySynValData,
headPat = SynPat.Const(SynConst.Unit, mUnit),
returnInfo = None,
expr = rhsExpr,
range = rhsExpr.Range,
debugPoint = DebugPointAtBinding.NoneAtDo,
trivia = SynBindingTrivia.Zero
)

SynExpr.LetOrUse(false, false, false, true, [ binding ], bodyExpr, m, SynExprLetOrUseTrivia.Zero)

TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace letBangBind translatedCtxt

Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6072,7 +6072,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
| SynExpr.DoBang (trivia = { DoBangKeyword = m })
| SynExpr.MatchBang (trivia = { MatchBangKeyword = m })
| SynExpr.WhileBang (range = m)
| SynExpr.LetOrUseBang (trivia = { LetOrUseKeyword = m }) ->
| SynExpr.LetOrUse (isComputed = true; trivia = { LetOrUseKeyword = m }) ->
error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m))

| SynExpr.IndexFromEnd (rightExpr, m) ->
Expand Down Expand Up @@ -9199,7 +9199,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed =
| SynExpr.YieldOrReturn _
| SynExpr.YieldOrReturnFrom _
| SynExpr.MatchBang _
| SynExpr.LetOrUseBang _
| SynExpr.LetOrUse (isComputed = true)
| SynExpr.DoBang _
| SynExpr.WhileBang _
| SynExpr.TraitCall _
Expand Down Expand Up @@ -10614,7 +10614,7 @@ and TcLinearExprs bodyChecker cenv env overallTy tpenv isCompExpr synExpr cont =
TcLinearExprs bodyChecker cenv env2 overallTy tpenv isCompExpr expr2 (fun (expr2R, tpenv) ->
cont (Expr.Sequential (expr1R, expr2R, NormalSeq, m), tpenv))

| SynExpr.LetOrUse (isRec, isUse, binds, body, m, _) when not (isUse && isCompExpr) ->
| SynExpr.LetOrUse (isRec, isUse, _, _, binds, body, m, _) when not (isUse && isCompExpr) ->
if isRec then
// TcLinearExprs processes at most one recursive binding, this is not tailcalling
CheckRecursiveBindingIds binds
Expand Down
6 changes: 1 addition & 5 deletions src/Compiler/Checking/Expressions/CheckExpressionsOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,6 @@ let YieldFree (cenv: TcFileState) expr =
| SynExpr.While(doExpr = body)
| SynExpr.WhileBang(doExpr = body)
| SynExpr.ForEach(bodyExpr = body) -> YieldFree body

| SynExpr.LetOrUseBang(body = body) -> YieldFree body

| SynExpr.YieldOrReturn(flags = (true, _)) -> false

| _ -> true
Expand Down Expand Up @@ -232,7 +229,7 @@ let YieldFree (cenv: TcFileState) expr =
| SynExpr.WhileBang(doExpr = body)
| SynExpr.ForEach(bodyExpr = body) -> YieldFree body

| SynExpr.LetOrUseBang _
| SynExpr.LetOrUse(isComputed = true)
| SynExpr.YieldOrReturnFrom _
| SynExpr.YieldOrReturn _
| SynExpr.ImplicitZero _
Expand All @@ -256,7 +253,6 @@ let inline IsSimpleSemicolonSequenceElement expr cenv acceptDeprecated =
| SynExpr.LetOrUse _
| SynExpr.Do _
| SynExpr.MatchBang _
| SynExpr.LetOrUseBang _
| SynExpr.While _
| SynExpr.WhileBang _ -> false
| _ -> true
Expand Down
Loading
Loading