Skip to content

[Repo Assist] Fix decodeILCustomAttribData: resolve System.Type custom attribute arguments#490

Merged
dsyme merged 2 commits intomasterfrom
repo-assist/fix-decode-system-type-attrs-20260331-c35ffee8095b70ba
Apr 1, 2026
Merged

[Repo Assist] Fix decodeILCustomAttribData: resolve System.Type custom attribute arguments#490
dsyme merged 2 commits intomasterfrom
repo-assist/fix-decode-system-type-attrs-20260331-c35ffee8095b70ba

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Fixes a long-standing TODO in decodeILCustomAttribData where custom attribute arguments of type System.Type were silently decoded as null instead of the actual Type object.

Root Cause

In ECMA-335, custom attribute constructors store System.Type arguments as serialised strings (the assembly-qualified type name) in the attribute blob — not as TypeRef/TypeDef table indices. The existing code parsed the type name string correctly via ILTypeSigParser, but then discarded the result and returned null:

// Before — TODO comments, always returned null
| None -> (argty, box null), sigptr // TODO: read System.Type attrs
| Some n ->
    let parser = ILTypeSigParser(n)
    parser.ParseType() |> ignore
    (argty, box null), sigptr  // TODO: read System.Type attributes

Fix

  1. Added a resolveILType: ILType -> Type parameter to decodeILCustomAttribData so the caller provides a type resolver.
  2. The System.Type branch now uses the parsed ILType and resolves it via the provided resolver.
  3. Graceful fallback to null if resolution fails (e.g. the type is not present in the target context).
  4. At the call site in txCustomAttributesDatum, passes txILType ([||], [||]) — the existing target-assembly type translator — as the resolver.
// After — resolves the type from the attribute blob
| None -> (argty, box null), sigptr
| Some n ->
    let parser = ILTypeSigParser(n)
    let ilty = parser.ParseType()
    let resolvedType = try resolveILType ilty with _ -> null
    (argty, box resolvedType), sigptr

Impact

Custom attributes like DebuggerTypeProxyAttribute (constructor takes Type) that are read from binary reference assemblies via the target assembly reader now return the correct Type value instead of null. This improves the accuracy of GetCustomAttributesData() for target-context types.

Test Status

✅ All 126 tests pass locally (dotnet test tests/FSharp.TypeProviders.SDK.Tests.fsproj -c Release)

A dedicated test for this specific path would require finding a reference assembly type with a System.Type custom attribute argument and verifying it resolves non-null — feasible but deferred to a follow-up as it requires navigating the target context fixture.

Generated by 🌈 Repo Assist at {run-started}. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@1f672aef974f4246124860fc532f82fe8a93a57e

…guments

Previously, when decoding custom attribute blobs containing System.Type
arguments, the type name string was parsed but then discarded, returning
null for every Type argument. This fixes two TODO comments (lines 6751
and 6756 in the original) by:

1. Adding a 'resolveILType: ILType -> Type' parameter to
   decodeILCustomAttribData so callers can provide a type resolver.
2. Using ILTypeSigParser to parse the stored type name string into an
   ILType, then resolving it via the provided resolver.
3. Falling back to null gracefully if resolution fails (e.g. the type
   is not available in the target context).
4. Passing 'txILType ([||], [||])' at the call site so types are
   resolved via the existing target-assembly translation layer.

This means that attributes like DebuggerTypeProxyAttribute, which pass
a System.Type to their constructor, now decode correctly when read from
binary assemblies via the target assembly reader.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review April 1, 2026 17:09
@dsyme dsyme merged commit d1b018c into master Apr 1, 2026
2 checks passed
dsyme pushed a commit that referenced this pull request Apr 20, 2026
…ase 8.7.0 (#506)

🤖 *This is an automated pull request from Repo Assist.*

## Summary

Adds `GenerativeCustomAttributeTests.fs` — 5 regression tests for custom
attribute encoding in the generative IL writer. These cover attribute
targets and argument types not previously exercised by the existing
tests in `BasicGenerativeProvisionTests.fs` (which only tested
attributes on *properties*).

Also updates `RELEASE_NOTES.md` with a new `8.7.0` entry covering this
and the previously-merged `GenerativeMethodsTests` (#505).

## New tests

| Test | What it verifies |
|------|-----------------|
| `Custom attribute on a generative type round-trips correctly` |
`ObsoleteAttribute(string, bool)` placed on the *type definition itself*
|
| `Custom attribute with bool constructor argument round-trips
correctly` | `bool` values survive the ECMA-335 encode/decode path |
| `Custom attribute with enum constructor argument round-trips
correctly` | `DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)`
— enum arg decoded as underlying int |
| `Multiple custom attributes on a single generative method are all
preserved` | `defineCustomAttrs` writes **all** attributes, not just the
first |
| `Custom attribute on a generative method has correct string argument`
| `DescriptionAttribute(string)` on an instance method |

## Root cause / motivation

Several custom-attribute encoding bugs were fixed in earlier PRs
(`#432`, `#490`, `#501`). This PR adds focused regression tests for the
remaining un-covered paths:
- attributes on **types** (not just members)  
- attributes on **methods** (not just properties)  
- **bool** and **enum** constructor argument encoding  
- multiple attributes on a single member

## Test Status

```
Passed! - Failed: 0, Passed: 147, Skipped: 0, Total: 147, Duration: 7 s
```
All 147 tests pass (142 pre-existing + 5 new).




> Generated by 🌈 Repo Assist, see [workflow
run](https://github.com/fsprojects/FSharp.TypeProviders.SDK/actions/runs/24617397828).
[Learn
more](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md).
>
> To install this [agentic
workflow](https://github.com/githubnext/agentics/blob/97143ac59cb3a13ef2a77581f929f06719c7402a/workflows/repo-assist.md),
run
> ```
> gh aw add
githubnext/agentics@97143ac
> ```

<!-- gh-aw-agentic-workflow: Repo Assist, engine: copilot, model: auto,
id: 24617397828, workflow_id: repo-assist, run:
https://github.com/fsprojects/FSharp.TypeProviders.SDK/actions/runs/24617397828
-->

<!-- gh-aw-workflow-id: repo-assist -->

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant