Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,8 @@ let TcArrayOrListComputedExpression (cenv: TcFileState) env (overallTy: OverallT

| None ->

// LanguageFeatures.ImplicitYield do not require this validation
let implicitYieldEnabled =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield

let validateExpressionWithIfRequiresParenthesis = not implicitYieldEnabled
let acceptDeprecatedIfThenExpression = not implicitYieldEnabled

match comp with
| SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems ->
match comp with
| SimpleSemicolonSequence cenv false _ -> ()
| _ when validateExpressionWithIfRequiresParenthesis ->
errorR (Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis (), m))
| _ -> ()

| SimpleSemicolonSequence elems ->
let replacementExpr =
if isArray then
// This are to improve parsing/processing speed for parser tables by converting to an array blob ASAP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3037,11 +3037,10 @@ let TcComputationExpression (cenv: TcFileState) env (overallTy: OverallTy) tpenv
// then allow the type-directed rule interpreting non-unit-typed expressions in statement
// positions as 'yield'. 'yield!' may be present in the computation expression.
let enableImplicitYield =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield
&& (hasMethInfo "Yield" cenv env mBuilderVal ad builderTy
&& hasMethInfo "Combine" cenv env mBuilderVal ad builderTy
&& hasMethInfo "Delay" cenv env mBuilderVal ad builderTy
&& YieldFree cenv comp)
hasMethInfo "Yield" cenv env mBuilderVal ad builderTy
&& hasMethInfo "Combine" cenv env mBuilderVal ad builderTy
&& hasMethInfo "Delay" cenv env mBuilderVal ad builderTy
&& YieldFree comp

let origComp = comp

Expand Down
87 changes: 24 additions & 63 deletions src/Compiler/Checking/Expressions/CheckExpressionsOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -180,69 +180,31 @@ let RewriteRangeExpr synExpr =
| _ -> None

/// Check if a computation or sequence expression is syntactically free of 'yield' (though not yield!)
let YieldFree (cenv: TcFileState) expr =
if cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield then

// Implement yield free logic for F# Language including the LanguageFeature.ImplicitYield
let rec YieldFree expr =
match expr with
| SynExpr.Sequential(expr1 = expr1; expr2 = expr2) -> YieldFree expr1 && YieldFree expr2

| SynExpr.IfThenElse(thenExpr = thenExpr; elseExpr = elseExprOpt) -> YieldFree thenExpr && Option.forall YieldFree elseExprOpt

| SynExpr.TryWith(tryExpr = body; withCases = clauses) ->
YieldFree body
&& clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)

| SynExpr.Match(clauses = clauses)
| SynExpr.MatchBang(clauses = clauses) -> clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)

| SynExpr.For(doBody = body)
| SynExpr.TryFinally(tryExpr = body)
| SynExpr.LetOrUse({ Body = body })
| SynExpr.While(doExpr = body)
| SynExpr.WhileBang(doExpr = body)
| SynExpr.ForEach(bodyExpr = body) -> YieldFree body
| SynExpr.YieldOrReturn(flags = (true, _)) -> false

| _ -> true

YieldFree expr
else
// Implement yield free logic for F# Language without the LanguageFeature.ImplicitYield
let rec YieldFree expr =
match expr with
| SynExpr.Sequential(expr1 = expr1; expr2 = expr2) -> YieldFree expr1 && YieldFree expr2

| SynExpr.IfThenElse(thenExpr = thenExpr; elseExpr = elseExprOpt) -> YieldFree thenExpr && Option.forall YieldFree elseExprOpt

| SynExpr.TryWith(tryExpr = e1; withCases = clauses) ->
YieldFree e1
&& clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)
let rec YieldFree expr =
match expr with
| SynExpr.Sequential(expr1 = expr1; expr2 = expr2) -> YieldFree expr1 && YieldFree expr2

| SynExpr.Match(clauses = clauses)
| SynExpr.MatchBang(clauses = clauses) -> clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)
| SynExpr.IfThenElse(thenExpr = thenExpr; elseExpr = elseExprOpt) -> YieldFree thenExpr && Option.forall YieldFree elseExprOpt

| SynExpr.For(doBody = body)
| SynExpr.TryFinally(tryExpr = body)
| SynExpr.LetOrUse({ Body = body })
| SynExpr.While(doExpr = body)
| SynExpr.WhileBang(doExpr = body)
| SynExpr.ForEach(bodyExpr = body) -> YieldFree body
| SynExpr.TryWith(tryExpr = body; withCases = clauses) ->
YieldFree body
&& clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)

