Skip to content

Commit b4c26d8

Browse files
dawedawepsfinaki
andauthored
Tail recursion warning and attribute, analysis after optimization (#15503)
* Add TailCall attribute Move work of Avi Avni to current sources but use a field in cenv instead of a function parameter to pass around * Adjust error number after merge * add two test cases for type members * Don't try to split empty CurriedArgInfos * Add more member tests * seems like we need to build up the env.mustTailCall set earlier in the traversal to have the content ready when checking members which call each other * Fix an error from migrating the old PR to current sources. * As cenv is mutated in loops, doing "with" copies isn't that great as the failing CI shows. Making isTailCall also mutable is error prone as one has to switch back to orig values in many places. So refactor to use a flag like Avi did. This should fix the side effects (shown by the failing CI) and more tailrec specific tests * update baselines for FSharp.Core to include TailCallAttribute * warn for rec call in binding, still very WIP * - improve check for problematic bindings to tailcall attributed functions - add tests * improve seq support * add language version flag * improve tests a bit * add tests for async expressions * add tests for module rec * Improve handling of ModuleOrNamespaceContents.TMDefDo and extend testing * suppress some invalid warnings by keeping track of ranges that are annotated with [<TailRec>] * fix build * use Stamp instead of LogicalName as the Map key * fix error number after merge * remove TailCall check code from PostInferenceChecks.fs * Add new file TailCallChecks.fs to focus on tail call checks * first steps to remove limits calculations * remove last bits of limits * don't bother with attribute checking here * remove more unneeded code * small optimization * Adjust error number after main merge * add TailCallChecks.fs to .fantomasignore * remove last non-tailrec error reporting from dedicated file * - add fsi file - trim down some more * simplify * Remove resumable checks * remove external handling * remove isInAppExpr * remove returnScope * remove boundTyparNames * remove argVals from env * let's drop quote and reflect, too, for now * remove usesQuotations * get rid of range-based approach, collect TailRec-attributed bindings upfront and just traverse these * fold instead of mutate * format * make tests more challenging * do the TailCall checks during the main traversal * WIP: move TailCallChecks into main3 after optimization * format * let TailCallChecks.fs be formatted * bring over support for TyLambda bodies from other branch * adjust expected errors * fix the doubled error messages * fix seq analysis * cleanup * cover some more rec constructs * remove commented code from tests * Rename the type "IsTailCall" to "TailCall" * model boolean as dedicated type "TailCallReturnType" * remove unused members of type "PermitByRefExpr" * remove unused mustTailCallExprs from env * add comment to explain origin of PermitByRefExpr * First stab at support for continuation-passing-style * - refactor approach for CPS support to be much simpler - more CPS tests * one env ought to be enough for everyone * report time for "TailCall Checks" * clean up unused function args * improve some comments and names * add API docs for TailCall attribute * add xml comment for TailCallChecks.CheckImplFile * Update src/FSharp.Core/prim-types.fsi Co-authored-by: Petr <[email protected]> * remove some superfluous stuff from CheckLambdas * More detailed comment * extend test with an inner class type * optimize * update xlf * adjust error messages after xlf update * revert white space changes that sneaked in during rebase --------- Co-authored-by: Petr <[email protected]>
1 parent 5c15a40 commit b4c26d8

29 files changed

+2031
-0
lines changed

src/Compiler/Checking/TailCallChecks.fs

Lines changed: 792 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module internal FSharp.Compiler.TailCallChecks
2+
3+
open FSharp.Compiler
4+
open FSharp.Compiler.TcGlobals
5+
open FSharp.Compiler.TypedTree
6+
7+
/// Perform the TailCall analysis on the optimized TAST for a file.
8+
/// The TAST is traversed analogously to the PostInferenceChecks phase.
9+
/// For functions that are annotated with the [<TailCall>] attribute, a warning is emmitted if they are called in a
10+
/// non-tailrecursive manner in the recursive scope of the function.
11+
/// The ModuleOrNamespaceContents aren't mutated in any way by performing this check.
12+
val CheckImplFile:
13+
g: TcGlobals * amap: Import.ImportMap * reportErrors: bool * implFileContents: ModuleOrNamespaceContents -> unit

src/Compiler/Driver/fsc.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ open FSharp.Compiler.CreateILModule
4040
open FSharp.Compiler.DependencyManager
4141
open FSharp.Compiler.Diagnostics
4242
open FSharp.Compiler.DiagnosticsLogger
43+
open FSharp.Compiler.Features
4344
open FSharp.Compiler.IlxGen
4445
open FSharp.Compiler.InfoReader
4546
open FSharp.Compiler.IO
@@ -878,6 +879,14 @@ let main3
878879

879880
optimizedImpls, EncodeOptimizationData(tcGlobals, tcConfig, outfile, exportRemapping, (generatedCcu, optimizationData), false)
880881

882+
if tcGlobals.langVersion.SupportsFeature LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage then
883+
match optimizedImpls with
884+
| CheckedAssemblyAfterOptimization checkedImplFileAfterOptimizations ->
885+
ReportTime tcConfig ("TailCall Checks")
886+
887+
for f in checkedImplFileAfterOptimizations do
888+
TailCallChecks.CheckImplFile(tcGlobals, tcImports.GetImportMap(), true, f.ImplFile.Contents)
889+
881890
let refAssemblySignatureHash =
882891
match tcConfig.emitMetadataAssembly with
883892
| MetadataAssemblyGeneration.None -> None

src/Compiler/FSComp.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,7 @@ featureExtendedStringInterpolation,"Extended string interpolation similar to C#
15761576
featureWarningWhenMultipleRecdTypeChoice,"Raises warnings when multiple record type matches were found during name resolution because of overlapping field names."
15771577
featureImprovedImpliedArgumentNames,"Improved implied argument names"
15781578
featureStrictIndentation,"Raises errors on incorrect indentation, allows better recovery and analysis during editing"
1579+
featureChkNotTailRecursive,"Raises warnings if a member or function has the 'TailCall' attribute, but is not being used in a tail recursive way."
15791580
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
15801581
3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
15811582
3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
@@ -1700,4 +1701,5 @@ featureInformationalObjInferenceDiagnostic,"Diagnostic 3559 (warn when obj infer
17001701
3566,tcMultipleRecdTypeChoice,"Multiple type matches were found:\n%s\nThe type '%s' was used. Due to the overlapping field names\n%s\nconsider using type annotations or change the order of open statements."
17011702
3567,parsMissingMemberBody,"Expecting member body"
17021703
3568,parsMissingKeyword,"Missing keyword '%s'"
1704+
3569,chkNotTailRecursive,"The member or function '%s' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way."
17031705
3577,tcOverrideUsesMultipleArgumentsInsteadOfTuple,"This override takes a tuple instead of multiple arguments. Try to add an additional layer of parentheses at the method definition (e.g. 'member _.Foo((x, y))'), or remove parentheses at the abstract method declaration (e.g. 'abstract member Foo: 'a * 'b -> 'c')."

src/Compiler/FSharp.Compiler.Service.fsproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@
337337
<Compile Include="Checking\QuotationTranslator.fs" />
338338
<Compile Include="Checking\PostInferenceChecks.fsi" />
339339
<Compile Include="Checking\PostInferenceChecks.fs" />
340+
<Compile Include="Checking\TailCallChecks.fsi" />
341+
<Compile Include="Checking\TailCallChecks.fs" />
340342
<Compile Include="Checking\CheckBasics.fsi" />
341343
<Compile Include="Checking\CheckBasics.fs" />
342344
<Compile Include="Checking\CheckRecordSyntaxHelpers.fsi" />

src/Compiler/Facilities/LanguageFeatures.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type LanguageFeature =
7171
| WarningWhenMultipleRecdTypeChoice
7272
| ImprovedImpliedArgumentNames
7373
| DiagnosticForObjInference
74+
| WarningWhenTailRecAttributeButNonTailRecUsage
7475

7576
/// LanguageVersion management
7677
type LanguageVersion(versionText) =
@@ -165,6 +166,7 @@ type LanguageVersion(versionText) =
165166
LanguageFeature.ImprovedImpliedArgumentNames, previewVersion
166167
LanguageFeature.DiagnosticForObjInference, previewVersion
167168
LanguageFeature.StrictIndentation, previewVersion
169+
LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage, previewVersion
168170

169171
]
170172

