Skip to content

Commit dcaa43f

Browse files
T-GroCopilot
andcommitted
Fix empty array handling in custom attributes: use Object element type instead of erroring
Empty arrays of user-defined types in custom attributes (e.g. [<DefaultValue([||] : A[])>]) no longer produce FS3885. Since no elements need encoding, System.Object is used as the element type. Non-empty arrays of unencodable types still error correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 73cfbce commit dcaa43f

3 files changed

Lines changed: 24 additions & 16 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* Fixed how the source ranges of warn directives are reported (as trivia) in the parser output (by not reporting leading spaces). ([Issue #19405](https://github.com/dotnet/fsharp/issues/19405), [PR #19408]((https://github.com/dotnet/fsharp/pull/19408)))
2020
* Fix UoM value type `ToString()` returning garbage values when `--checknulls+` is enabled, caused by double address-taking in codegen. ([Issue #19435](https://github.com/dotnet/fsharp/issues/19435), [PR #19440](https://github.com/dotnet/fsharp/pull/19440))
2121
* Fix completion inconsistently showing some obsolete members (fields and events) while hiding others (methods and properties). All obsolete members are now consistently hidden by default. ([Issue #13512](https://github.com/dotnet/fsharp/issues/13512), [PR #19506](https://github.com/dotnet/fsharp/pull/19506))
22-
* Fix internal error `FS0192: encodeCustomAttrElemType` when using an array of user-defined type as a custom attribute argument. Now reports a proper diagnostic (FS3885). ([Issue #12796](https://github.com/dotnet/fsharp/issues/12796), [PR #19472](https://github.com/dotnet/fsharp/pull/19472))
22+
* Fix internal error `FS0192: encodeCustomAttrElemType` when using an empty array of user-defined type as a custom attribute argument (e.g. `[<DefaultValue([||] : A[])>]`). Empty arrays of arbitrary types are now encoded using `System.Object` as the element type. ([Issue #12796](https://github.com/dotnet/fsharp/issues/12796), [PR #19472](https://github.com/dotnet/fsharp/pull/19472))
2323

2424
### Added
2525

src/Compiler/CodeGen/IlxGen.fs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10224,18 +10224,26 @@ and GenAttribArg amap g eenv x (ilArgTy: ILType) =
1022410224
| Expr.Op(TOp.Array, [ elemTy ], args, m), _ ->
1022510225
let ilElemTy = GenType amap m eenv.tyenv elemTy
1022610226

10227-
// Validate element type is encodable in custom attribute metadata (ECMA 335).
10228-
// Only primitive types, enums, string, System.Type, and System.Object are valid.
10229-
match ilElemTy with
10230-
| ILType.Boxed tspec when
10231-
tspec.Name <> "System.String"
10232-
&& tspec.Name <> "System.Object"
10233-
&& tspec.Name <> "System.Type"
10234-
->
10235-
error (Error(FSComp.SR.ilCustomAttrInvalidArrayElemType (tspec.Name), m))
10236-
| _ -> ()
10227+
// Check if element type can be encoded in custom attribute metadata (ECMA 335).
10228+
// Valid element types: primitives, enums, string, System.Type, System.Object.
10229+
let isUnencodableBoxedElemType =
10230+
match ilElemTy with
10231+
| ILType.Boxed tspec when
10232+
tspec.Name <> "System.String"
10233+
&& tspec.Name <> "System.Object"
10234+
&& tspec.Name <> "System.Type"
10235+
->
10236+
true
10237+
| _ -> false
1023710238

10238-
ILAttribElem.Array(ilElemTy, List.map (fun arg -> GenAttribArg amap g eenv arg ilElemTy) args)
10239+
if isUnencodableBoxedElemType then
10240+
if args.IsEmpty then
10241+
// Empty arrays: substitute System.Object as element type since no elements need encoding.
10242+
ILAttribElem.Array(g.ilg.typ_Object, [])
10243+
else
10244+
error (Error(FSComp.SR.ilCustomAttrInvalidArrayElemType (ilElemTy.TypeRef.Name), m))
10245+
else
10246+
ILAttribElem.Array(ilElemTy, List.map (fun arg -> GenAttribArg amap g eenv arg ilElemTy) args)
1023910247

1024010248
// Detect 'typeof<ty>' calls
1024110249
| TypeOfExpr g ty, _ -> ILAttribElem.Type(Some(GenType amap x.Range eenv.tyenv ty))

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ type C() =
7979
|> shouldSucceed
8080

8181
// https://github.com/dotnet/fsharp/issues/12796
82-
// Passing an array of a user-defined type as a custom attribute argument is invalid per ECMA 335.
83-
// Previously this caused FS0192 internal error in encodeCustomAttrElemType. Now it gives a proper diagnostic.
82+
// Empty arrays of user-defined types in custom attributes should compile successfully.
83+
// The element type is substituted with System.Object since no elements need encoding.
84+
// Previously this caused FS0192 internal error in encodeCustomAttrElemType.
8485
[<Fact>]
8586
let ``Issue 12796 - DefaultValue empty array on record field of array type should not cause internal error`` () =
8687
FSharp
@@ -94,5 +95,4 @@ type B = { [<DefaultValue([||] : A[])>] BField: A[] }
9495
"""
9596
|> asLibrary
9697
|> compile
97-
|> shouldFail
98-
|> withErrorCode 3885
98+
|> shouldSucceed

0 commit comments

Comments
 (0)