Skip to content

Commit

Permalink
[RFC FS-1110, 1111] index syntax and ref cell op deprecation (#11900)
Browse files Browse the repository at this point in the history
* indexer notation expr[expr]

* add tests

* back compat

* update tests

* fix build

* fix build

* fix additional case of syntactic sugar triggering warning

* fix warning#

* fix warnings

* fix warning#

* improve messages

* remvoe test case no longer of interest

* emit informationals

* update baselines

* don't produce informationals for expr.[idx] as yet

* tweak error messages

* remove dead code

* merge main

* fix tests

* fix tests

* fix tests

* fix tests

* improve diagnostics

* add aka.ms links

* update baselines

* fix error messages

* change warning to informational in preview

* fix test

* code review feedback

* code review feedback

* Update salsa.fs

Co-authored-by: Don Syme <[email protected]>
  • Loading branch information
dsyme and Don Syme authored Aug 23, 2021
1 parent 69f4495 commit 699291a
Show file tree
Hide file tree
Showing 98 changed files with 3,376 additions and 1,003 deletions.
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

0 comments on commit 699291a

Please sign in to comment.