| LetOrUse(_, true, _)
| SynExpr.YieldOrReturnFrom _
| SynExpr.YieldOrReturn _
| SynExpr.ImplicitZero _
| SynExpr.Do _ -> false
| SynExpr.Match(clauses = clauses)
| SynExpr.MatchBang(clauses = clauses) -> clauses |> List.forall (fun (SynMatchClause(resultExpr = res)) -> YieldFree res)

| _ -> true
| SynExpr.For(doBody = body)
| SynExpr.TryFinally(tryExpr = body)
| SynExpr.LetOrUse({ Body = body })
| SynExpr.While(doExpr = body)
| SynExpr.WhileBang(doExpr = body)
| SynExpr.ForEach(bodyExpr = body) -> YieldFree body
| SynExpr.YieldOrReturn(flags = (true, _)) -> false

YieldFree expr
| _ -> true

let inline IsSimpleSemicolonSequenceElement expr cenv acceptDeprecated =
let inline IsSimpleSemicolonSequenceElement expr =
match expr with
| SynExpr.IfThenElse _ when acceptDeprecated && YieldFree cenv expr -> true
| SynExpr.IfThenElse _
| SynExpr.TryWith _
| SynExpr.Match _
Expand All @@ -259,25 +221,24 @@ let inline IsSimpleSemicolonSequenceElement expr cenv acceptDeprecated =
| _ -> true

[<TailCall>]
let rec TryGetSimpleSemicolonSequenceOfComprehension expr acc cenv acceptDeprecated =
let rec TryGetSimpleSemicolonSequenceOfComprehension expr acc =
match expr with
| SynExpr.Sequential(isTrueSeq = true; expr1 = e1; expr2 = e2) ->
if IsSimpleSemicolonSequenceElement e1 cenv acceptDeprecated then
TryGetSimpleSemicolonSequenceOfComprehension e2 (e1 :: acc) cenv acceptDeprecated
if IsSimpleSemicolonSequenceElement e1 then
TryGetSimpleSemicolonSequenceOfComprehension e2 (e1 :: acc)
else
ValueNone
| _ ->
if IsSimpleSemicolonSequenceElement expr cenv acceptDeprecated then
if IsSimpleSemicolonSequenceElement expr then
ValueSome(List.rev (expr :: acc))
else
ValueNone

/// Determine if a syntactic expression inside 'seq { ... }' or '[...]' counts as a "simple sequence
/// of semicolon separated values". For example [1;2;3].
/// 'acceptDeprecated' is true for the '[ ... ]' case, where we allow the syntax '[ if g then t else e ]' but ask it to be parenthesized
[<return: Struct>]
let (|SimpleSemicolonSequence|_|) cenv acceptDeprecated cexpr =
TryGetSimpleSemicolonSequenceOfComprehension cexpr [] cenv acceptDeprecated
let (|SimpleSemicolonSequence|_|) cexpr =
TryGetSimpleSemicolonSequenceOfComprehension cexpr []

let elimFastIntegerForLoop (spFor, spTo, id, start: SynExpr, dir, finish: SynExpr, innerExpr, m: range) =
let mOp = (unionRanges start.Range finish.Range).MakeSynthetic()
Expand Down
17 changes: 1 addition & 16 deletions src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
// If there are no 'yield' in the computation expression then allow the type-directed rule
// interpreting non-unit-typed expressions in statement positions as 'yield'. 'yield!' may be
// present in the computation expression.
let enableImplicitYield =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield
&& (YieldFree cenv comp)
let enableImplicitYield = YieldFree comp

let mkSeqDelayedExpr m (coreExpr: Expr) =
let overallTy = tyOfExpr cenv.g coreExpr
Expand Down Expand Up @@ -162,9 +160,6 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT

Some(mkSeqFinally cenv env mTryToLast genOuterTy innerExpr unwindExpr, tpenv)

| SynExpr.Paren(range = m) when not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield) ->
error (Error(FSComp.SR.tcConstructIsAmbiguousInSequenceExpression (), m))

| SynExpr.ImplicitZero m -> Some(mkSeqEmpty cenv env m genOuterTy, tpenv)

| SynExpr.DoBang(trivia = { DoBangKeyword = m }) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m))
Expand Down Expand Up @@ -469,16 +464,6 @@ let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpe
match RewriteRangeExpr comp with
| Some replacementExpr -> TcExpr cenv overallTy env tpenv replacementExpr
| None ->
let implicitYieldEnabled =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield

let validateObjectSequenceOrRecordExpression = not implicitYieldEnabled

match comp with
| SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression ->
errorR (Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression (), m))
| _ -> ()

