Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
98 changes: 64 additions & 34 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3518,14 +3518,57 @@ 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 =
let langVersionSupportsImplicitYield = cenv.g.langVersion.SupportsFeature 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, _) ->
if cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield then
YieldFree body
else
false

| SynExpr.YieldOrReturn((true, _), _, _) when langVersionSupportsImplicitYield -> false

| SynExpr.YieldOrReturnFrom _
| SynExpr.YieldOrReturn _
| SynExpr.ImplicitZero _
| SynExpr.Do _ when not langVersionSupportsImplicitYield -> false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could this be moved up so that it's below YieldOrReturn?

This was a little hard for me to read since I had was mistakenly thinking that the previous cases would also evaluate to false before I realized there was a guard here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the aim is to re-introduce the exact same code that was present for prior versions of F#, so we should keep it exactly as it was

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KevinRansom Can you move this back to the matching location so the diff is minimized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ dsyme, this is the original location … You moved it, once it was no longer necessary in |SimpleSemicolonSequence|. However, it needs to be in there to verify YieldFree (ness) for IfThenElse.


| _ -> 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 not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield) && acceptDeprecated && YieldFree cenv expr -> true
| SynExpr.IfThenElse _
| SynExpr.TryWith _
| SynExpr.Match _
| SynExpr.For _
Expand Down Expand Up @@ -5932,6 +5975,8 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =
match comp with
| SynExpr.New _ ->
errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m))
| SimpleSemicolonSequence cenv false _ when not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield) ->
errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m))
| _ ->
()
if not !isNotNakedRefCell && not cenv.g.compilingFslib then
Expand All @@ -5941,9 +5986,13 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =

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

let acceptDeprecated = not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield)
match comp with
| SynExpr.CompExpr (_, _, SimpleSemicolonSequence elems, _) ->
| SynExpr.CompExpr (_, _, (SimpleSemicolonSequence cenv acceptDeprecated elems as body), _) ->
match body with
| SimpleSemicolonSequence cenv false _ -> ()
| _ when not (cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield) -> errorR(Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis(), m))
| _ -> ()

let replacementExpr =
if isArray then
Expand Down Expand Up @@ -7331,31 +7380,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 +7838,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 +8226,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 +8468,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 +8532,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
5 changes: 5 additions & 0 deletions src/fsharp/xlf/FSComp.txt.ru.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
Loading