Skip to content

Commit c777f60

Browse files
T-GroCopilot
andcommitted
Add regression tests for 4 previously-fixed codegen issues
Add 11 regression tests covering 4 codegen issues that are already fixed on main but lacked test coverage. - #13100: --platform:x64 no longer sets Bit32Machine PE flag - #12460: InternalName and ProductVersion now populated in version info - #11935: unmanaged constraint emits modreq + IsUnmanagedAttribute for C# interop - #7861: Assembly references emitted for types used only in attributes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 019588e commit c777f60

2 files changed

Lines changed: 289 additions & 0 deletions

File tree

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespace EmittedIL
4+
5+
open Xunit
6+
open FSharp.Test
7+
open FSharp.Test.Compiler
8+
open FSharp.Test.Utilities
9+
10+
module CodeGenRegressions_Observations =
11+
// https://github.com/dotnet/fsharp/issues/13100
12+
[<Fact>]
13+
let ``Issue_13100_PlatformCharacteristic`` () =
14+
let source = """
15+
module PlatformTest
16+
17+
[<EntryPoint>]
18+
let main _ = 0
19+
"""
20+
FSharp source
21+
|> asExe
22+
|> withPlatform ExecutionPlatform.X64
23+
|> compile
24+
|> shouldSucceed
25+
|> withPeReader (fun rdr ->
26+
let characteristics = rdr.PEHeaders.CoffHeader.Characteristics
27+
if not (characteristics.HasFlag(System.Reflection.PortableExecutable.Characteristics.LargeAddressAware)) then
28+
failwith $"x64 binary should have LargeAddressAware flag. Found: {characteristics}"
29+
if characteristics.HasFlag(System.Reflection.PortableExecutable.Characteristics.Bit32Machine) then
30+
failwith $"x64 binary should NOT have Bit32Machine flag. Found: {characteristics}")
31+
|> ignore
32+
33+
34+
// https://github.com/dotnet/fsharp/issues/12460
35+
[<Fact>]
36+
let ``Issue_12460_VersionInfoDifference`` () =
37+
let source = """
38+
module VersionInfoTest
39+
40+
open System.Reflection
41+
42+
[<assembly: AssemblyFileVersion("1.2.3.4")>]
43+
[<assembly: AssemblyInformationalVersion("5.6.7")>]
44+
do ()
45+
46+
let value = 42
47+
"""
48+
FSharp source
49+
|> asLibrary
50+
|> withName "VersionInfoTest"
51+
|> compile
52+
|> shouldSucceed
53+
|> fun result ->
54+
match result with
55+
| CompilationResult.Success s ->
56+
match s.OutputPath with
57+
| Some path ->
58+
let fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(path)
59+
if System.String.IsNullOrEmpty(fvi.InternalName) then
60+
failwith $"InternalName should not be empty. Expected filename, got: '{fvi.InternalName}'"
61+
if fvi.ProductVersion <> "5.6.7" then
62+
failwith $"ProductVersion should be '5.6.7' (from AssemblyInformationalVersion), got: '{fvi.ProductVersion}'"
63+
if fvi.FileVersion <> "1.2.3.4" then
64+
failwith $"FileVersion should be '1.2.3.4', got: '{fvi.FileVersion}'"
65+
result
66+
| None -> failwith "Output path not found"
67+
| _ -> failwith "Compilation failed"
68+
|> ignore
69+
70+
71+
[<Fact>]
72+
let ``Issue_12460_VersionInfoFallback`` () =
73+
let source = """
74+
module VersionInfoFallbackTest
75+
76+
open System.Reflection
77+
78+
[<assembly: AssemblyFileVersion("2.3.4.5")>]
79+
do ()
80+
81+
let value = 42
82+
"""
83+
FSharp source
84+
|> asLibrary
85+
|> withName "VersionInfoFallbackTest"
86+
|> compile
87+
|> shouldSucceed
88+
|> fun result ->
89+
match result with
90+
| CompilationResult.Success s ->
91+
match s.OutputPath with
92+
| Some path ->
93+
let fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(path)
94+
if System.String.IsNullOrEmpty(fvi.InternalName) then
95+
failwith $"InternalName should not be empty, got: '{fvi.InternalName}'"
96+
if fvi.FileVersion <> "2.3.4.5" then
97+
failwith $"FileVersion should be '2.3.4.5', got: '{fvi.FileVersion}'"
98+
if System.String.IsNullOrEmpty(fvi.OriginalFilename) then
99+
failwith $"OriginalFilename should not be empty, got: '{fvi.OriginalFilename}'"
100+
result
101+
| None -> failwith "Output path not found"
102+
| _ -> failwith "Compilation failed"
103+
|> ignore
104+
105+
106+
// https://github.com/dotnet/fsharp/issues/11935
107+
[<Fact>]
108+
let ``Issue_11935_UnmanagedConstraintInterop`` () =
109+
let source = """
110+
module Test
111+
112+
let test<'T when 'T : unmanaged> (x: 'T) = x
113+
"""
114+
FSharp source
115+
|> asLibrary
116+
|> withLangVersion10
117+
|> compile
118+
|> shouldSucceed
119+
|> verifyIL ["""
120+
.method public static !!T test<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>(!!T x) cil managed
121+
{
122+
.param type T
123+
.custom instance void [runtime]System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 )
124+
125+
.maxstack 8
126+
IL_0000: ldarg.0
127+
IL_0001: ret
128+
}"""]
129+
130+
131+
[<Fact>]
132+
let ``Issue_11935_UnmanagedConstraintInterop_ClassType`` () =
133+
let source = """
134+
module Test
135+
136+
type Container<'T when 'T : unmanaged>() =
137+
member _.GetDefault() : 'T = Unchecked.defaultof<'T>
138+
"""
139+
FSharp source
140+
|> asLibrary
141+
|> withLangVersion10
142+
|> compile
143+
|> shouldSucceed
144+
|> verifyILContains [
145+
"Container`1<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>"
146+
".custom instance void [runtime]System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 )"
147+
]
148+
|> shouldSucceed
149+
150+
151+
[<Fact>]
152+
let ``Issue_11935_UnmanagedConstraintInterop_StructType`` () =
153+
let source = """
154+
module Test
155+
156+
[<Struct>]
157+
type StructContainer<'T when 'T : unmanaged> =
158+
val Value : 'T
159+
new(v) = { Value = v }
160+
"""
161+
FSharp source
162+
|> asLibrary
163+
|> withLangVersion10
164+
|> compile
165+
|> shouldSucceed
166+
|> verifyILContains [
167+
"StructContainer`1<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>"
168+
".custom instance void [runtime]System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 )"
169+
]
170+
|> shouldSucceed
171+
172+
173+
[<Fact>]
174+
let ``Issue_11935_UnmanagedConstraintInterop_InstanceMethod`` () =
175+
let source = """
176+
module Test
177+
178+
type Processor() =
179+
member _.Process<'T when 'T : unmanaged>(x: 'T) = x
180+
"""
181+
FSharp source
182+
|> asLibrary
183+
|> withLangVersion10
184+
|> compile
185+
|> shouldSucceed
186+
|> verifyIL ["""
187+
.method public hidebysig instance !!T
188+
Process<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>(!!T x) cil managed
189+
{
190+
.param type T
191+
.custom instance void [runtime]System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 )
192+
193+
.maxstack 8
194+
IL_0000: ldarg.1
195+
IL_0001: ret
196+
}"""]
197+
198+
199+
[<Fact>]
200+
let ``Issue_11935_UnmanagedConstraintInterop_MultipleTypeParams`` () =
201+
let source = """
202+
module Test
203+
204+
let combine<'T, 'U when 'T : unmanaged and 'U : unmanaged> (x: 'T) (y: 'U) = struct(x, y)
205+
"""
206+
FSharp source
207+
|> asLibrary
208+
|> withLangVersion10
209+
|> compile
210+
|> shouldSucceed
211+
|> verifyILContains [
212+
"combine<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T,valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) U>(!!T x, !!U y) cil managed"
213+
]
214+
|> shouldSucceed
215+
216+
217+
// https://github.com/dotnet/fsharp/issues/7861
218+
[<Fact>]
219+
let ``Issue_7861_AttributeTypeReference`` () =
220+
let source = """
221+
module Test
222+
223+
open System
224+
225+
type TypedAttribute(t: Type) =
226+
inherit Attribute()
227+
member _.TargetType = t
228+
229+
[<Typed(typeof<System.Xml.XmlDocument>)>]
230+
type MyClass() = class end
231+
"""
232+
FSharp source
233+
|> asLibrary
234+
|> compile
235+
|> shouldSucceed
236+
|> verifyILContains [
237+
".assembly extern System.Xml.ReaderWriter"
238+
]
239+
|> shouldSucceed
240+
241+
242+
[<Fact>]
243+
let ``Issue_7861_NamedAttributeArgument`` () =
244+
let source = """
245+
module Test
246+
247+
open System
248+
249+
type TypePropertyAttribute() =
250+
inherit Attribute()
251+
member val TargetType : Type = null with get, set
252+
253+
[<TypeProperty(TargetType = typeof<System.Xml.XmlDocument>)>]
254+
type MyClass() = class end
255+
"""
256+
FSharp source
257+
|> asLibrary
258+
|> compile
259+
|> shouldSucceed
260+
|> verifyILContains [
261+
".assembly extern System.Xml.ReaderWriter"
262+
]
263+
|> shouldSucceed
264+
265+
266+
[<Fact>]
267+
let ``Issue_7861_AttributeOnMethod`` () =
268+
let source = """
269+
module Test
270+
271+
open System
272+
273+
type TypedAttribute(t: Type) =
274+
inherit Attribute()
275+
member _.TargetType = t
276+
277+
type MyClass() =
278+
[<Typed(typeof<System.Xml.XmlDocument>)>]
279+
member _.MyMethod() = ()
280+
"""
281+
FSharp source
282+
|> asLibrary
283+
|> compile
284+
|> shouldSucceed
285+
|> verifyILContains [
286+
".assembly extern System.Xml.ReaderWriter"
287+
]
288+
|> shouldSucceed

tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
<Compile Include="EmittedIL\TryCatch\TryCatch.fs" />
196196
<Compile Include="EmittedIL\Nullness\NullnessMetadata.fs" />
197197
<Compile Include="EmittedIL\FixedBindings\FixedBindings.fs" />
198+
<Compile Include="EmittedIL\CodeGenRegressions\CodeGenRegressions_Observations.fs" />
198199
<Compile Include="ErrorMessages\TypedInterpolatedStringsTests.fs" />
199200
<!--<Compile Include="EmittedIL\StructDefensiveCopy\StructDefensiveCopy.fs" />-->
200201
<Compile Include="ErrorMessages\UnsupportedAttributes.fs" />

0 commit comments

Comments
 (0)