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 #17447 -MethodAccessException on equality comparison of a record with private #17449

Closed
wants to merge 12 commits into from

Conversation

KevinRansom
Copy link
Member

@KevinRansom KevinRansom commented Jul 26, 2024

Fix #17447 -MethodAccessException on equality comparison of a record with private

There is an issue with code generation when using realsig- (The legacy visibility mechanism) on compiler generated methods that are not overrides. The compiler generates them internal, even though they are created with a visibility of public.

This is a better fix:
Change the codegenerator to generate augments for equals as Final, Overrides, this causes them to go through the same code path as the other code generated Equals operations, this has way fewer side effects and generates the right members.

  • The fix is for compiler generated Equals
  • Added test cases realsig + or -
  • cleaned up Testframework RealInternalSignature handling

@KevinRansom KevinRansom requested a review from a team as a code owner July 26, 2024 05:31
Copy link
Contributor

github-actions bot commented Jul 26, 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.100.md

@@ -8360,7 +8360,9 @@ and ComputeMethodAccessRestrictedBySig eenv vspec =
else
vspec

let isHiddenBySignatureVal = IsHiddenVal eenv.sigToImplRemapInfo vspec
let isHiddenBySignatureVal =
Copy link
Member

Choose a reason for hiding this comment

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

This might intervene with the generated .Is* members properties which are automatically added for DUs.
I am not sure the problem is real, but the combination of your change and the way I remember the .Is* feature rings a bell for me.

Copy link
Member Author

@KevinRansom KevinRansom Jul 27, 2024

Choose a reason for hiding this comment

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

@T-Gro , yes that popped into my mind while working on this too ... however, the fix for that was to make the compilergenerated Is* methods visible to the TypeChecker. Here the fix is to ensure that CompilerGenerated methods are not forced to be emitted internal but instead are emitted with the visibility specified when generated for generated methods without a sigfile definiton.

Equals for these specified type generated equals is different from other generated Equals methods, because they are overrides, where this is just a new method on the type. There is a code path that forces the overriden Equals to public, and then the compiler changes it to the visibility of the overriden method definition.

Copy link
Member Author

Choose a reason for hiding this comment

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

@T-Gro , over the weekend I came up with a much better more targeted fix.

psfinaki
psfinaki previously approved these changes Jul 26, 2024
Copy link
Member

@psfinaki psfinaki left a comment

Choose a reason for hiding this comment

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

Thanks for this Kevin. I fixed baselines, added new baselines, fix formatting and added release notes.

@@ -77,7 +77,7 @@ extends [runtime]System.Object

}

.method assembly specialname static class [runtime]System.Tuple`2<bool,int32> get_patternInput@9() cil managed
.method public specialname static class [runtime]System.Tuple`2<bool,int32> get_patternInput@9() cil managed
Copy link
Member

Choose a reason for hiding this comment

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

@KevinRansom so these guys became public now... I was pondering on this - I don't really have enough picture to evaluate the real world implications since this is quite a special case, but what I feel is that this is either okay or uncovering a different issue which should be addressed separately.

Copy link
Member Author

@KevinRansom KevinRansom Jul 27, 2024

Choose a reason for hiding this comment

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

@psfinaki public is the expected scope, it is not hard to argue that it is incorrect, but the bug is certainly elsewhere.

module OutOptionalTests

// unnecessary code elided here

let (_:bool), (_:int) = Thing.Do(i = 42)
let (_:bool), (_:int) = Thing.Do()

So:
1: bindings on modules default to being public ...
2: The binding is unnamed discards, so the side effect is still necessary.
if you make the bindings look like:

let (_a:bool), (_b:int) = Thing.Do(i = 42)
let (_c:bool), (_d:int) = Thing.Do()

Then compile with --allsigs you get this output:

module OutOptionalTests

// unnecessary code elided here

val _b: int
val _a: bool
val _d: int
val _c: bool

So give them a name and the value is emitted. So ... if it is expected to not be public ... I think it was relying on the side-effect of a bug. Raise an issue suggesting that unnamed bindings should not be public when emitted to il.
And require that it's fixed before we merge this one. I will look at it. It is better as a separate issue, because they are entirely unrelated.

Copy link
Member Author

Choose a reason for hiding this comment

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

@psfinaki - ignore the above over the weekend I revisited this and decided that my earlier approach was a bit too much of a hack. I replaced it with a better more targetted fix.

@KevinRansom KevinRansom marked this pull request as draft July 28, 2024 05:55
@KevinRansom KevinRansom dismissed psfinaki’s stale review July 28, 2024 22:12

I changed the fix. The new one is much more targeted

@KevinRansom
Copy link
Member Author

This was entirely the wrong approach

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

Successfully merging this pull request may close these issues.

MethodAccessException on equality comparison of a record with private fields
3 participants