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

[RFC FS-1110, 1111] index syntax and ref cell op deprecation #11900

Merged
merged 34 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
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
81 changes: 64 additions & 17 deletions src/fsharp/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@ let TcComputationExpression cenv env (overallTy: OverallTy) tpenv (mWhole, inter


| SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) ->
let sourceExpr =
match RewriteRangeExpr sourceExpr with
| Some e -> e
| None -> sourceExpr
let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr
let mFor = match spForLoop with DebugPointAtFor.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.For) | _ -> pat.Range
let mPat = pat.Range
Expand Down Expand Up @@ -1727,6 +1731,10 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m =
let rec tryTcSequenceExprBody env genOuterTy tpenv comp =
match comp with
| SynExpr.ForEach (spFor, SeqExprOnly _seqExprOnly, _isFromSource, pat, pseudoEnumExpr, innerComp, m) ->
let pseudoEnumExpr =
match RewriteRangeExpr pseudoEnumExpr with
| Some e -> e
| None -> pseudoEnumExpr
// This expression is not checked with the knowledge it is an IEnumerable, since we permit other enumerable types with GetEnumerator/MoveNext methods, as does C#
let pseudoEnumExpr, arb_ty, tpenv = TcExprOfUnknownType cenv env tpenv pseudoEnumExpr
let enumExpr, enumElemTy = ConvertArbitraryExprToEnumerable cenv arb_ty env pseudoEnumExpr
Expand Down Expand Up @@ -1932,31 +1940,70 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m =
let delayedExpr = mkDelayedExpr coreExpr.Range coreExpr
delayedExpr, tpenv

let TcSequenceExpressionEntry (cenv: cenv) env (overallTy: OverallTy) tpenv (isArrayOrList, isNotNakedRefCell, comp) m =
let TcSequenceExpressionEntry (cenv: cenv) env (overallTy: OverallTy) tpenv (hasBuilder, comp) m =
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
if not isArrayOrList then
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
match comp with
| SynExpr.New _ ->
errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m))
| SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression ->
errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m))
| _ ->
()
if not hasBuilder && not cenv.g.compilingFslib then
error(Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm(), m))

TcSequenceExpression cenv env tpenv comp overallTy m

let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, comp) m =
let TcArrayOrListComputedExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (isArray, comp) m =
// The syntax '[ n .. m ]' and '[ n .. step .. m ]' is not really part of array or list syntax.
// It could be in the future, e.g. '[ 1; 2..30; 400 ]'
//
// The elaborated form of '[ n .. m ]' is 'List.ofSeq (seq (op_Range n m))' and this shouldn't change
match RewriteRangeExpr comp with
| Some replacementExpr ->
let genCollElemTy = NewInferenceType ()

let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy

UnifyTypes cenv env m overallTy.Commit genCollTy

let exprTy = mkSeqTy cenv.g genCollElemTy

let expr, tpenv = TcExpr cenv (MustEqual exprTy) env tpenv replacementExpr
let expr =
if cenv.g.compilingFslib then
//warning(Error(FSComp.SR.fslibUsingComputedListOrArray(), expr.Range))
expr
else
// We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the
// comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined.
mkCallSeq cenv.g m genCollElemTy expr

let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy.Commit)

let expr =
if isArray then
mkCallSeqToArray cenv.g m genCollElemTy expr
else
mkCallSeqToList cenv.g m genCollElemTy expr
expr, tpenv

| 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
| SynExpr.CompExpr (_, _, (SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems as body), _) ->
match body with
| SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems ->
match comp with
| SimpleSemicolonSequence cenv false _ -> ()
| _ when validateExpressionWithIfRequiresParenthesis -> errorR(Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis(), m))
| _ -> ()
Expand Down Expand Up @@ -1986,12 +2033,12 @@ let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, c
// let x : seq<int64> = [ yield 1; if true then yield 2 ]
TcPropagatingExprLeafThenConvert cenv overallTy genCollTy env (* canAdhoc *) m (fun () ->

let exprty = mkSeqTy cenv.g genCollElemTy
let exprTy = mkSeqTy cenv.g genCollElemTy

// Check the comprehension
let expr, tpenv = TcExpr cenv (MustEqual exprty) env tpenv comp
let expr, tpenv = TcSequenceExpression cenv env tpenv comp (MustEqual exprTy) m

let expr = mkCoerceIfNeeded cenv.g exprty (tyOfExpr cenv.g expr) expr
let expr = mkCoerceIfNeeded cenv.g exprTy (tyOfExpr cenv.g expr) expr

let expr =
if cenv.g.compilingFslib then
Expand All @@ -2002,7 +2049,7 @@ let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, c
// comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined.
mkCallSeq cenv.g m genCollElemTy expr

let expr = mkCoerceExpr(expr, exprty, expr.Range, overallTy.Commit)
let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy.Commit)

let expr =
if isArray then
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/CheckComputationExpressions.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ open FSharp.Compiler.Syntax
open FSharp.Compiler.Text
open FSharp.Compiler.TypedTree

val TcSequenceExpressionEntry: cenv:TcFileState -> env:TcEnv -> overallTy:OverallTy -> tpenv:UnscopedTyparEnv -> isArrayOrList:bool * isNotNakedRefCell:bool ref * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv
val TcSequenceExpressionEntry: cenv:TcFileState -> env:TcEnv -> overallTy:OverallTy -> tpenv:UnscopedTyparEnv -> hasBuilder:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv

val TcArrayOrListSequenceExpression: cenv:TcFileState -> env:TcEnv -> overallTy:OverallTy -> tpenv:UnscopedTyparEnv -> isArray:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv
val TcArrayOrListComputedExpression: cenv:TcFileState -> env:TcEnv -> overallTy:OverallTy -> tpenv:UnscopedTyparEnv -> isArray:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv

val TcComputationExpression: cenv:TcFileState -> env:TcEnv -> overallTy:OverallTy -> tpenv:UnscopedTyparEnv -> mWhole:range * interpExpr:Expr * builderTy:TType * comp:SynExpr -> Expr * UnscopedTyparEnv

4 changes: 2 additions & 2 deletions src/fsharp/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5806,7 +5806,7 @@ let TypeCheckOneImplFile
cenv.Create (g, isScript, niceNameGen, amap, topCcu, false, Option.isSome rootSigOpt,
conditionalDefines, tcSink, (LightweightTcValForUsingInBuildMethodCall g), isInternalTestSpanStackReferring,
tcSequenceExpressionEntry=TcSequenceExpressionEntry,
tcArrayOrListSequenceExpression=TcArrayOrListSequenceExpression,
tcArrayOrListSequenceExpression=TcArrayOrListComputedExpression,
tcComputationExpression=TcComputationExpression)

let envinner, mtypeAcc = MakeInitialEnv env
Expand Down Expand Up @@ -5913,7 +5913,7 @@ let TypeCheckOneSigFile (g, niceNameGen, amap, topCcu, checkForErrors, condition
(g, false, niceNameGen, amap, topCcu, true, false, conditionalDefines, tcSink,
(LightweightTcValForUsingInBuildMethodCall g), isInternalTestSpanStackReferring,
tcSequenceExpressionEntry=TcSequenceExpressionEntry,
tcArrayOrListSequenceExpression=TcArrayOrListSequenceExpression,
tcArrayOrListSequenceExpression=TcArrayOrListComputedExpression,
tcComputationExpression=TcComputationExpression)

let envinner, mtypeAcc = MakeInitialEnv tcEnv
Expand Down
Loading