Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ tcUseWhenPatternGuard,"Character range matches have been removed in F#. Consider
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'"
Expand Down
3 changes: 3 additions & 0 deletions src/fsharp/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type LanguageFeature =
| WildCardInForLoop = 3
| RelaxWhitespace = 4
| NameOf = 5
| ImplicitYield = 6


/// LanguageVersion management
type LanguageVersion (specifiedVersion) =
Expand All @@ -49,6 +51,7 @@ type LanguageVersion (specifiedVersion) =
LanguageFeature.WildCardInForLoop, previewVersion
LanguageFeature.RelaxWhitespace, previewVersion
LanguageFeature.NameOf, previewVersion
LanguageFeature.ImplicitYield, previewVersion
|]

let specified =
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type LanguageFeature =
| WildCardInForLoop = 3
| RelaxWhitespace = 4
| NameOf = 5
| ImplicitYield = 6


/// LanguageVersion management
type LanguageVersion =
Expand Down
131 changes: 97 additions & 34 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3518,14 +3518,84 @@ let (|ExprAsPat|_|) (f: SynExpr) =
None
| _ -> None

/// Check if a computation or sequence expression is syntactically free of 'yield' (though not yield!)
let YieldFree cenv 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 (_, _, e1, e2, _) ->
YieldFree e1 && YieldFree e2

| SynExpr.IfThenElse (_, e2, e3opt, _, _, _, _) ->
YieldFree e2 && Option.forall YieldFree e3opt

| SynExpr.TryWith (e1, _, clauses, _, _, _, _) ->
YieldFree e1 && clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)

| (SynExpr.Match (_, _, clauses, _) | SynExpr.MatchBang (_, _, clauses, _)) ->
clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)

| SynExpr.For (_, _, _, _, _, body, _)
| SynExpr.TryFinally (body, _, _, _, _)
| SynExpr.LetOrUse (_, _, _, body, _)
| SynExpr.While (_, _, body, _)
| SynExpr.ForEach (_, _, _, _, _, body, _) ->
YieldFree body

| SynExpr.LetOrUseBang(_, _, _, _, _, body, _) ->
YieldFree body

| SynExpr.YieldOrReturn((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 (_, _, e1, e2, _) ->
YieldFree e1 && YieldFree e2

| SynExpr.IfThenElse (_, e2, e3opt, _, _, _, _) ->
YieldFree e2 && Option.forall YieldFree e3opt

| SynExpr.TryWith (e1, _, clauses, _, _, _, _) ->
YieldFree e1 && clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)

| (SynExpr.Match (_, _, clauses, _) | SynExpr.MatchBang (_, _, clauses, _)) ->
clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)

| SynExpr.For (_, _, _, _, _, body, _)
| SynExpr.TryFinally (body, _, _, _, _)
| SynExpr.LetOrUse (_, _, _, body, _)
| SynExpr.While (_, _, body, _)
| SynExpr.ForEach (_, _, _, _, _, body, _) ->
YieldFree body

| SynExpr.LetOrUseBang _
| SynExpr.YieldOrReturnFrom _
| SynExpr.YieldOrReturn _
| SynExpr.ImplicitZero _
| SynExpr.Do _ -> false

| _ -> true

YieldFree expr


/// 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
///
let (|SimpleSemicolonSequence|_|) cexpr =
let (|SimpleSemicolonSequence|_|) cenv acceptDeprecated cexpr =

let IsSimpleSemicolonSequenceElement expr =
match expr with
| SynExpr.IfThenElse _
match expr with
| SynExpr.IfThenElse _ when acceptDeprecated && YieldFree cenv expr -> true
| SynExpr.IfThenElse _
| SynExpr.TryWith _
| SynExpr.Match _
| SynExpr.For _
Expand Down Expand Up @@ -5734,6 +5804,13 @@ and TcExprUndelayedNoType cenv env tpenv synExpr: Expr * TType * _ =
expr, overallTy, tpenv

and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =

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