@@ -291,6 +293,7 @@ type LanguageVersion(versionText) =
291293
| LanguageFeature.ImprovedImpliedArgumentNames -> FSComp.SR.featureImprovedImpliedArgumentNames ()
292294
| LanguageFeature.DiagnosticForObjInference -> FSComp.SR.featureInformationalObjInferenceDiagnostic ()
293295
| LanguageFeature.StrictIndentation -> FSComp.SR.featureStrictIndentation ()
296+
| LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage -> FSComp.SR.featureChkNotTailRecursive ()
294297

295298
/// Get a version string associated with the given feature.
296299
static member GetFeatureVersionString feature =

src/Compiler/Facilities/LanguageFeatures.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type LanguageFeature =
6161
| WarningWhenMultipleRecdTypeChoice
6262
| ImprovedImpliedArgumentNames
6363
| DiagnosticForObjInference
64+
| WarningWhenTailRecAttributeButNonTailRecUsage
6465

6566
/// LanguageVersion management
6667
type LanguageVersion =

src/Compiler/TypedTree/TcGlobals.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,7 @@ type TcGlobals(
15091509
member val attrib_CompilerFeatureRequiredAttribute = findSysAttrib "System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute"
15101510
member val attrib_SetsRequiredMembersAttribute = findSysAttrib "System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute"
15111511
member val attrib_RequiredMemberAttribute = findSysAttrib "System.Runtime.CompilerServices.RequiredMemberAttribute"
1512+
member val attrib_TailCallAttribute = mk_MFCore_attrib "TailCallAttribute"
15121513

15131514
member g.improveType tcref tinst = improveTy tcref tinst
15141515

src/Compiler/xlf/FSComp.txt.cs.xlf

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Compiler/xlf/FSComp.txt.de.xlf

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)