Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Empty/NoEmpty)-bodied named computation expression should produce the same AST #18126

Closed
Closed
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
40 changes: 27 additions & 13 deletions src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5910,8 +5910,12 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
| SynExpr.ForEach (spFor, spIn, SeqExprOnly seqExprOnly, isFromSource, pat, synEnumExpr, synBodyExpr, m) ->
TcForEachExpr cenv overallTy env tpenv (seqExprOnly, isFromSource, pat, synEnumExpr, synBodyExpr, m, spFor, spIn, m)

| SynExpr.ComputationExpr (hasSeqBuilder, comp, m) ->
let isIndexRange = match comp with | SynExpr.IndexRange _ -> true | _ -> false
| SynExpr.ComputationExpr (hasSeqBuilder, Some comp, m) ->
let isIndexRange =
match comp with
| (SynExpr.IndexRange _) -> true
| _ -> false

let deprecatedPlacesWhereSeqCanBeOmitted =
cenv.g.langVersion.SupportsFeature LanguageFeature.DeprecatePlacesWhereSeqCanBeOmitted
if
Expand All @@ -5924,6 +5928,11 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE

let env = ExitFamilyRegion env
cenv.TcSequenceExpressionEntry cenv env overallTy tpenv (hasSeqBuilder, comp) m

| SynExpr.ComputationExpr (_, None, m)
| SynExpr.EmptyRecordOrComputationExpr m ->
TcNonControlFlowExpr env <| fun env ->
TcExprRecord cenv overallTy env tpenv (None, None, [], m)

| SynExpr.ArrayOrListComputed (isArray, comp, m) ->
TcNonControlFlowExpr env <| fun env ->
Expand Down Expand Up @@ -8508,7 +8517,7 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg
let denv = env.DisplayEnv
let mArg = synArg.Range
let mLeftExpr = leftExpr.Range

(*
/// Treat an application of a value to an empty record expression
/// as a computation expression with a single unit expression.
/// Insert a (), i.e., such that builder { } ≡ builder { () }.
Expand All @@ -8519,6 +8528,7 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg
| [] when g.langVersion.SupportsFeature LanguageFeature.EmptyBodiedComputationExpressions -> Some (EmptyFieldListAsUnit (SynExpr.Const (SynConst.Unit, range0)))
| _ -> None

*)
// If the type of 'synArg' unifies as a function type, then this is a function application, otherwise
// it is an error or a computation expression or indexer or delegate invoke
match UnifyFunctionTypeUndoIfFailed cenv denv mLeftExpr exprTy with
Expand All @@ -8542,13 +8552,13 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg
match synArg with
// seq { comp }
// seq { }
| SynExpr.ComputationExpr (false, comp, m)
| SynExpr.Record (None, None, EmptyFieldListAsUnit comp, m) when
| SynExpr.ComputationExpr (false, None, m)
| SynExpr.EmptyRecordOrComputationExpr m when
(match leftExpr with
| ApplicableExpr(expr=Expr.Op(TOp.Coerce, _, [SeqExpr g], _)) -> true
| _ -> false) ->
SynExpr.ComputationExpr (true, comp, m)

| _ -> false) && g.langVersion.SupportsFeature LanguageFeature.EmptyBodiedComputationExpressions ->
SynExpr.ComputationExpr (true, Some(SynExpr.Const (SynConst.Unit, range0)), m)
| _ -> synArg

let (arg, tpenv), cenv =
Expand Down Expand Up @@ -8598,12 +8608,15 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg

// Perhaps 'leftExpr' is a computation expression builder, and 'arg' is '{ ... }' or '{ }':
// leftExpr { comp }
// leftExpr { }
| SynExpr.ComputationExpr (false, comp, _m)
| SynExpr.Record (None, None, EmptyFieldListAsUnit comp, _m) ->
| SynExpr.ComputationExpr (false, Some comp, _m) ->
let bodyOfCompExpr, tpenv = cenv.TcComputationExpression cenv env overallTy tpenv (mLeftExpr, leftExpr.Expr, exprTy, comp)
TcDelayed cenv overallTy env tpenv mExprAndArg (MakeApplicableExprNoFlex cenv bodyOfCompExpr) (tyOfExpr g bodyOfCompExpr) ExprAtomicFlag.NonAtomic delayed