if not hasBuilder && not cenv.g.compilingFSharpCore then
error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m))

Expand Down
4 changes: 0 additions & 4 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,7 @@ tcCouldNotFindIDisposable,"Couldn't find Dispose on IDisposable, or it was overl
736,tcExprUndelayed,"TcExprUndelayed: delayed"
737,tcExpressionRequiresSequence,"This expression form may only be used in sequence and computation expressions"
738,tcInvalidObjectExpressionSyntaxForm,"Invalid object expression. Objects without overrides or interfaces should use the expression form 'new Type(args)' without braces."
739,tcInvalidObjectSequenceOrRecordExpression,"Invalid object, sequence or record expression"
740,tcInvalidSequenceExpressionSyntaxForm,"Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'"
tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an element of the form 'if ... then ... else'. Parenthesize this expression to indicate it is an individual element of the list or array, to disambiguate this from a list generated using a sequence expression"
741,tcUnableToParseFormatString,"Unable to parse format string '%s'"
742,tcListLiteralMaxSize,"This list expression exceeds the maximum size for list literals. Use an array for larger literals and call Array.ToList."
743,tcExpressionFormRequiresObjectConstructor,"The expression form 'expr then expr' may only be used as part of an explicit object constructor"
Expand Down Expand Up @@ -647,7 +645,6 @@ tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an
790,tcTypeIsNotARecordTypeNeedConstructor,"This type is not a record type. Values of class and struct types must be created using calls to object constructors."
791,tcTypeIsNotARecordType,"This type is not a record type"
792,tcConstructIsAmbiguousInComputationExpression,"This construct is ambiguous as part of a computation expression. Nested expressions may be written using 'let _ = (...)' and nested computations using 'let! res = builder {{ ... }}'."
793,tcConstructIsAmbiguousInSequenceExpression,"This construct is ambiguous as part of a sequence expression. Nested expressions may be written using 'let _ = (...)' and nested sequences using 'yield! seq {{... }}'."
794,tcDoBangIllegalInSequenceExpression,"'do!' cannot be used within sequence expressions"
795,tcUseForInSequenceExpression,"The use of 'let! x = coll' in sequence expressions is not permitted. Use 'for x in coll' instead."
796,tcTryIllegalInSequenceExpression,"'try'/'with' cannot be used within sequence expressions"
Expand Down Expand Up @@ -1567,7 +1564,6 @@ featureSingleUnderscorePattern,"single underscore pattern"
featureWildCardInForLoop,"wild card in for loop"
featureRelaxWhitespace,"whitespace relaxation"
featureNameOf,"nameof"
featureImplicitYield,"implicit yield"
featureDotlessFloat32Literal,"dotless float32 literal"
featurePackageManagement,"package management"
featureFromEndSlicing,"from-end slicing"
Expand Down
3 changes: 0 additions & 3 deletions src/Compiler/Facilities/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ type LanguageFeature =
| RelaxWhitespace
| RelaxWhitespace2
| NameOf
| ImplicitYield
| DotlessFloat32Literal
| PackageManagement
| FromEndSlicing
Expand Down Expand Up @@ -153,7 +152,6 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
LanguageFeature.SingleUnderscorePattern, languageVersion47
LanguageFeature.WildCardInForLoop, languageVersion47
LanguageFeature.RelaxWhitespace, languageVersion47
LanguageFeature.ImplicitYield, languageVersion47

// F# 5.0
LanguageFeature.FixedIndexSlice3d4d, languageVersion50
Expand Down Expand Up @@ -365,7 +363,6 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
| LanguageFeature.RelaxWhitespace -> FSComp.SR.featureRelaxWhitespace ()
| LanguageFeature.RelaxWhitespace2 -> FSComp.SR.featureRelaxWhitespace2 ()
| LanguageFeature.NameOf -> FSComp.SR.featureNameOf ()
| LanguageFeature.ImplicitYield -> FSComp.SR.featureImplicitYield ()
| LanguageFeature.DotlessFloat32Literal -> FSComp.SR.featureDotlessFloat32Literal ()
| LanguageFeature.PackageManagement -> FSComp.SR.featurePackageManagement ()
| LanguageFeature.FromEndSlicing -> FSComp.SR.featureFromEndSlicing ()
Expand Down
1 change: 0 additions & 1 deletion src/Compiler/Facilities/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ type LanguageFeature =
| RelaxWhitespace
| RelaxWhitespace2
| NameOf
| ImplicitYield
| DotlessFloat32Literal
| PackageManagement
| FromEndSlicing
Expand Down
20 changes: 0 additions & 20 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading