Skip to content

Commit d0d6b4e

Browse files
authored
fixes #17541 - Equals visibility for DU's (#17548)
1 parent d3989f7 commit d0d6b4e

File tree

15 files changed

+140
-151
lines changed

15 files changed

+140
-151
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Fix `function` implicit conversion. ([Issue #7401](https://github.com/dotnet/fsharp/issues/7401), [PR #17487](https://github.com/dotnet/fsharp/pull/17487))
99
* Compiler fails to recognise namespace in FQN with enabled GraphBasedChecking. ([Issue #17508](https://github.com/dotnet/fsharp/issues/17508), [PR #17510](https://github.com/dotnet/fsharp/pull/17510))
1010
* Fix missing message for type error (FS0001). ([Issue #17373](https://github.com/dotnet/fsharp/issues/17373), [PR #17516](https://github.com/dotnet/fsharp/pull/17516))
11+
* MethodAccessException on equality comparison of a type private to module. ([Issue #17541](https://github.com/dotnet/fsharp/issues/17541), [PR #17548](https://github.com/dotnet/fsharp/pull/17548))
1112

1213
### Added
1314

src/Compiler/Checking/AugmentWithHashCompare.fs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ let MakeValsForCompareWithComparerAugmentation g (tcref: TyconRef) =
13221322
let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
13231323
let m = tcref.Range
13241324
let _, ty = mkMinimalTy g tcref
1325-
let vis = tcref.TypeReprAccessibility
1325+
let vis = tcref.Accessibility
13261326
let tps = tcref.Typars m
13271327

13281328
let objEqualsVal =
@@ -1333,7 +1333,7 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
13331333
g
13341334
tcref
13351335
ty
1336-
tcref.Accessibility
1336+
vis
13371337
(if tcref.Deref.IsFSharpException then
13381338
None
13391339
else
@@ -1347,16 +1347,13 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
13471347

13481348
let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) =
13491349
let _, ty = mkMinimalTy g tcref
1350-
let vis =
1351-
// Equality method for union types match the union type visibility rather than the TypeReprAccessibility
1352-
if tcref.IsUnionTycon then tcref.Accessibility
1353-
else tcref.TypeReprAccessibility
1350+
let vis = tcref.Accessibility
13541351
let tps = tcref.Typars tcref.Range
13551352

13561353
let objGetHashCodeVal =
13571354
mkValSpec g tcref ty vis (Some(mkGetHashCodeSlotSig g)) "GetHashCode" (tps +-> (mkHashTy g ty)) unitArg false
13581355

1359-
let withcGetHashCodeVal =
1356+
let withGetHashCodeVal =
13601357
mkValSpec
13611358
g
13621359
tcref
@@ -1368,27 +1365,27 @@ let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) =
13681365
unaryArg
13691366
false
13701367

1371-
let withcEqualsVal =
1368+
let withEqualsVal =
13721369
mkValSpec g tcref ty vis (Some(mkIStructuralEquatableEqualsSlotSig g)) "Equals" (tps +-> (mkEqualsWithComparerTy g ty)) tupArg false
13731370

1374-
let withcEqualsValExact =
1371+
let withEqualsExactWithComparer =
1372+
let vis = TAccess (updateSyntaxAccessForCompPath (vis.CompilationPaths) SyntaxAccess.Public)
13751373
mkValSpec
13761374
g
13771375
tcref
13781376
ty
1379-
tcref.Accessibility
1377+
vis
13801378
// This doesn't implement any interface.
13811379
None
13821380
"Equals"
13831381
(tps +-> (mkEqualsWithComparerTyExact g ty))
13841382
tupArg
13851383
false
1386-
13871384
{
13881385
GetHashCode = objGetHashCodeVal
1389-
GetHashCodeWithComparer = withcGetHashCodeVal
1390-
EqualsWithComparer = withcEqualsVal
1391-
EqualsExactWithComparer = withcEqualsValExact
1386+
GetHashCodeWithComparer = withGetHashCodeVal
1387+
EqualsWithComparer = withEqualsVal
1388+
EqualsExactWithComparer = withEqualsExactWithComparer
13921389
}
13931390

13941391
let MakeBindingsForCompareAugmentation g (tycon: Tycon) =

tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,7 @@ let main _ =
769769
|> shouldSucceed
770770
|> verifyIL [
771771
"""
772-
.method public specialname static class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>
773-
'|IsEqual|IsNonEqual|'<(class [Potato]Potato.Lib/IPotato`1<!!T>) T>(!!T x,
774-
!!T y) cil managed
772+
.method public specialname static class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> '|IsEqual|IsNonEqual|'<(class [Potato]Potato.Lib/IPotato`1<!!T>) T>(!!T x, !!T y) cil managed
775773
{
776774
777775
.maxstack 8

tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionStructTypes.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,8 +871,7 @@ let main args =
871871
IL_0002: newobj instance void Foo/StructUnion::.ctor(int32)
872872
IL_0007: ret
873873
}""";(*This is a 'maker method' New{CaseName} used for cases which do have fields associated with them, + the _tag gets initialized*)"""
874-
NewCase3(string _field1_3,
875-
string _field2_3) cil managed
874+
NewCase3(string _field1_3, string _field2_3) cil managed
876875
{
877876
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
878877
int32) = ( 01 00 08 00 00 00 02 00 00 00 00 00 )

tests/FSharp.Compiler.ComponentTests/EmittedIL/ByRefTests.fs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,7 @@ type C() =
283283
.get instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute) Test/C::get_X()
284284
}"""
285285

286-
let verifyMethod = """.method public hidebysig specialname
287-
instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute)
288-
get_X() cil managed
286+
let verifyMethod = """.method public hidebysig specialname instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute) get_X() cil managed
289287
{
290288
.param [0]
291289
.custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 )"""
@@ -313,9 +311,7 @@ type C() =
313311
.get instance int32& modreq([netstandard]System.Runtime.InteropServices.InAttribute) Test/C::get_X()
314312
}"""
315313

316-
let verifyMethod = """.method public hidebysig specialname
317-
instance int32& modreq([netstandard]System.Runtime.InteropServices.InAttribute)
318-
get_X() cil managed
314+
let verifyMethod = """.method public hidebysig specialname instance int32& modreq([netstandard]System.Runtime.InteropServices.InAttribute) get_X() cil managed
319315
{
320316
.param [0]
321317
.custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 )"""
@@ -452,9 +448,7 @@ type C<'T>() =
452448
abstract X<'U> : unit -> inref<'U>
453449
"""
454450

455-
let verifyMethod = """.method public hidebysig abstract virtual
456-
instance !!U& modreq([runtime]System.Runtime.InteropServices.InAttribute)
457-
X<U>() cil managed
451+
let verifyMethod = """.method public hidebysig abstract virtual instance !!U& modreq([runtime]System.Runtime.InteropServices.InAttribute) X<U>() cil managed
458452
{
459453
.param [0]
460454
.custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 )"""
@@ -481,9 +475,7 @@ type C =
481475
.get instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute) Test/C::get_X()
482476
}"""
483477

484-
let verifyMethod = """.method public hidebysig specialname abstract virtual
485-
instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute)
486-
get_X() cil managed
478+
let verifyMethod = """.method public hidebysig specialname abstract virtual instance int32& modreq([runtime]System.Runtime.InteropServices.InAttribute) get_X() cil managed
487479
{
488480
.param [0]
489481
.custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 )"""

tests/FSharp.Compiler.ComponentTests/EmittedIL/CCtorDUWithMember/CCtorDUWithMember.fs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,59 @@ type ILArrayShape =
144144
]
145145
|> shouldSucceed
146146

147+
[<InlineData(true, "public")>] // RealSig
148+
[<InlineData(false, "assembly")>] // Regular
149+
[<Theory>]
150+
let ``private DU in module`` (realSig, expected) =
151+
FSharp """
152+
module RealInternalSignature
153+
module Module =
154+
type private DU = ABC | YYZ
155+
156+
let publicFunction () : bool =
157+
ABC = YYZ
158+
159+
Module.publicFunction () |> printfn "%b"
160+
"""
161+
|> asExe
162+
|> withRealInternalSignature realSig
163+
|> compileAndRun
164+
|> withILContains [
165+
$$"""
166+
.method {{expected}} hidebysig instance bool Equals(class RealInternalSignature/Module/DU obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
167+
{
168+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
169+
170+
.maxstack 4
171+
.locals init (int32 V_0,
172+
int32 V_1)
173+
IL_0000: ldarg.0
174+
IL_0001: brfalse.s IL_001b
175+
176+
IL_0003: ldarg.1
177+
IL_0004: brfalse.s IL_0019
178+
179+
IL_0006: ldarg.0
180+
IL_0007: ldfld int32 RealInternalSignature/Module/DU::_tag
181+
IL_000c: stloc.0
182+
IL_000d: ldarg.1
183+
IL_000e: ldfld int32 RealInternalSignature/Module/DU::_tag
184+
IL_0013: stloc.1
185+
IL_0014: ldloc.0
186+
IL_0015: ldloc.1
187+
IL_0016: ceq
188+
IL_0018: ret
189+
190+
IL_0019: ldc.i4.0
191+
IL_001a: ret
192+
193+
IL_001b: ldarg.1
194+
IL_001c: ldnull
195+
IL_001d: cgt.un
196+
IL_001f: ldc.i4.0
197+
IL_0020: ceq
198+
IL_0022: ret
199+
}
200+
"""
201+
]
202+
|> shouldSucceed

tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/CrossAssembly.fs

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ Value.Zero = Value.Create 0 |> ignore"""
5454
|> compileExeAndRun
5555
|> shouldSucceed
5656

57-
[<InlineData(false, "private", "assembly")>] // Legacy, private WrapType, private visibility in IL
57+
[<InlineData(false, "private", "assembly")>] // Legacy, private WrapType, assembly visibility in IL
5858
[<InlineData(false, "internal", "assembly")>] // RealSig, internal WrapType, assembly visibility in IL
5959
[<InlineData(false, "public", "public")>] // Legacy, public WrapType, public visibility in IL
60-
[<InlineData(true, "private", "private")>] // RealSig, private WrapType, private visibility in IL
61-
[<InlineData(true, "internal", "assembly")>] // RealSig, internal WrapType, assembly visibility in IL
60+
[<InlineData(true, "private", "public")>] // RealSig, private WrapType, public visibility in IL
61+
[<InlineData(true, "internal", "public")>] // RealSig, internal WrapType, public visibility in IL
6262
[<InlineData(true, "public", "public")>] // RealSig, public WrapType, public visibility in IL
6363
[<Theory>]
6464
let ``Generated typed Equals`` (realsig, typeScope, targetVisibility) =
@@ -81,9 +81,7 @@ module Module1 =
8181
|> shouldSucceed
8282
|> verifyIL [
8383
$"""
84-
.method {targetVisibility} hidebysig instance bool
85-
Equals(valuetype Program/Module1/Struct obj,
86-
class [runtime]System.Collections.IEqualityComparer comp) cil managed
84+
.method {targetVisibility} hidebysig instance bool Equals(valuetype Program/Module1/Struct obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
8785
{{
8886
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
8987
@@ -106,24 +104,24 @@ module Module1 =
106104
}} """ ]
107105

108106

109-
[<InlineData(false, "private")>] // Legacy, private record fields, private visibility in IL
110-
[<InlineData(false, "internal")>] // RealSig, internal record fields, assembly visibility in IL
111-
[<InlineData(false, "public")>] // Legacy, public record fields, public visibility in IL
112-
[<InlineData(true, "private")>] // RealSig, private record fields, private visibility in IL
113-
[<InlineData(true, "internal")>] // RealSig, internal record fields, assembly visibility in IL
114-
[<InlineData(true, "public")>] // RealSig, public record fields, public visibility in IL
107+
[<InlineData(false, "private")>] // Legacy, private WrapType
108+
[<InlineData(false, "internal")>] // RealSig, internal WrapType
109+
[<InlineData(false, "public")>] // Legacy, public WrapType
110+
[<InlineData(true, "private")>] // RealSig, private WrapType
111+
[<InlineData(true, "internal")>] // RealSig, internal WrapType
112+
[<InlineData(true, "public")>] // RealSig, public WrapType
115113
[<Theory>]
116-
let ``Record with various fields`` (realsig, fieldScope) =
114+
let ``Record with various scoped fields`` (realsig, fieldScope) =
117115

118116
let mainModule =
119117
FSharpWithFileName "Program.fs"
120-
$"""
118+
$$"""
121119
module Module1 =
122120
type Value =
123-
{fieldScope} {{ value: uint32 }}
121+
{{fieldScope}} { value: uint32 }
124122
125-
static member Zero = {{ value = 0u }}
126-
static member Create(value: int) = {{ value = uint value }}
123+
static member Zero = { value = 0u }
124+
static member Create(value: int) = { value = uint value }
127125
128126
Value.Zero = Value.Create 0 |> ignore
129127
printfn "Hello, World" """
@@ -134,7 +132,7 @@ module Module1 =
134132
|> shouldSucceed
135133
|> verifyIL [
136134
"""
137-
.method public hidebysig virtual final instance bool Equals(class Program/Module1/Value obj) cil managed
135+
.method public hidebysig instance bool Equals(class Program/Module1/Value obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
138136
{
139137
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
140138
@@ -161,26 +159,27 @@ module Module1 =
161159
IL_001b: ldc.i4.0
162160
IL_001c: ceq
163161
IL_001e: ret
164-
} """
165-
"""
166-
IL_0020: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer()
167-
IL_0025: callvirt instance bool Program/Module1/Value::Equals(class Program/Module1/Value,
168-
class [runtime]System.Collections.IEqualityComparer)
169-
""" ]
170-
171-
172-
[<InlineData(false, "private", "assembly")>] // Legacy, private WrapType, private visibility in IL
173-
[<InlineData(false, "internal", "assembly")>] // RealSig, internal WrapType, assembly visibility in IL
174-
[<InlineData(false, "public", "public")>] // Legacy, public WrapType, public visibility in IL
175-
[<InlineData(true, "private", "private")>] // RealSig, private WrapType, private visibility in IL
176-
[<InlineData(true, "internal", "assembly")>] // RealSig, internal WrapType, assembly visibility in IL
177-
[<InlineData(true, "public", "public")>] // RealSig, public WrapType, public visibility in IL
162+
} """ ]
163+
164+
165+
[<InlineData(false, "public", "private", "assembly")>] // public module - Legacy, private WrapType, private visibility in IL
166+
[<InlineData(false, "public", "internal", "assembly")>] // public module - RealSig, internal WrapType, assembly visibility in IL
167+
[<InlineData(false, "public", "public", "public")>] // public module - Legacy, public WrapType, public visibility in IL
168+
[<InlineData(true, "public", "private", "public")>] // public module - RealSig, private WrapType, public visibility in IL
169+
[<InlineData(true, "public", "internal", "public")>] // public module - RealSig, internal WrapType, public visibility in IL
170+
[<InlineData(true, "public", "public", "public")>] // public module - RealSig, public WrapType, public visibility in IL
171+
[<InlineData(false, "private", "private", "assembly")>] // private module - Legacy, private WrapType, private visibility in IL
172+
[<InlineData(false, "private", "internal", "assembly")>] // private module - RealSig, internal WrapType, assembly visibility in IL
173+
[<InlineData(false, "private", "public", "assembly")>] // private module - Legacy, public WrapType, assembly visibility in IL
174+
[<InlineData(true, "private", "private", "public")>] // private module - RealSig, private WrapType, public visibility in IL
175+
[<InlineData(true, "private", "internal", "public")>] // private module - RealSig, internal WrapType, public visibility in IL
176+
[<InlineData(true, "private", "public", "public")>] // private module - RealSig, public WrapType, public visibility in IL
178177
[<Theory>]
179-
let ``scoped type arg`` (realsig, argScope, targetVisibility) =
178+
let ``scoped main and scoped type Equals`` (realsig, moduleScope, argScope, targetVisibility) =
180179
let mainModule =
181180
FSharpWithFileName "Program.fs"
182181
$"""
183-
module IPartialEqualityComparer =
182+
module {moduleScope} IPartialEqualityComparer =
184183
open System.Collections.Generic
185184
186185
[<StructuralEquality; NoComparison>]
@@ -195,9 +194,7 @@ module IPartialEqualityComparer =
195194
|> shouldSucceed
196195
|> verifyIL [
197196
$"""
198-
.method {targetVisibility} hidebysig instance bool
199-
Equals(class Program/IPartialEqualityComparer/WrapType`1<!T> obj,
200-
class [runtime]System.Collections.IEqualityComparer comp) cil managed
197+
.method {targetVisibility} hidebysig instance bool Equals(class Program/IPartialEqualityComparer/WrapType`1<!T> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
201198
{{
202199
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
203200

tests/FSharp.Compiler.ComponentTests/EmittedIL/GenericComparison/Equals16.fsx.il.net472.bsl

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,7 @@
128128
IL_000c: ret
129129
}
130130

131-
.method public hidebysig virtual final
132-
instance int32 CompareTo(object obj,
133-
class [runtime]System.Collections.IComparer comp) cil managed
131+
.method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed
134132
{
135133
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
136134

@@ -235,9 +233,7 @@
235233
IL_000b: ret
236234
}
237235

238-
.method assembly hidebysig instance bool
239-
Equals(valuetype assembly/EqualsMicroPerfAndCodeGenerationTests/SomeStruct obj,
240-
class [runtime]System.Collections.IEqualityComparer comp) cil managed
236+
.method public hidebysig instance bool Equals(valuetype assembly/EqualsMicroPerfAndCodeGenerationTests/SomeStruct obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
241237
{
242238
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
243239

@@ -259,9 +255,7 @@
259255
IL_0020: ret
260256
}
261257

262-
.method public hidebysig virtual final
263-
instance bool Equals(object obj,
264-
class [runtime]System.Collections.IEqualityComparer comp) cil managed
258+
.method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed
265259
{
266260
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
267261

@@ -285,9 +279,7 @@
285279
IL_0019: ret
286280
}
287281

288-
.method public specialname rtspecialname
289-
instance void .ctor(int32 v,
290-
int32 u) cil managed
282+
.method public specialname rtspecialname instance void .ctor(int32 v, int32 u) cil managed
291283
{
292284

293285
.maxstack 8

0 commit comments

Comments
 (0)