// leftExpr { }
| SynExpr.ComputationExpr (false, None, m)
| SynExpr.EmptyRecordOrComputationExpr m when g.langVersion.SupportsFeature LanguageFeature.EmptyBodiedComputationExpressions ->
let bodyOfCompExpr, tpenv = cenv.TcComputationExpression cenv env overallTy tpenv (mLeftExpr, leftExpr.Expr, exprTy, SynExpr.Const(SynConst.Unit, range0))
TcDelayed cenv overallTy env tpenv mExprAndArg (MakeApplicableExprNoFlex cenv bodyOfCompExpr) (tyOfExpr g bodyOfCompExpr) ExprAtomicFlag.NonAtomic delayed
| _ ->
error (NotAFunction(denv, overallTy.Commit, mLeftExpr, mArg))

Expand Down Expand Up @@ -9137,6 +9150,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed =
| SynExpr.ForEach _
| SynExpr.ArrayOrListComputed _
| SynExpr.ComputationExpr _
| SynExpr.EmptyRecordOrComputationExpr _
| SynExpr.Lambda _
| SynExpr.MatchLambda _
| SynExpr.Match _
Expand Down Expand Up @@ -10914,7 +10928,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
// { new Foo } -> SynExpr.ObjExpr
// { new Foo() } -> SynExpr.ObjExpr
// { New Foo with ... } -> SynExpr.ObjExpr
| SynExpr.ComputationExpr(false, SynExpr.New(_, targetType, expr, m), _) ->
| SynExpr.ComputationExpr(false, Some(SynExpr.New(_, targetType, expr, m)), _) ->
false, SynExpr.ObjExpr(targetType, Some(expr, None), None, [], [], [], m, rhsExpr.Range), overallTy, overallTy
| e -> false, e, overallTy, overallTy

Expand Down
7 changes: 6 additions & 1 deletion src/Compiler/Driver/GraphChecking/FileContentMapping.fs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,12 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list =
| None, Some e -> visit e continuation
| Some e1, Some e2 -> visit e1 (fun e1Nodes -> visit e2 (fun e2Nodes -> e1Nodes @ e2Nodes |> continuation))
| SynExpr.IndexFromEnd(expr, _) -> visit expr continuation
| SynExpr.ComputationExpr(expr = expr) -> visit expr continuation
| SynExpr.ComputationExpr(expr = expr) ->
match expr with
| None -> continuation []
| Some e -> visit e continuation

| SynExpr.EmptyRecordOrComputationExpr _ -> continuation []
| SynExpr.Lambda(args = args; body = body) -> visit body (fun bodyNodes -> visitSynSimplePats args @ bodyNodes |> continuation)
| SynExpr.DotLambda(expr = expr) -> visit expr continuation
| SynExpr.MatchLambda(matchClauses = clauses) -> List.collect visitSynMatchClause clauses |> continuation
Expand Down
6 changes: 5 additions & 1 deletion src/Compiler/Service/FSharpParseFileResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -533,13 +533,13 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
| SynExpr.Ident _
| SynExpr.ImplicitZero _
| SynExpr.Const _
| SynExpr.EmptyRecordOrComputationExpr _
| SynExpr.Dynamic _ -> ()

| SynExpr.Quote(_, _, e, _, _)
| SynExpr.TypeTest(e, _, _)
| SynExpr.Upcast(e, _, _)
| SynExpr.AddressOf(_, e, _, _)
| SynExpr.ComputationExpr(_, e, _)
| SynExpr.ArrayOrListComputed(_, e, _)
| SynExpr.Typed(e, _, _)
| SynExpr.FromParseError(e, _)
Expand Down Expand Up @@ -643,6 +643,10 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,

yield! walkExprs (fs |> List.map (fun (_, _, e) -> e))

| SynExpr.ComputationExpr(_, e, _) ->
match e with
| Some e -> yield! walkExpr false e
| None -> ()
| SynExpr.ObjExpr(argOptions = args; bindings = bs; members = ms; extraImpls = is) ->
let bs = unionBindingAndMembers bs ms

Expand Down
5 changes: 4 additions & 1 deletion src/Compiler/Service/ServiceInterfaceStubGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,10 @@ module InterfaceStubGenerator =

| SynExpr.ArrayOrListComputed(_, synExpr, _range) -> walkExpr synExpr

