Skip to content

Commit 09b5991

Browse files
authored
Merge pull request #17469 from dotnet/merges/main-to-release/dev17.12
2 parents db079bb + 0b17830 commit 09b5991

File tree

8 files changed

+263
-65
lines changed

8 files changed

+263
-65
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Compiler hangs when compiling inline recursive invocation ([Issue #17376](https://github.com/dotnet/fsharp/issues/17376), [PR #17394](https://github.com/dotnet/fsharp/pull/17394))
44
* Fix reporting IsFromComputationExpression only for CE builder type constructors and let bindings. ([PR #17375](https://github.com/dotnet/fsharp/pull/17375))
55
* Optimize simple mappings in comprehensions when the body of the mapping has `let`-bindings and/or sequential expressions before a single yield. ([PR #17419](https://github.com/dotnet/fsharp/pull/17419))
6+
* C# protected property can be assigned in F# inherit constructor call. ([Issue #13299](https://github.com/dotnet/fsharp/issues/13299), [PR #17391](https://github.com/dotnet/fsharp/pull/17391))
7+
* MethodAccessException on equality comparison of a record with private fields. ([Issue #17447](https://github.com/dotnet/fsharp/issues/17447), [PR #17391](https://github.com/dotnet/fsharp/pull/17467))
68

79
### Added
810

src/Compiler/Checking/AugmentWithHashCompare.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,7 @@ let MakeValsForEqualsAugmentation g (tcref: TyconRef) =
13331333
g
13341334
tcref
13351335
ty
1336-
vis
1336+
tcref.Accessibility
13371337
(if tcref.Deref.IsFSharpException then
13381338
None
13391339
else
@@ -1376,7 +1376,7 @@ let MakeValsForEqualityWithComparerAugmentation g (tcref: TyconRef) =
13761376
g
13771377
tcref
13781378
ty
1379-
vis
1379+
tcref.Accessibility
13801380
// This doesn't implement any interface.
13811381
None
13821382
"Equals"

src/Compiler/Checking/MethodCalls.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ let MethInfoChecks g amap isInstance tyargsOpt objArgs ad m (minfo: MethInfo) =
12371237
AccessibleFrom(paths, None)
12381238
| _ -> ad
12391239

1240-
if not (IsTypeAndMethInfoAccessible amap m adOriginal ad minfo) then
1240+
if not (minfo.IsProtectedAccessibility && minfo.LogicalName.StartsWithOrdinal("set_")) && not(IsTypeAndMethInfoAccessible amap m adOriginal ad minfo) then
12411241
error (Error (FSComp.SR.tcMethodNotAccessible(minfo.LogicalName), m))
12421242

12431243
if isAnyTupleTy g minfo.ApparentEnclosingType && not minfo.IsExtensionMember &&

src/Compiler/TypedTree/TypedTree.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type ValBaseOrThisInfo =
9090
/// Indicates a normal value
9191
| NormalVal
9292

93-
/// Indicates the 'this' value specified in a memberm e.g. 'x' in 'member x.M() = 1'
93+
/// Indicates the 'this' value specified in a member e.g. 'x' in 'member x.M() = 1'
9494
| MemberThisVal
9595

9696
/// Flags on values

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/Basic/Basic.fs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,42 @@ module AccessibilityAnnotations_Basic =
188188
compilation
189189
|> verifyCompileAndRun
190190
|> shouldSucceed
191+
192+
[<Fact>]
193+
let ``C# protected property can be assigned in a F# inherit constructor call`` () =
194+
195+
let csharp =
196+
CSharp
197+
"""
198+
namespace Consumer
199+
{
200+
public class Foo
201+
{
202+
protected string Value { get; set; } = "";
203+
}
204+
}
205+
"""
206+
|> withName "CSLib"
207+
208+
let fsharp =
209+
FSharp
210+
"""
211+
module Hello
212+
open Consumer
213+
214+
type Bar() =
215+
inherit Foo(Value = "Works")
216+
217+
type Bar2() as this =
218+
inherit Foo()
219+
do this.Value <- "Works"
220+
221+
{ new Foo(Value = "OK") with member x.ToString() = "OK" } |> ignore
222+
"""
223+
|> withLangVersion80
224+
|> withName "FSLib"
225+
|> withReferences [ csharp ]
226+
227+
fsharp
228+
|> compile
229+
|> shouldSucceed

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

Lines changed: 212 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,87 +7,239 @@ open FSharp.Test.Compiler
77

88
module GenericComparisonCrossAssembly =
99

10-
[<Fact>]
11-
let ``fslib``() =
10+
[<InlineData(true)>] // RealSig
11+
[<InlineData(false)>] // Regular
12+
[<Theory>]
13+
let ``fslib``(realsig) =
1214
FSharpWithFileName "Program.fs"
1315
"""
1416
ValueSome (1, 2) = ValueSome (2, 3) |> ignore"""
17+
|> withRealInternalSignature realsig
1518
|> withOptimize
1619
|> compileExeAndRun
1720
|> shouldSucceed
1821
|> verifyIL [ """
19-
.method assembly specialname static void staticInitialization@() cil managed
20-
{
21-
22-
.maxstack 8
23-
IL_0000: ldc.i4.1
24-
IL_0001: ldc.i4.2
25-
IL_0002: newobj instance void class [runtime]System.Tuple`2<int32,int32>::.ctor(!0,
26-
!1)
27-
IL_0007: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<!0> valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>>::NewValueSome(!0)
28-
IL_000c: stsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>> Program::x@1
29-
IL_0011: ldc.i4.2
30-
IL_0012: ldc.i4.3
31-
IL_0013: newobj instance void class [runtime]System.Tuple`2<int32,int32>::.ctor(!0,
32-
!1)
33-
IL_0018: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<!0> valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>>::NewValueSome(!0)
34-
IL_001d: stsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>> Program::y@1
35-
IL_0022: ldsflda valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>> Program::x@1
36-
IL_0027: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>> Program::get_y@1()
3722
IL_002c: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer()
3823
IL_0031: call instance bool valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<class [runtime]System.Tuple`2<int32,int32>>::Equals(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpValueOption`1<!0>,
39-
class [runtime]System.Collections.IEqualityComparer)
40-
IL_0036: stsfld bool Program::arg@1
41-
IL_003b: ret
42-
}
4324
""" ]
4425

45-
[<Fact>]
46-
let ``Another assembly``() =
47-
let module1 =
26+
[<InlineData(true)>] // RealSig
27+
[<InlineData(false)>] // Regular
28+
[<Theory>]
29+
let ``Another Assembly - record with private fields`` (realsig) =
30+
let library =
4831
FSharpWithFileName "Module1.fs"
4932
"""
5033
module Module1
5134
52-
[<Struct>]
53-
type Struct(v: int, u: int) =
54-
member _.V = v
55-
member _.U = u """
35+
type Value =
36+
private { value: uint32 }
37+
38+
static member Zero = { value = 0u }
39+
static member Create(value: int) = { value = uint value } """
40+
|> withRealInternalSignature realsig
5641
|> withOptimize
5742
|> asLibrary
5843
|> withName "module1"
5944

60-
let module2 =
45+
let mainModule =
6146
FSharpWithFileName "Program.fs"
62-
"""
63-
Module1.Struct(1, 2) = Module1.Struct(2, 3) |> ignore"""
47+
$"""
48+
open Module1
49+
Value.Zero = Value.Create 0 |> ignore"""
6450

65-
module2
66-
|> withReferences [module1]
51+
mainModule
52+
|> withRealInternalSignature realsig
53+
|> withReferences [ library ]
54+
|> compileExeAndRun
55+
|> shouldSucceed
56+
57+
[<InlineData(false, "private", "assembly")>] // Legacy, private WrapType, private visibility in IL
58+
[<InlineData(false, "internal", "assembly")>] // RealSig, internal WrapType, assembly visibility in IL
59+
[<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
62+
[<InlineData(true, "public", "public")>] // RealSig, public WrapType, public visibility in IL
63+
[<Theory>]
64+
let ``Generated typed Equals`` (realsig, typeScope, targetVisibility) =
65+
let library =
66+
FSharpWithFileName "Program.fs"
67+
$"""
68+
module Module1 =
69+
70+
[<Struct>]
71+
type {typeScope} Struct(v: int, u: int) =
72+
member _.V = v
73+
member _.U = u"""
74+
75+
library
76+
|> asExe
77+
|> withNoWarn 988
78+
|> withRealInternalSignature realsig
6779
|> withOptimize
80+
|> compile
81+
|> shouldSucceed
82+
|> verifyIL [
83+
$"""
84+
.method {targetVisibility} hidebysig instance bool
85+
Equals(valuetype Program/Module1/Struct obj,
86+
class [runtime]System.Collections.IEqualityComparer comp) cil managed
87+
{{
88+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
89+
90+
.maxstack 8
91+
IL_0000: ldarg.0
92+
IL_0001: ldfld int32 Program/Module1/Struct::v
93+
IL_0006: ldarga.s obj
94+
IL_0008: ldfld int32 Program/Module1/Struct::v
95+
IL_000d: bne.un.s IL_001f
96+
97+
IL_000f: ldarg.0
98+
IL_0010: ldfld int32 Program/Module1/Struct::u
99+
IL_0015: ldarga.s obj
100+
IL_0017: ldfld int32 Program/Module1/Struct::u
101+
IL_001c: ceq
102+
IL_001e: ret
103+
104+
IL_001f: ldc.i4.0
105+
IL_0020: ret
106+
}} """ ]
107+
108+
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
115+
[<Theory>]
116+
let ``Record with various fields`` (realsig, fieldScope) =
117+
118+
let mainModule =
119+
FSharpWithFileName "Program.fs"
120+
$"""
121+
module Module1 =
122+
type Value =
123+
{fieldScope} {{ value: uint32 }}
124+
125+
static member Zero = {{ value = 0u }}
126+
static member Create(value: int) = {{ value = uint value }}
127+
128+
Value.Zero = Value.Create 0 |> ignore
129+
printfn "Hello, World" """
130+
131+
mainModule
132+
|> withRealInternalSignature realsig
68133
|> compileExeAndRun
69134
|> shouldSucceed
70-
|> verifyIL [ """
71-
.method assembly specialname static void staticInitialization@() cil managed
72-
{
73-
74-
.maxstack 8
75-
IL_0000: ldc.i4.1
76-
IL_0001: ldc.i4.2
77-
IL_0002: newobj instance void [module1]Module1/Struct::.ctor(int32,
78-
int32)
79-
IL_0007: stsfld valuetype [module1]Module1/Struct Program::x@1
80-
IL_000c: ldc.i4.2
81-
IL_000d: ldc.i4.3
82-
IL_000e: newobj instance void [module1]Module1/Struct::.ctor(int32,
83-
int32)
84-
IL_0013: stsfld valuetype [module1]Module1/Struct Program::y@1
85-
IL_0018: ldsflda valuetype [module1]Module1/Struct Program::x@1
86-
IL_001d: call valuetype [module1]Module1/Struct Program::get_y@1()
87-
IL_0022: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer()
88-
IL_0027: call instance bool [module1]Module1/Struct::Equals(valuetype [module1]Module1/Struct,
89-
class [runtime]System.Collections.IEqualityComparer)
90-
IL_002c: stsfld bool Program::arg@1
91-
IL_0031: ret
92-
}
93-
""" ]
135+
|> verifyIL [
136+
"""
137+
.method public hidebysig virtual final instance bool Equals(class Program/Module1/Value obj) cil managed
138+
{
139+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
140+
141+
.maxstack 8
142+
IL_0000: ldarg.0
143+
IL_0001: brfalse.s IL_0017
144+
145+
IL_0003: ldarg.1
146+
IL_0004: brfalse.s IL_0015
147+
148+
IL_0006: ldarg.0
149+
IL_0007: ldfld uint32 Program/Module1/Value::value@
150+
IL_000c: ldarg.1
151+
IL_000d: ldfld uint32 Program/Module1/Value::value@
152+
IL_0012: ceq
153+
IL_0014: ret
154+
155+
IL_0015: ldc.i4.0
156+
IL_0016: ret
157+
158+
IL_0017: ldarg.1
159+
IL_0018: ldnull
160+
IL_0019: cgt.un
161+
IL_001b: ldc.i4.0
162+
IL_001c: ceq
163+
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
178+
[<Theory>]
179+
let ``scoped type arg`` (realsig, argScope, targetVisibility) =
180+
let mainModule =
181+
FSharpWithFileName "Program.fs"
182+
$"""
183+
module IPartialEqualityComparer =
184+
open System.Collections.Generic
185+
186+
[<StructuralEquality; NoComparison>]
187+
type {argScope} WrapType<'T> = Wrap of 'T
188+
"""
189+
mainModule
190+
|> asExe
191+
|> withNoWarn 988
192+
|> withRealInternalSignature realsig
193+
|> withOptimize
194+
|> compile
195+
|> shouldSucceed
196+
|> verifyIL [
197+
$"""
198+
.method {targetVisibility} hidebysig instance bool
199+
Equals(class Program/IPartialEqualityComparer/WrapType`1<!T> obj,
200+
class [runtime]System.Collections.IEqualityComparer comp) cil managed
201+
{{
202+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
203+
204+
.maxstack 5
205+
.locals init (class Program/IPartialEqualityComparer/WrapType`1<!T> V_0,
206+
class Program/IPartialEqualityComparer/WrapType`1<!T> V_1,
207+
!T V_2,
208+
!T V_3)
209+
IL_0000: ldarg.0
210+
IL_0001: brfalse.s IL_0027
211+
212+
IL_0003: ldarg.1
213+
IL_0004: brfalse.s IL_0025
214+
215+
IL_0006: ldarg.0
216+
IL_0007: pop
217+
IL_0008: ldarg.0
218+
IL_0009: stloc.0
219+
IL_000a: ldarg.1
220+
IL_000b: stloc.1
221+
IL_000c: ldloc.0
222+
IL_000d: ldfld !0 class Program/IPartialEqualityComparer/WrapType`1<!T>::item
223+
IL_0012: stloc.2
224+
IL_0013: ldloc.1
225+
IL_0014: ldfld !0 class Program/IPartialEqualityComparer/WrapType`1<!T>::item
226+
IL_0019: stloc.3
227+
IL_001a: ldarg.2
228+
IL_001b: ldloc.2
229+
IL_001c: ldloc.3
230+
IL_001d: tail.
231+
IL_001f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/HashCompare::GenericEqualityWithComparerIntrinsic<!T>(class [runtime]System.Collections.IEqualityComparer,
232+
!!0,
233+
!!0)
234+
IL_0024: ret
235+
236+
IL_0025: ldc.i4.0
237+
IL_0026: ret
238+
239+
IL_0027: ldarg.1
240+
IL_0028: ldnull
241+
IL_0029: cgt.un
242+
IL_002b: ldc.i4.0
243+
IL_002c: ceq
244+
IL_002e: ret
245+
}} """ ]

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ module GenericComparison =
8585
|> verifyCompilation
8686

8787

88-
8988
// SOURCE=Hash01.fsx SCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Hash01.dll" # Hash01.fs -
9089
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"Hash01.fsx"|])>]
9190
let ``Hash01_fsx`` compilation =

0 commit comments

Comments
 (0)