@@ -68,8 +68,6 @@ type cenv =
6868
6969 amap: Import .ImportMap
7070
71- reportErrors: bool
72-
7371 /// Values in module that have been marked [<TailCall>]
7472 mustTailCall: Zset < Val >
7573 }
@@ -140,81 +138,79 @@ let rec mkArgsForAppliedExpr isBaseCall argsl x =
140138 | Expr.Op( TOp.Coerce, _, [ f ], _) -> mkArgsForAppliedExpr isBaseCall argsl f
141139 | _ -> []
142140
143- /// Check an expression, where the expression is in a position where byrefs can be generated
144- let rec CheckExprNoByrefs cenv ( tailCall : TailCall ) expr =
145- CheckExpr cenv expr PermitByRefExpr.No tailCall
146-
147141/// Check an expression, warn if it's attributed with TailCall but our analysis concludes it's not a valid tail call
148- and CheckForNonTailRecCall ( cenv : cenv ) expr ( tailCall : TailCall ) =
142+ let CheckForNonTailRecCall ( cenv : cenv ) expr ( tailCall : TailCall ) =
149143 let g = cenv.g
150144 let expr = stripExpr expr
151145 let expr = stripDebugPoints expr
152146
153147 match expr with
154148 | Expr.App( f, _ fty, _ tyargs, argsl, m) ->
155149
156- if cenv.reportErrors then
157- if cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage then
158- match f with
159- | ValUseAtApp( vref, valUseFlags) when cenv.mustTailCall.Contains vref.Deref ->
160-
161- let canTailCall =
162- match tailCall with
163- | TailCall.No -> // an upper level has already decided that this is not in a tailcall position
164- false
165- | TailCall.Yes returnType ->
166- if vref.IsMemberOrModuleBinding && vref.ValReprInfo.IsSome then
167- let topValInfo = vref.ValReprInfo.Value
168-
169- let nowArgs , laterArgs =
170- let _ , curriedArgInfos , _ , _ =
171- GetValReprTypeInFSharpForm cenv.g topValInfo vref.Type m
172-
173- if argsl.Length >= curriedArgInfos.Length then
174- ( List.splitAfter curriedArgInfos.Length argsl)
175- else
176- ([], argsl)
177-
178- let numEnclosingTypars = CountEnclosingTyparsOfActualParentOfVal vref.Deref
179-
180- let _ , _ , _ , returnTy , _ =
181- GetValReprTypeInCompiledForm g topValInfo numEnclosingTypars vref.Type m
182-
183- let _ , _ , isNewObj , isSuperInit , isSelfInit , _ , _ , _ =
184- GetMemberCallInfo cenv.g ( vref, valUseFlags)
185-
186- let isCCall =
187- match valUseFlags with
188- | PossibleConstrainedCall _ -> true
189- | _ -> false
190-
191- let hasByrefArg = nowArgs |> List.exists ( tyOfExpr cenv.g >> isByrefTy cenv.g)
192-
193- let mustGenerateUnitAfterCall =
194- ( Option.isNone returnTy && returnType <> TailCallReturnType.MustReturnVoid)
195-
196- let noTailCallBlockers =
197- not isNewObj
198- && not isSuperInit
199- && not isSelfInit
200- && not mustGenerateUnitAfterCall
201- && isNil laterArgs
202- && not ( IsValRefIsDllImport cenv.g vref)
203- && not isCCall
204- && not hasByrefArg
205-
206- noTailCallBlockers // blockers that will prevent the IL level from emmiting a tail instruction
150+ match f with
151+ | ValUseAtApp( vref, valUseFlags) when cenv.mustTailCall.Contains vref.Deref ->
152+
153+ let canTailCall =
154+ match tailCall with
155+ | TailCall.No -> // an upper level has already decided that this is not in a tailcall position
156+ false
157+ | TailCall.Yes returnType ->
158+ if vref.IsMemberOrModuleBinding && vref.ValReprInfo.IsSome then
159+ let topValInfo = vref.ValReprInfo.Value
160+
161+ let nowArgs , laterArgs =
162+ let _ , curriedArgInfos , _ , _ =
163+ GetValReprTypeInFSharpForm cenv.g topValInfo vref.Type m
164+
165+ if argsl.Length >= curriedArgInfos.Length then
166+ ( List.splitAfter curriedArgInfos.Length argsl)
207167 else
208- true
168+ ([], argsl )
209169
210- // warn if we call inside of recursive scope in non-tail-call manner/with tail blockers. See
211- // ``Warn successfully in match clause``
212- // ``Warn for byref parameters``
213- if not canTailCall then
214- warning ( Error( FSComp.SR.chkNotTailRecursive vref.DisplayName, m))
215- | _ -> ()
170+ let numEnclosingTypars = CountEnclosingTyparsOfActualParentOfVal vref.Deref
171+
172+ let _ , _ , _ , returnTy , _ =
173+ GetValReprTypeInCompiledForm g topValInfo numEnclosingTypars vref.Type m
174+
175+ let _ , _ , isNewObj , isSuperInit , isSelfInit , _ , _ , _ =
176+ GetMemberCallInfo cenv.g ( vref, valUseFlags)
177+
178+ let isCCall =
179+ match valUseFlags with
180+ | PossibleConstrainedCall _ -> true
181+ | _ -> false
182+
183+ let hasByrefArg = nowArgs |> List.exists ( tyOfExpr cenv.g >> isByrefTy cenv.g)
184+
185+ let mustGenerateUnitAfterCall =
186+ ( Option.isNone returnTy && returnType <> TailCallReturnType.MustReturnVoid)
187+
188+ let noTailCallBlockers =
189+ not isNewObj
190+ && not isSuperInit
191+ && not isSelfInit
192+ && not mustGenerateUnitAfterCall
193+ && isNil laterArgs
194+ && not ( IsValRefIsDllImport cenv.g vref)
195+ && not isCCall
196+ && not hasByrefArg
197+
198+ noTailCallBlockers // blockers that will prevent the IL level from emmiting a tail instruction
199+ else
200+ true
201+
202+ // warn if we call inside of recursive scope in non-tail-call manner/with tail blockers. See
203+ // ``Warn successfully in match clause``
204+ // ``Warn for byref parameters``
205+ if not canTailCall then
206+ warning ( Error( FSComp.SR.chkNotTailRecursive vref.DisplayName, m))
207+ | _ -> ()
216208 | _ -> ()
217209
210+ /// Check an expression, where the expression is in a position where byrefs can be generated
211+ let rec CheckExprNoByrefs cenv ( tailCall : TailCall ) expr =
212+ CheckExpr cenv expr PermitByRefExpr.No tailCall
213+
218214/// Check call arguments, including the return argument.
219215and CheckCall cenv args ctxts ( tailCall : TailCall ) =
220216 // detect CPS-like expressions
@@ -730,10 +726,7 @@ and CheckBindings cenv binds =
730726let CheckModuleBinding cenv ( isRec : bool ) ( TBind _ as bind ) =
731727
732728 // warn for non-rec functions which have the attribute
733- if
734- cenv.reportErrors
735- && cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec
736- then
729+ if cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec then
737730 let isNotAFunction =
738731 match bind.Var.ValReprInfo with
739732 | Some info -> info.HasNoArgs
@@ -842,14 +835,17 @@ and CheckModuleSpec cenv isRec mbind =
842835
843836 | ModuleOrNamespaceBinding.Module(_ mspec, rhs) -> CheckDefnInModule cenv rhs
844837
845- let CheckImplFile ( g , amap , reportErrors , implFileContents ) =
846- let cenv =
847- {
848- g = g
849- reportErrors = reportErrors
850- stackGuard = StackGuard( PostInferenceChecksStackGuardDepth, " CheckImplFile" )
851- amap = amap
852- mustTailCall = Zset.empty valOrder
853- }
854-
855- CheckDefnInModule cenv implFileContents
838+ let CheckImplFile ( g : TcGlobals , amap , reportErrors , implFileContents ) =
839+ if
840+ reportErrors
841+ && g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage
842+ then
843+ let cenv =
844+ {
845+ g = g
846+ stackGuard = StackGuard( PostInferenceChecksStackGuardDepth, " CheckImplFile" )
847+ amap = amap
848+ mustTailCall = Zset.empty valOrder
849+ }
850+
851+ CheckDefnInModule cenv implFileContents
0 commit comments