| SynExpr.ComputationExpr(_, synExpr, _range) -> walkExpr synExpr
| SynExpr.ComputationExpr(_, synExpr, _range) ->
match synExpr with
| Some synExpr -> walkExpr synExpr
| None -> None

| SynExpr.Lambda(body = synExpr) -> walkExpr synExpr

Expand Down
10 changes: 8 additions & 2 deletions src/Compiler/Service/ServiceParseTreeWalk.fs
Original file line number Diff line number Diff line change
Expand Up @@ -632,10 +632,15 @@ module SyntaxTraversal =

let ok =
match isPartOfArrayOrList, synExpr with
| false, LongOrSingleIdent(_, lid, _, _) -> visitor.VisitRecordField(path, None, Some lid)
| false, Some(LongOrSingleIdent(_, lid, _, _)) -> visitor.VisitRecordField(path, None, Some lid)
| _ -> None

if ok.IsSome then ok else traverseSynExpr synExpr
if ok.IsSome then
ok
else
match synExpr with
| Some synExpr -> traverseSynExpr synExpr
| None -> None

| SynExpr.Lambda(parsedData = parsedData) ->
[
Expand Down Expand Up @@ -780,6 +785,7 @@ module SyntaxTraversal =
| SynExpr.LibraryOnlyStaticOptimization _
| SynExpr.LibraryOnlyUnionCaseFieldGet _
| SynExpr.LibraryOnlyUnionCaseFieldSet _
| SynExpr.EmptyRecordOrComputationExpr _
| SynExpr.ArbitraryAfterError _ -> None

visitor.VisitExpr(origPath, traverseSynExpr origPath, defaultTraverse, expr)
Expand Down
12 changes: 9 additions & 3 deletions src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,6 @@ module ParsedInput =
| SynExpr.Do(expr = e)
| SynExpr.Assert(expr = e)
| SynExpr.ArrayOrListComputed(expr = e)
| SynExpr.ComputationExpr(expr = e)
| SynExpr.Lambda(body = e)
| SynExpr.DotLambda(expr = e)
| SynExpr.InferredUpcast(expr = e)
Expand All @@ -776,6 +775,10 @@ module ParsedInput =
| SynExpr.Paren(expr = e)
| SynExpr.Quote(quotedExpr = e)
| SynExpr.Typed(expr = e) -> walkExprWithKind parentKind e
| SynExpr.ComputationExpr(expr = e) ->
match e with
| Some e -> walkExprWithKind parentKind e
| None -> None

| SynExpr.NamedIndexedPropertySet(expr1 = e1; expr2 = e2)
| SynExpr.TryFinally(tryExpr = e1; finallyExpr = e2)
Expand Down Expand Up @@ -1463,7 +1466,7 @@ module ParsedInput =
|> Option.orElseWith (fun () -> defaultTraverse expr)

// { new | }
| SynExpr.ComputationExpr(expr = SynExpr.ArbitraryAfterError _) when
| SynExpr.ComputationExpr(expr = Some(SynExpr.ArbitraryAfterError _)) when
lineStr.Trim().Split(' ') |> Array.contains "new"
->
Some(CompletionContext.Inherit(InheritanceContext.Unknown, ([], None)))
Expand Down Expand Up @@ -2024,13 +2027,16 @@ module ParsedInput =
| SynExpr.DoBang(expr = e)
| SynExpr.YieldOrReturn(expr = e)
| SynExpr.ArrayOrListComputed(expr = e)
| SynExpr.ComputationExpr(expr = e)
| SynExpr.Do(expr = e)
| SynExpr.Assert(expr = e)
| SynExpr.Lazy(expr = e)
| SynExpr.DotLambda(expr = e)
| SynExpr.IndexFromEnd(expr = e)
| SynExpr.YieldOrReturnFrom(expr = e) -> walkExpr e
| SynExpr.ComputationExpr(expr = e) ->
match e with
| None -> ()
| Some e -> walkExpr e

| SynExpr.Lambda(args = pats; body = e) ->
walkSimplePats pats
Expand Down
5 changes: 4 additions & 1 deletion src/Compiler/Service/ServiceStructure.fs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,10 @@ module Structure =
rcheck Scope.ArrayOrList Collapse.Same r collapse
parseExpr e

| SynExpr.ComputationExpr(_, e, _r) as _c -> parseExpr e
| SynExpr.ComputationExpr(_, e, _r) as _c ->
match e with
| Some e -> parseExpr e
| None -> ()

| SynExpr.ObjExpr(
argOptions = argOpt; bindings = bindings; members = ms; extraImpls = extraImpls; newExprRange = newRange; range = mWhole) ->
Expand Down
5 changes: 4 additions & 1 deletion src/Compiler/SyntaxTree/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,9 @@ type SynExpr =

| IndexFromEnd of expr: SynExpr * range: range

| ComputationExpr of hasSeqBuilder: bool * expr: SynExpr * range: range
| ComputationExpr of hasSeqBuilder: bool * expr: SynExpr option * range: range

| EmptyRecordOrComputationExpr of range: range

| Lambda of
fromMethod: bool *
Expand Down Expand Up @@ -780,6 +782,7 @@ type SynExpr =
| SynExpr.For(range = m)
| SynExpr.ForEach(range = m)
| SynExpr.ComputationExpr(range = m)
| SynExpr.EmptyRecordOrComputationExpr(range = m)
| SynExpr.ArrayOrListComputed(range = m)
| SynExpr.Lambda(range = m)
| SynExpr.Match(range = m)
Expand Down
5 changes: 4 additions & 1 deletion src/Compiler/SyntaxTree/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,10 @@ type SynExpr =
| IndexFromEnd of expr: SynExpr * range: range

/// F# syntax: { expr }
| ComputationExpr of hasSeqBuilder: bool * expr: SynExpr * range: range
| ComputationExpr of hasSeqBuilder: bool * expr: SynExpr option * range: range

/// F# syntax: { }
| EmptyRecordOrComputationExpr of range: range

/// First bool indicates if lambda originates from a method. Patterns here are always "simple"
/// Second bool indicates if this is a "later" part of an iterated sequence of lambdas
Expand Down
7 changes: 6 additions & 1 deletion src/Compiler/SyntaxTree/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -863,12 +863,12 @@ let rec synExprContainsError inpExpr =
| SynExpr.Typar _
| SynExpr.ImplicitZero _
| SynExpr.Const _
| SynExpr.EmptyRecordOrComputationExpr _
| SynExpr.Dynamic _ -> false

| SynExpr.TypeTest(e, _, _)
| SynExpr.Upcast(e, _, _)
| SynExpr.AddressOf(_, e, _, _)
| SynExpr.ComputationExpr(_, e, _)
| SynExpr.ArrayOrListComputed(_, e, _)
| SynExpr.Typed(e, _, _)
| SynExpr.Do(e, _)
Expand Down Expand Up @@ -924,6 +924,11 @@ let rec synExprContainsError inpExpr =

walkBinds bs || walkBinds binds

| SynExpr.ComputationExpr(_, e, _) ->
match e with
| None -> false
| Some value -> walkExpr value

| SynExpr.ForEach(_, _, _, _, _, e1, e2, _)
| SynExpr.While(_, e1, e2, _)
| SynExpr.WhileBang(_, e1, e2, _) -> walkExpr e1 || walkExpr e2
Expand Down
10 changes: 8 additions & 2 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -5052,6 +5052,12 @@ appExpr:
| appExpr argExpr %prec expr_app
{ SynExpr.App(ExprAtomicFlag.NonAtomic, false, $1, $2, unionRanges $1.Range $2.Range) }

| appExpr LBRACE rbrace
{ let appExprRange = $1.Range
let ceRange = rhs2 parseState 1 2
let m = unionRanges appExprRange ceRange
SynExpr.App(ExprAtomicFlag.NonAtomic, false, $1, SynExpr.ComputationExpr (false, None, ceRange), m) }

| atomicExpr
{ let arg, _ = $1
arg }
Expand Down Expand Up @@ -5438,7 +5444,7 @@ braceExpr:

| LBRACE rbrace
{ let m = rhs2 parseState 1 2
SynExpr.Record(None, None, [], m) }
SynExpr.EmptyRecordOrComputationExpr(m) }

braceExprBody:
| recdExpr
Expand Down Expand Up @@ -5466,7 +5472,7 @@ arrayExprElements:

computationExpr:
| sequentialExpr
{ $1.Range, (fun mLhs -> SynExpr.ComputationExpr(false, $1, mLhs)) }
{ $1.Range, (fun mLhs -> SynExpr.ComputationExpr(false, Some $1, mLhs)) }

arrowThenExprR:
| RARROW typedSequentialExprBlockR
Expand Down
Loading