Skip to content

[Repo Assist] Fix GetEnumUnderlyingType for non-Int32 enums + tests for byte/int64 enums#470

Merged
dsyme merged 2 commits intomasterfrom
repo-assist/improve-enum-underlying-type-20260309-06cd96f67ed87c55
Mar 16, 2026
Merged

[Repo Assist] Fix GetEnumUnderlyingType for non-Int32 enums + tests for byte/int64 enums#470
dsyme merged 2 commits intomasterfrom
repo-assist/improve-enum-underlying-type-20260309-06cd96f67ed87c55

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Mar 9, 2026

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

Two related improvements to enum support in the type provider SDK.

Fix: TargetTypeDefinition.GetEnumUnderlyingType() (Task 5 – Coding Improvement)

Before: TargetTypeDefinition.GetEnumUnderlyingType() always returned System.Int32, regardless of the actual enum backing type in the reference assembly:

// TODO: in theory the assumption of "Int32" is not accurate for all enums,
// however in practice .NET only uses enums with backing field Int32
txILType ([| |], [| |]) ilGlobals.typ_Int32

The comment was incorrect — .NET (and F#/C#) fully support enums backed by byte, sbyte, int16, uint16, int32, uint32, int64, and uint64.

After: Looks up the value__ special field that the compiler emits on every enum IL type definition and returns its type. Falls back to Int32 only if the field is absent (which would indicate a malformed binary):

let valueField = inp.Fields.Entries |> Array.tryFind (fun f -> f.Name = "value__")
match valueField with
| Some f -> txILType ([| |], [| |]) f.FieldType
| None -> txILType ([| |], [| |]) ilGlobals.typ_Int32
```

This affects type providers that read reference assemblies containing non-`int32` enums and need to accurately reflect their underlying type (e.g., interop scenarios with `byte` flag enums, or `int64` discriminated enums).

## Tests: Generative enums with `byte` and `int64` underlying types (Task 9 Testing Improvements)

Added two new type provider fixtures and two new `[(Fact)]` tests in `GenerativeEnumsProvisionTests.fs`:

| Test | Provider | Underlying type | Notable case |
|------|----------|-----------------|--------------|
| `Generative enum with byte underlying type is generated correctly` | `GenerativeByteEnumsProvider` | `byte` (`uint8`) | Verifies 0, 1, 255 encoded correctly |
| `Generative enum with int64 underlying type is generated correctly` | `GenerativeInt64EnumsProvider` | `int64` | Uses `3_000_000_000L` (> `Int32.MaxValue`) to confirm 64-bit path |

Both tests verify:
- The generated assembly loads without error
- `IsEnum` is true on the generated type
- `GetEnumUnderlyingType()` returns the expected type
- `Enum.GetValues` and `Enum.GetNames` return the correct values

## Test Status

```
Passed!  - Failed: 0, Passed: 112, Skipped: 0, Total: 112, Duration: 6 s

108 existing tests + 4 new tests, all passing.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

…int32 enum backing types

- Fix TargetTypeDefinition.GetEnumUnderlyingType() to read the 'value__' special
  field from the IL type definition instead of always returning Int32. This correctly
  handles enums backed by byte, int16, int64, uint32, etc.

- Add GenerativeByteEnumsProvider and GenerativeInt64EnumsProvider test fixtures in
  GenerativeEnumsProvisionTests.fs, plus two new [<Fact>] tests that verify the
  generated assembly carries the right underlying type and correct literal values.
  The int64 test uses a value > Int32.MaxValue (3_000_000_000L) to confirm the 64-bit
  encoding path in the IL binary writer is exercised.

All 112 tests pass (108 existing + 4 new).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review March 16, 2026 17:32
@dsyme dsyme merged commit fedcc2e into master Mar 16, 2026
2 checks passed
dsyme pushed a commit that referenced this pull request Mar 17, 2026
… attribute test (#477)

🤖 *This is an automated PR from Repo Assist, an AI assistant for this
repository.*

## Summary

Two categories of testing improvement for generative type providers,
both targeting previously untested code paths.

### 1 — Generative event tests (`GenerativeEventsTests.fs`, new file, 4
tests)

`ProvidedEvent` was used in `BasicGenerativeProvisionTests.fs` to
construct a type, but no test ever loaded the resulting generated
assembly and verified that events survived the round-trip. The new file
adds:

| Test | What it checks |
|------|----------------|
| `Generative instance event is present` | Event exists in generated
assembly, `EventHandlerType` is correct, add/remove are instance methods
|
| `Instance event add/remove methods have correct signatures` |
`add_Changed`/`remove_Changed` names, single `EventHandler` parameter |
| `Generative static event is present` | Static event exists, add/remove
are static methods |
| `Generative type has expected event count` | Total event count is 2
(one instance + one static) |

### 2 — Named-argument custom attribute test
(`BasicGenerativeProvisionTests.fs`, 1 test)

Existing custom-attribute tests only exercised positional constructor
arguments (`ConstructorArguments`). The `NamedArguments` encoding path
in `defineCustomAttrs` (ProvidedTypes.fs lines 15696–15697) was
reachable but untested. The new test:

- Adds `GenerativeProviderWithNamedArgAttrs` — a generative type
provider that attaches `DebuggerDisplayAttribute("{Value}")` **with a
named property argument** `Name = "MyProp"` to a provided property.
- Verifies both the constructor arg `"{Value}"` and the named arg `Name
= "MyProp"` survive `GetGeneratedAssemblyContents` → `Assembly.Load` →
`GetCustomAttributesData()`.

## Test Status

```
Passed! - Failed: 0, Passed: 117, Skipped: 0, Total: 117
```
(117 tests; was 110 before this PR's additions, with the delta from PRs
#470 / #475 already merged.)




> Generated by [Repo
Assist](https://github.com/fsprojects/FSharp.TypeProviders.SDK/actions/runs/23172533836)
·
[◷](https://github.com/search?q=repo%3Afsprojects%2FFSharp.TypeProviders.SDK+%22gh-aw-workflow-id%3A+repo-assist%22&type=pullrequests)
>
> To install this [agentic
workflow](https://github.com/githubnext/agentics/tree/346204513ecfa08b81566450d7d599556807389f/workflows/repo-assist.md),
run
> ```
> gh aw add
githubnext/agentics@3462045
> ```

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

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

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dsyme pushed a commit that referenced this pull request Apr 1, 2026
🤖 *This PR was created by [Repo
Assist](https://github.com/fsprojects/FSharp.TypeProviders.SDK/actions/runs/23774627661),
an automated AI assistant.*

## Summary

Release notes for version **8.4.0**, covering all changes merged since
8.3.0 (February 26, 2026).

## Changes included in 8.4.0

**Bug fixes:**
- `GetEnumUnderlyingType()` now correctly handles non-Int32 enum
underlying types (#470)
- `decodeILCustomAttribData` reads correct byte-width for non-Int32 enum
fixed args (ECMA-335) (#475)
- Generative delegate type support fixed; `GetInterface` implemented on
`ProvidedTypeDefinition` and `TargetTypeDefinition` (#479)
- Thread-safety races in `TargetTypeDefinition` member-wrapper caches
fixed (#482)

**Performance:**
- Member wrapper objects cached in `TargetTypeDefinition` to avoid
repeated allocations (#471)
- `FullName`, `BaseType` and `GetInterfaces()` cached in
`TargetTypeDefinition` (#485)

**Refactoring:**
- `mkCacheInt32`/`mkCacheGeneric` simplified to use
`ConcurrentDictionary` (#486)

**CI:**
- GitHub Actions updated from v1 to v4 (#476)

## Test Status

✅ All 126 tests pass on the current master (`dotnet test
tests/FSharp.TypeProviders.SDK.Tests.fsproj -c Release`)

*Please bump the NuGet package version to 8.4.0 in the project file
before merging if that step isn't automated.*




> Generated by 🌈 Repo Assist at
[{run-started}](https://github.com/fsprojects/FSharp.TypeProviders.SDK/actions/runs/23774627661).
[Learn
more](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md).
>
> To install this [agentic
workflow](https://github.com/githubnext/agentics/tree/1f672aef974f4246124860fc532f82fe8a93a57e/workflows/repo-assist.md),
run
> ```
> gh aw add
githubnext/agentics@1f672ae
> ```

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

<!-- 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>
dsyme pushed a commit that referenced this pull request Apr 13, 2026
… call); add 5 tests for warning + enum round-trip (#501)

🤖 *This PR was created by [Repo
Assist](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md),
an automated AI assistant.*

## Summary

This PR bundles a **bug fix** and **new tests** (Task 9: Testing
Improvements).

### Bug fix: `ProvidedTypeDefinition.Logger` was silently broken

The static `Logger` member was implemented as a computed property:

```fsharp
// Before — creates a fresh ref cell on every access; impossible to set
static member Logger: (string -> unit) option ref = ref None
```

Every read of `ProvidedTypeDefinition.Logger` returned a *different*
`ref` object, so calling `ProvidedTypeDefinition.Logger := Some f` would
write into a temporary cell that is immediately discarded. The Logger
was effectively inoperative: the "all static parameters optional"
warning (added in 8.3.0 / PR #428) could never fire via the Logger, and
type-creation trace messages were silently dropped.

**Fix**: introduces a `static let loggerRef` field and makes `Logger`
return it:

```fsharp
static let loggerRef: (string -> unit) option ref = ref None
...
static member Logger: (string -> unit) option ref = loggerRef
```

### New tests (5 tests, 131 total)

**`BasicErasedProvisionTests.fs` — 3 new tests for the all-optional
warning:**
- `DefineStaticParameters warns when all static parameters have
defaults` — regression for the warning path (which was previously
unreachable due to the Logger bug)
- `DefineStaticParameters does not warn when at least one parameter has
no default`
- `DefineStaticParameters does not warn when there are no static
parameters`

**`GenerativeEnumsProvisionTests.fs` — 2 new tests for non-Int32 enum
round-trip via target context:**
- `Byte enum underlying type is correct when read via target context
(ReadRelatedAssembly)` — exercises
`TargetTypeDefinition.GetEnumUnderlyingType()` for a `byte`-backed enum
- `Int64 enum underlying type is correct when read via target context
(ReadRelatedAssembly)` — same for `int64`-backed enums

These complement the existing runtime-path enum tests (`Assembly.Load`)
by covering the design-time IL-reader path, which was fixed in PR
#470/#475.

## Trade-offs

- The Logger ref is now module-level shared state. Tests that manipulate
it should save/restore the previous value (all three new tests do this
via `try/finally`).

## Test Status

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




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

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

<!-- 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