match synExpr with
| SynExpr.Paren (expr2, _, _, mWholeExprIncludingParentheses) ->
// We invoke CallExprHasTypeSink for every construct which is atomic in the syntax, i.e. where a '.' immediately following the
Expand Down Expand Up @@ -5932,6 +6009,8 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =
match comp with
| SynExpr.New _ ->
errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m))
| SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression ->
errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m))
| _ ->
()
if not !isNotNakedRefCell && not cenv.g.compilingFslib then
Expand All @@ -5941,9 +6020,12 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =

| SynExpr.ArrayOrListOfSeqExpr (isArray, comp, m) ->
CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.DisplayEnv, env.eAccessRights)

match comp with
| SynExpr.CompExpr (_, _, SimpleSemicolonSequence elems, _) ->
| SynExpr.CompExpr (_, _, (SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems as body), _) ->
match body with
| SimpleSemicolonSequence cenv false _ -> ()
| _ when validateExpressionWithIfRequiresParenethesis -> errorR(Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis(), m))
| _ -> ()

let replacementExpr =
if isArray then
Expand Down Expand Up @@ -7331,31 +7413,6 @@ and TcQuotationExpr cenv overallTy env tpenv (_oper, raw, ast, isFromQueryExpres
/// Ignores an attribute
and IgnoreAttribute _ = None

/// Check if a computation or sequence expression is syntactically free of 'yield' (though not yield!)
and YieldFree expr =
match expr with
| SynExpr.Sequential (_, _, e1, e2, _) -> YieldFree e1 && YieldFree e2
| SynExpr.IfThenElse (_, e2, e3opt, _, _, _, _) -> YieldFree e2 && Option.forall YieldFree e3opt
| SynExpr.TryWith (e1, _, clauses, _, _, _, _) ->
YieldFree e1 && clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)
| (SynExpr.Match (_, _, clauses, _) | SynExpr.MatchBang (_, _, clauses, _)) ->
clauses |> List.forall (fun (Clause(_, _, e, _, _)) -> YieldFree e)
| SynExpr.For (_, _, _, _, _, body, _)
| SynExpr.TryFinally (body, _, _, _, _)
| SynExpr.LetOrUse (_, _, _, body, _)
| SynExpr.LetOrUseBang(_, _, _, _, _, body, _)
| SynExpr.LetOrUse (_, _, _, body, _)
| SynExpr.While (_, _, body, _)
| SynExpr.ForEach (_, _, _, _, _, body, _) ->
YieldFree body

// 'yield!' in expressions doesn't trigger the 'yield free' rule
//| SynExpr.YieldOrReturnFrom _
| SynExpr.YieldOrReturn((true, _), _, _) ->
false

| _ -> true

/// Used for all computation expressions except sequence expressions
and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builderTy tpenv (comp: SynExpr) =

Expand Down Expand Up @@ -7814,7 +7871,9 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
// If there are no 'yield' in the computation expression, and the builder supports 'Yield',
// 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 = hasMethInfo "Yield" && hasMethInfo "Combine" && hasMethInfo "Delay" && YieldFree comp
let enableImplicitYield =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield
&& (hasMethInfo "Yield" && hasMethInfo "Combine" && hasMethInfo "Delay" && YieldFree cenv comp)

