Skip to content

Commit a530e0f

Browse files
T-GroCopilot
andcommitted
Improve #12796 tests: TDD with compileAndRun, ILVerify, and runtime reflection
- Rewrite tests to use compileExeAndRun pipeline: compile, shouldSucceed, verifyPEFileWithSystemDlls, run, verify stdout - Each test compiles an exe that reads the attribute value via reflection at runtime and verifies the array length is 0 - Add ILVerify step (verifyPEFileWithSystemDlls) to validate IL metadata - Fix decodeCustomAttrElemType to handle 0x51 (SERIALIZATION_TYPE_TAGGED_OBJECT) for object[] array element types in custom attribute blobs (ECMA-335 II.23.3) - Add open FSharp.Test for ILVerifierModule access Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a8d77f7 commit a530e0f

2 files changed

Lines changed: 62 additions & 13 deletions

File tree

src/Compiler/AbstractIL/il.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4978,6 +4978,7 @@ let rec decodeCustomAttrElemType bytes sigptr x =
49784978
let elemTy, sigptr = decodeCustomAttrElemType bytes sigptr et
49794979
mkILArr1DTy elemTy, sigptr
49804980
| x when x = 0x50uy -> PrimaryAssemblyILGlobals.typ_Type, sigptr
4981+
| x when x = 0x51uy -> PrimaryAssemblyILGlobals.typ_Object, sigptr // SERIALIZATION_TYPE_TAGGED_OBJECT (ECMA-335 II.23.3)
49814982
| _ -> failwithf "decodeCustomAttrElemType ilg: unrecognized custom element type: %A" x
49824983

49834984
/// Given a custom attribute element, encode it to a binary representation according to the rules in Ecma 335 Partition II.

tests/FSharp.Compiler.ComponentTests/Language/AttributeCheckingTests.fs

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Language
44

55
open Xunit
6+
open FSharp.Test
67
open FSharp.Test.Compiler
78

89
module AttributeCheckingTests =
@@ -194,47 +195,94 @@ type C() = class end
194195
// The element type is substituted with System.Object since no elements need encoding.
195196
// Previously this caused FS0192 internal error in encodeCustomAttrElemType.
196197
[<Fact>]
197-
let ``Issue 12796 - DefaultValue empty array on record field of array type should not cause internal error`` () =
198+
let ``Issue 12796 - Empty array of user-defined type in attribute compiles runs and verifies IL`` () =
198199
FSharp
199200
"""
200201
module TestModule
201202
203+
open System
202204
open System.ComponentModel
205+
open System.Reflection
203206
204207
type A = { AField: string }
205-
type B = { [<DefaultValue([||] : A[])>] BField: A[] }
208+
209+
[<DefaultValue([||] : A[])>]
210+
type B() = class end
211+
212+
[<EntryPoint>]
213+
let main _ =
214+
let attr = typeof<B>.GetCustomAttribute<DefaultValueAttribute>()
215+
let arr = attr.Value :?> obj[]
216+
printfn "len=%d" arr.Length
217+
0
206218
"""
207-
|> asLibrary
219+
|> asExe
208220
|> compile
209221
|> shouldSucceed
222+
|> verifyPEFileWithSystemDlls
223+
|> shouldSucceed
224+
|> run
225+
|> shouldSucceed
226+
|> withStdOutContains "len=0"
210227

211228
// https://github.com/dotnet/fsharp/issues/12796
212229
[<Fact>]
213-
let ``Issue 12796 - Empty array of enum type in attribute should succeed`` () =
230+
let ``Issue 12796 - Empty array of enum type in attribute compiles runs and verifies IL`` () =
214231
FSharp
215232
"""
216233
module TestModule
217234
235+
open System
236+
open System.ComponentModel
237+
open System.Reflection
238+
218239
type MyEnum = A = 0 | B = 1
219-
type MyAttr(v: obj) = inherit System.Attribute()
220-
type T = { [<MyAttr([||] : MyEnum[])>] F: int }
240+
241+
[<DefaultValue([||] : MyEnum[])>]
242+
type T() = class end
243+
244+
[<EntryPoint>]
245+
let main _ =
246+
let attr = typeof<T>.GetCustomAttribute<DefaultValueAttribute>()
247+
let arr = attr.Value :?> MyEnum[]
248+
printfn "len=%d" arr.Length
249+
0
221250
"""
222-
|> asLibrary
251+
|> asExe
223252
|> compile
224253
|> shouldSucceed
254+
|> verifyPEFileWithSystemDlls
255+
|> shouldSucceed
256+
|> run
257+
|> shouldSucceed
258+
|> withStdOutContains "len=0"
225259

226260
// https://github.com/dotnet/fsharp/issues/12796
227261
[<Fact>]
228-
let ``Issue 12796 - Empty array of primitive type in attribute should succeed`` () =
262+
let ``Issue 12796 - Empty array of primitive type in attribute compiles runs and verifies IL`` () =
229263
FSharp
230264
"""
231265
module TestModule
232266
233-
type MyAttr(v: int[]) = inherit System.Attribute()
234-
type T = { [<MyAttr([||])>] F: int }
267+
open System
268+
open System.ComponentModel
269+
open System.Reflection
270+
271+
[<DefaultValue([||] : int[])>]
272+
type T() = class end
273+
274+
[<EntryPoint>]
275+
let main _ =
276+
let attr = typeof<T>.GetCustomAttribute<DefaultValueAttribute>()
277+
let arr = attr.Value :?> int[]
278+
printfn "len=%d" arr.Length
279+
0
235280
"""
236-
|> asLibrary
281+
|> asExe
237282
|> compile
238283
|> shouldSucceed
239-
240-
284+
|> verifyPEFileWithSystemDlls
285+
|> shouldSucceed
286+
|> run
287+
|> shouldSucceed
288+
|> withStdOutContains "len=0"

0 commit comments

Comments
 (0)