@@ -4253,6 +4253,12 @@ type TyconBindingDefn = TyconBindingDefn of ContainerInfo * NewSlotsOK * DeclKin
42534253
42544254type ValSpecResult = ValSpecResult of ParentRef * ValMemberInfoTransient option * Ident * Typars * Typars * TType * PartialValReprInfo * DeclKind
42554255
4256+ /// Used to flag if this is the first or a sebsequent translation pass through a computation expression
4257+ type CompExprTranslationPass = Initial | Subsequent
4258+
4259+ /// Used to flag if computation expression custom operations are allowed in a given context
4260+ type CustomOperationsMode = Allowed | Denied
4261+
42564262//-------------------------------------------------------------------------
42574263// Additional data structures used by checking recursive bindings
42584264//-------------------------------------------------------------------------
@@ -7950,7 +7956,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
79507956 | _ -> None
79517957
79527958 /// Decide if the identifier represents a use of a custom query operator
7953- let hasCustomOperations () = not ( isNil customOperationMethods)
7959+ let hasCustomOperations () = if isNil customOperationMethods then CustomOperationsMode.Denied else CustomOperationsMode.Allowed
79547960
79557961 let isCustomOperation nm = tryGetDataForCustomOperation nm |> Option.isSome
79567962
@@ -8333,7 +8339,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
83338339 | ForEachThenJoinOrGroupJoinOrZipClause (isFromSource, firstSourcePat, firstSource, nm, secondSourcePat, secondSource, keySelectorsOpt, secondResultPatOpt, mOpCore, innerComp) ->
83348340
83358341
8336- if not q then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), nm.idRange))
8342+ if q = CustomOperationsMode.Denied then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), nm.idRange))
83378343 let firstSource = mkSourceExprConditional isFromSource firstSource
83388344 let secondSource = mkSourceExpr secondSource
83398345
@@ -8474,7 +8480,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
84748480 let varSpaceExpr = mkExprForVarSpace mOpCore valsInner
84758481 let varSpacePat = mkPatForVarSpace mOpCore valsInner
84768482 let joinExpr = mkOverallExprGivenVarSpaceExpr varSpaceExpr
8477- Some (trans true q varSpaceInner (SynExpr.ForEach (DebugPointAtFor.No, SeqExprOnly false, false, varSpacePat, joinExpr, innerComp, mOpCore)) translatedCtxt)
8483+ Some (trans CompExprTranslationPass.Initial q varSpaceInner (SynExpr.ForEach (DebugPointAtFor.No, SeqExprOnly false, false, varSpacePat, joinExpr, innerComp, mOpCore)) translatedCtxt)
84788484
84798485
84808486 | SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) ->
@@ -8492,14 +8498,14 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
84928498 let _, _, vspecs, envinner, _ = TcMatchPattern cenv (NewInferenceType()) env tpenv (pat, None)
84938499 vspecs, envinner)
84948500
8495- Some (trans true q varSpace innerComp
8501+ Some (trans CompExprTranslationPass.Initial q varSpace innerComp
84968502 (fun holeFill ->
84978503 translatedCtxt (mkSynCall "For" mFor [wrappedSourceExpr; SynExpr.MatchLambda (false, sourceExpr.Range, [Clause(pat, None, holeFill, mPat, DebugPointForTarget.Yes)], spBind, mFor) ])) )
84988504
84998505 | SynExpr.For (spBind, id, start, dir, finish, innerComp, m) ->
85008506 let mFor = match spBind with DebugPointAtFor.Yes m -> m | _ -> m
85018507 if isQuery then errorR(Error(FSComp.SR.tcNoIntegerForLoopInQuery(), mFor))
8502- Some (trans true q varSpace (elimFastIntegerForLoop (spBind, id, start, dir, finish, innerComp, m)) translatedCtxt )
8508+ Some (trans CompExprTranslationPass.Initial q varSpace (elimFastIntegerForLoop (spBind, id, start, dir, finish, innerComp, m)) translatedCtxt )
85038509
85048510 | SynExpr.While (spWhile, guardExpr, innerComp, _) ->
85058511 let mGuard = guardExpr.Range
@@ -8509,7 +8515,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85098515 error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile))
85108516 if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "Delay" builderTy) then
85118517 error(Error(FSComp.SR.tcRequireBuilderMethod("Delay"), mWhile))
8512- Some(trans true q varSpace innerComp (fun holeFill -> translatedCtxt (mkSynCall "While" mWhile [mkSynDelay2 guardExpr; mkSynCall "Delay" mWhile [mkSynDelay innerComp.Range holeFill]])) )
8518+ Some(trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> translatedCtxt (mkSynCall "While" mWhile [mkSynDelay2 guardExpr; mkSynCall "Delay" mWhile [mkSynDelay innerComp.Range holeFill]])) )
85138519
85148520 | SynExpr.TryFinally (innerComp, unwindExpr, mTryToLast, spTry, _spFinally) ->
85158521
@@ -8529,7 +8535,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85298535 Some (translatedCtxt (mkSynCall "Zero" m []))
85308536
85318537 | OptionalSequential (JoinOrGroupJoinOrZipClause (_, _, _, _, _, mClause), _)
8532- when firstTry ->
8538+ when firstTry = CompExprTranslationPass.Initial ->
85338539
85348540 // 'join' clauses preceded by 'let' and other constructs get processed by repackaging with a 'for' loop.
85358541 let patvs, _env = varSpace.Force comp.Range
@@ -8544,12 +8550,12 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85448550 SynExpr.ForEach (DebugPointAtFor.No, SeqExprOnly false, false, varSpacePat, dataCompPrior, comp, comp.Range)
85458551
85468552 // Retry with the 'for' loop packaging. Set firstTry=false just in case 'join' processing fails
8547- tryTrans false q varSpace rebind id
8553+ tryTrans CompExprTranslationPass.Subsequent q varSpace rebind id
85488554
85498555
85508556 | OptionalSequential (CustomOperationClause (nm, _, opExpr, mClause, _), _) ->
85518557
8552- if not q then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), opExpr.Range))
8558+ if q = CustomOperationsMode.Denied then error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedHere(), opExpr.Range))
85538559
85548560 let patvs, _env = varSpace.Force comp.Range
85558561 let varSpaceExpr = mkExprForVarSpace mClause patvs
@@ -8566,7 +8572,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85668572
85678573 // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore innerComp1
85688574 if isQuery && checkForBinaryApp innerComp1 then
8569- Some (trans true q varSpace innerComp2 translatedCtxt)
8575+ Some (trans CompExprTranslationPass.Initial q varSpace innerComp2 translatedCtxt)
85708576
85718577 else
85728578
@@ -8575,7 +8581,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85758581 | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential
85768582 | _ -> errorR(Error(FSComp.SR.tcUnrecognizedQueryOperator(), innerComp1.RangeOfFirstPortion))
85778583
8578- match tryTrans true false varSpace innerComp1 id with
8584+ match tryTrans CompExprTranslationPass.Initial CustomOperationsMode.Denied varSpace innerComp1 id with
85798585 | Some c ->
85808586 // "cexpr; cexpr" is treated as builder.Combine(cexpr1, cexpr1)
85818587 // This is not pretty - we have to decide which range markers we use for the calls to Combine and Delay
@@ -8595,11 +8601,11 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
85958601 | DebugPointAtSequential.ExprOnly -> DebugPointAtBinding m
85968602 | DebugPointAtSequential.StmtOnly -> NoDebugPointAtDoBinding
85978603 | DebugPointAtSequential.Both -> DebugPointAtBinding m
8598- Some(trans true q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m)) translatedCtxt)
8604+ Some(trans CompExprTranslationPass.Initial q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m)) translatedCtxt)
85998605
86008606 // "expr; cexpr" is treated as sequential execution
86018607 | _ ->
8602- Some (trans true q varSpace innerComp2 (fun holeFill ->
8608+ Some (trans CompExprTranslationPass.Initial q varSpace innerComp2 (fun holeFill ->
86038609 let fillExpr =
86048610 if enableImplicitYield then
86058611 // When implicit yields are enabled, then if the 'innerComp1' checks as type
@@ -8624,7 +8630,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
86248630 if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mIfToThen ad "Zero" builderTy) then
86258631 error(Error(FSComp.SR.tcRequireBuilderMethod("Zero"), mIfToThen))
86268632 mkSynCall "Zero" mIfToThen []
8627- Some (trans true q varSpace thenComp (fun holeFill -> translatedCtxt (SynExpr.IfThenElse (guardExpr, holeFill, Some elseComp, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch))))
8633+ Some (trans CompExprTranslationPass.Initial q varSpace thenComp (fun holeFill -> translatedCtxt (SynExpr.IfThenElse (guardExpr, holeFill, Some elseComp, spIfToThen, isRecovery, mIfToThen, mIfToEndOfElseBranch))))
86288634
86298635 // 'let binds in expr'
86308636 | SynExpr.LetOrUse (isRec, false, binds, innerComp, m) ->
@@ -8654,7 +8660,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
86548660 // error case
86558661 error(Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings(), mQueryOp)))
86568662
8657- Some (trans true q varSpace innerComp (fun holeFill -> translatedCtxt (SynExpr.LetOrUse (isRec, false, binds, holeFill, m))))
8663+ Some (trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> translatedCtxt (SynExpr.LetOrUse (isRec, false, binds, holeFill, m))))
86588664
86598665 // 'use x = expr in expr'
86608666 | SynExpr.LetOrUse (_, true, [Binding (_, NormalBinding, _, _, _, _, _, pat, _, rhsExpr, _, spBind)], innerComp, _) ->
@@ -8958,7 +8964,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
89588964 else
89598965 SynExpr.ForEach (DebugPointAtFor.No, SeqExprOnly false, false, intoPat, dataCompAfterOp, contExpr, intoPat.Range)
89608966
8961- trans true q emptyVarSpace rebind id
8967+ trans CompExprTranslationPass.Initial q emptyVarSpace rebind id
89628968
89638969 // select a.Name; ...
89648970 // distinct; ...
@@ -8980,9 +8986,9 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
89808986 else
89818987 SynExpr.ForEach (DebugPointAtFor.No, SeqExprOnly false, false, varSpacePat, dataCompPrior, compClausesExpr, compClausesExpr.Range)
89828988
8983- trans true q varSpace rebind id
8989+ trans CompExprTranslationPass.Initial q varSpace rebind id
89848990 and transNoQueryOps comp =
8985- trans true false emptyVarSpace comp id
8991+ trans CompExprTranslationPass.Initial CustomOperationsMode.Denied emptyVarSpace comp id
89868992
89878993 and trans firstTry q varSpace comp translatedCtxt =
89888994 match tryTrans firstTry q varSpace comp translatedCtxt with
@@ -9000,20 +9006,20 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
90009006 SynExpr.ImplicitZero m
90019007 else
90029008 SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m)
9003- trans true q varSpace (SynExpr.LetOrUseBang (NoDebugPointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m)) translatedCtxt
9009+ trans CompExprTranslationPass.Initial q varSpace (SynExpr.LetOrUseBang (NoDebugPointAtDoBinding, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m)) translatedCtxt
90049010
90059011 // "expr;" in final position is treated as { expr; zero }
90069012 // Suppress the sequence point on the "zero"
90079013 | _ ->
90089014 // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore comp
90099015 if isQuery && checkForBinaryApp comp then
9010- trans true q varSpace (SynExpr.ImplicitZero comp.Range) translatedCtxt
9016+ trans CompExprTranslationPass.Initial q varSpace (SynExpr.ImplicitZero comp.Range) translatedCtxt
90119017 else
90129018 if isQuery && not comp.IsArbExprAndThusAlreadyReportedError then
90139019 match comp with
90149020 | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential
90159021 | _ -> errorR(Error(FSComp.SR.tcUnrecognizedQueryOperator(), comp.RangeOfFirstPortion))
9016- trans true q varSpace (SynExpr.ImplicitZero comp.Range) (fun holeFill ->
9022+ trans CompExprTranslationPass.Initial q varSpace (SynExpr.ImplicitZero comp.Range) (fun holeFill ->
90179023 let fillExpr =
90189024 if enableImplicitYield then
90199025 let implicitYieldExpr = mkSynCall "Yield" comp.Range [comp]
@@ -9055,7 +9061,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
90559061 error(Error(FSComp.SR.tcRequireBuilderMethod(bindName), bindRange))
90569062
90579063 // Build the `Bind` call
9058- trans true q varSpace innerComp (fun holeFill ->
9064+ trans CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill ->
90599065 let consumeExpr = SynExpr.MatchLambda(false, consumePat.Range, [Clause(consumePat, None, holeFill, innerRange, DebugPointForTarget.Yes)], spBind, innerRange)
90609066 translatedCtxt (mkSynCall bindName bindRange (bindArgs @ [consumeExpr])))
90619067
@@ -9146,7 +9152,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
91469152 | _ -> true
91479153
91489154 let basicSynExpr =
9149- trans true (hasCustomOperations ()) (LazyWithContext.NotLazy ([], env)) comp (fun holeFill -> holeFill)
9155+ trans CompExprTranslationPass.Initial (hasCustomOperations ()) (LazyWithContext.NotLazy ([], env)) comp (fun holeFill -> holeFill)
91509156
91519157 let delayedExpr =
91529158 match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mBuilderVal ad "Delay" builderTy with
0 commit comments