@@ -68,8 +68,6 @@ type cenv =
68
68
69
69
amap: Import .ImportMap
70
70
71
- reportErrors: bool
72
-
73
71
/// Values in module that have been marked [<TailCall>]
74
72
mustTailCall: Zset < Val >
75
73
}
@@ -140,81 +138,79 @@ let rec mkArgsForAppliedExpr isBaseCall argsl x =
140
138
| Expr.Op( TOp.Coerce, _, [ f ], _) -> mkArgsForAppliedExpr isBaseCall argsl f
141
139
| _ -> []
142
140
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
-
147
141
/// 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 ) =
149
143
let g = cenv.g
150
144
let expr = stripExpr expr
151
145
let expr = stripDebugPoints expr
152
146
153
147
match expr with
154
148
| Expr.App( f, _ fty, _ tyargs, argsl, m) ->
155
149
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)
207
167
else
208
- true
168
+ ([], argsl )
209
169
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
+ | _ -> ()
216
208
| _ -> ()
217
209
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
+
218
214
/// Check call arguments, including the return argument.
219
215
and CheckCall cenv args ctxts ( tailCall : TailCall ) =
220
216
// detect CPS-like expressions
@@ -730,10 +726,7 @@ and CheckBindings cenv binds =
730
726
let CheckModuleBinding cenv ( isRec : bool ) ( TBind _ as bind ) =
731
727
732
728
// 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
737
730
let isNotAFunction =
738
731
match bind.Var.ValReprInfo with
739
732
| Some info -> info.HasNoArgs
@@ -842,14 +835,17 @@ and CheckModuleSpec cenv isRec mbind =
842
835
843
836
| ModuleOrNamespaceBinding.Module(_ mspec, rhs) -> CheckDefnInModule cenv rhs
844
837
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