Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #17797 -- Realsig+ generates nested closures with incorrect Generic arguments #17877

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

KevinRansom
Copy link
Member

@KevinRansom KevinRansom commented Oct 13, 2024

When realsig+ is specified we generate closures as nested classes rather than classes at the same level as the class that the closures are for. This eliminates the need for members of the class to be internal allowing us to make the members private to reflect their source visibility.

Issue 17797 occurs because the closures were generated without the generic parameters. This fix addresses that by getting the generic parameters from the argument/typar environment.

@KevinRansom KevinRansom requested a review from a team as a code owner October 13, 2024 04:04
@KevinRansom KevinRansom marked this pull request as draft October 13, 2024 04:04
Copy link
Contributor

github-actions bot commented Oct 13, 2024

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/9.0.200.md

@KevinRansom KevinRansom force-pushed the fix17797 branch 4 times, most recently from 35a8aad to a7eeda8 Compare October 20, 2024 01:44
@KevinRansom KevinRansom force-pushed the fix17797 branch 5 times, most recently from bb06ffa to 1d562ef Compare November 8, 2024 20:58
@KevinRansom KevinRansom force-pushed the fix17797 branch 8 times, most recently from e13abad to ef80877 Compare November 20, 2024 01:49
@KevinRansom KevinRansom changed the title WIP : Attempt to fix #17797 Fix #17797 -- Realsig+ generates nested closures with incorrect Generic arguments Nov 20, 2024
@KevinRansom KevinRansom marked this pull request as ready for review November 20, 2024 05:20
[<InlineData(false, false)>] // Regular NoOptimize
[<Theory>]
let ``BigTuples`` (realSig, optimize) =
let withOptimization compilation =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block is repeated across tests, can be moved on top of the file:

|> withRealSig realSig |> withOptimize optimize

else compilation |> withNoOptimize

FSharp """
namespace Internal.Utilities.Collections
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code snippet is in my opinion big enough to justify living in its own file instead of being in an inline string.

IL_0012: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::Invoke(!0)
IL_0017: ret
IL_0008: ldnull
IL_0009: call int32 Match01/Test1::CompareTo$cont@4(class Match01/Test1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this diff is THE thing we have wanted to address in the dotnet/performance regression with structs, right?
i.e. calling a function directly as opposed to going via new closure allocation+invocation.

.maxstack 4
.locals init (class Match01/Test1 V_0,
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32> V_1)
.maxstack 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the amount of locals below, is the .maxstack 5 correct here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, you do plan do run ilverify and it will complain if there is any point in time for the program where it would needed more.

(just remembering we do reuse locals of same type, so I assume there must be some point in execution where more things are stacked)

@@ -1104,7 +1104,7 @@ type Generic1InGeneric1<'T>() =
extends [runtime]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
.class auto autochar sealed nested assembly beforefieldinit specialname clo@7<A>
.class auto autochar sealed nested assembly beforefieldinit specialname clo@7<T,A>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is closure heavy, can we have it ilverified too?

Comment on lines +38 to +43
Fsx """// #Regression #Conformance #LexicalAnalysis #Operators
// Regression test for FSHARP1.0:4805
// We are not really after the actual error messages here (some of them have been omitted), rather we
// want to verify we do not crash!
//<Expects status="warning" id="FS0064">This construct causes code to be less generic than indicated by the type annotations\. The type variable 'S has been constrained to be type 'int'</Expects>
//<Expects status="error" id="FS0670">This code is not sufficiently generic\. The type variable \^T when \^T : \(static member \( \+ \) : \^T \* \^T -> \^a\) could not be generalized because it would escape its scope</Expects>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fsx """// #Regression #Conformance #LexicalAnalysis #Operators
// Regression test for FSHARP1.0:4805
// We are not really after the actual error messages here (some of them have been omitted), rather we
// want to verify we do not crash!
//<Expects status="warning" id="FS0064">This construct causes code to be less generic than indicated by the type annotations\. The type variable 'S has been constrained to be type 'int'</Expects>
//<Expects status="error" id="FS0670">This code is not sufficiently generic\. The type variable \^T when \^T : \(static member \( \+ \) : \^T \* \^T -> \^a\) could not be generalized because it would escape its scope</Expects>
Fsx """

@@ -17,59 +18,59 @@ module ComputedCollections =
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"Int32RangeArrays.fs"|])>]
let ``Int32RangeArrays_fs`` compilation =
compilation
|> verifyCompilation
|> verifyCompilation false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am okay with this PR not turning realSig's default to true yet.

But when we do, I think we should be running as much tests as possible with the same default.
Will it be a painful update, or was there another reason for using "false" here?

@T-Gro
Copy link
Member

T-Gro commented Nov 26, 2024

My review is finished, but let's wait for the ilverify for realsig as a CI step as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: New
Development

Successfully merging this pull request may close these issues.

2 participants