// q - a flag indicating if custom operators are allowed. They are not allowed inside try/with, try/finally, if/then/else etc.
// varSpace - a lazy data structure indicating the variables bound so far in the overall computation
Expand Down Expand Up @@ -8200,8 +8259,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
| _ ->
Some (trans true q varSpace innerComp2 (fun holeFill ->
let fillExpr =
if enableImplicitYield then

if enableImplicitYield then
// When implicit yields are enabled, then if the 'innerComp1' checks as type
// 'unit' we interpret the expression as a sequential, and when it doesn't
// have type 'unit' we interpret it as a 'Yield + Combine'.
Expand Down Expand Up @@ -8443,7 +8501,9 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =
// 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 = YieldFree comp
let enableImplicitYield =
cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield
&& (YieldFree cenv comp)

let mkDelayedExpr (coreExpr: Expr) =
let m = coreExpr.Range
Expand Down Expand Up @@ -8505,6 +8565,9 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =

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

| SynExpr.Paren (_, _, _, 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 )

Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Neplatný objektový výraz. U objektů bez přepsání nebo rozhraní by se měl výraz formulovat pomocí notace new Type(args) bez složených závorek.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Neplatný výraz objektu, pořadí nebo záznamu</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Neplatný výraz záznamu, pořadí nebo výpočtu. Výrazy pořadí by měly mít notaci seq {{ ... }}.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Ungültiger Objektausdruck. Objekte ohne Überschreibungen oder Schnittstellen sollten das Ausdrucksformat "new Type(args)" ohne geschweifte Klammern verwenden.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Ungültiger Objekt-, Sequenz- oder Datensatzausdruck.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Ungültiger Datensatz-, Sequenz- oder Berechnungsausdruck. Sequenzausdrücke müssen das Format "seq {{ ... }}" besitzen.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Expresión de objeto no válida. Los objetos sin invalidaciones ni interfaces deben usar el formato de expresión 'new Type(args)' sin llaves.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Expresión de objeto, secuencia o registro no válida.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Expresión de registro, secuencia o cómputo no válida. Las expresiones de secuencia deben tener el formato 'seq {{ ... }}'.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Expression d'objet non valide. Les objets sans substitutions ou interfaces doivent utiliser la forme d'expression 'new Type(args)' sans accolades.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Expression d'objet, de séquence ou d'enregistrement non valide</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Expression d'enregistrement, de séquence ou de calcul non valide. Les expressions de séquence doivent avoir le format 'seq {{ ... }}'</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Espressione oggetto non valida. Gli oggetti senza override o interfacce devono usare il formato di espressione 'new Type(args)' senza parentesi graffe.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Espressione record, sequenza o oggetto non valida</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Espressione di calcolo, sequenza o record non valida. Il formato delle espressioni sequenza deve essere 'seq {{ ... }}'</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">オブジェクト式が無効です。オーバーライドまたはインターフェイスがないオブジェクトには、かっこなしで 'new Type(args)' という形式の式を使用してください。</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">オブジェクト式、シーケンス式、またはレコード式が無効です</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">無効なレコード、シーケンス式、またはコンピュテーション式です。シーケンス式は 'seq {{ ... }}' という形式にしてください。</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">개체 식이 잘못되었습니다. 재정의 또는 인터페이스가 없는 개체는 중괄호 없이 식 형식 'new Type(args)'을 사용해야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">개체, 시퀀스 또는 레코드 식이 잘못되었습니다.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">레코드, 시퀀스 또는 계산 식이 잘못되었습니다. 시퀀스 식의 형식은 'seq {{ ... }}'여야 합니다.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Nieprawidłowe wyrażenie obiektu. Obiekty bez przesłonięć lub interfejsy powinny używać wyrażenia w postaci „new Typ(argumenty)” bez nawiasów.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Nieprawidłowe wyrażenie obiektu, sekwencji lub rekordu</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Nieprawidłowe wyrażenie rekordu, sekwencji lub obliczenia. Wyrażenia sekwencji powinny mieć postać „seq {{ ... }}”</target>
Expand Down
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,11 @@
<target state="translated">Expressão de objeto inválida. Objetos sem substituições ou interfaces devem usar o formato de expressão 'new Type(args)' sem as chaves.</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidObjectSequenceOrRecordExpression">
<source>Invalid object, sequence or record expression</source>
<target state="translated">Expressão de objeto, sequência ou registro inválida</target>
<note />
</trans-unit>
<trans-unit id="tcInvalidSequenceExpressionSyntaxForm">
<source>Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq {{ ... }}'</source>
<target state="translated">Expressão de registro, sequência ou computação inválida. Expressões de sequência devem estar na forma 'seq {{ ... }}'</target>
Expand Down
Loading