Skip to content

[bgen] Propagate nullability information for generic type arguments. Fixes #16860#25541

Merged
rolfbjarne merged 28 commits into
mainfrom
dev/rolf/bgen-generic-actions
Jul 3, 2026
Merged

[bgen] Propagate nullability information for generic type arguments. Fixes #16860#25541
rolfbjarne merged 28 commits into
mainfrom
dev/rolf/bgen-generic-actions

Conversation

@rolfbjarne

@rolfbjarne rolfbjarne commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

When properties have generic delegate types (like Action<NSObject?, NSError?>), bgen now correctly propagates the ? nullability annotations on the generic type arguments in the generated C# code.

Previously, bgen only read the first byte of the [NullableAttribute(byte[])] array (for the outer type's nullability), ignoring the remaining bytes that encode nullability for generic type arguments. This caused properties like Action<UIViewController?, NSError?> to be rendered as Action<UIViewController, NSError> — losing the nullability annotations.

Changes

  • src/bgen/AttributeManager.cs: Added GetNullabilityBytes() method that extracts the full byte array from [NullableAttribute].
  • src/bgen/TypeManager.cs: Added FormatType(Type?, Type?, byte[]?) overload and a recursive FormatTypeUsedIn helper that consumes nullability bytes in depth-first traversal order, correctly skipping value types (which don't have bytes in the array).
  • src/bgen/Generator.cs: Updated property rendering to pass nullability bytes. The "wrap" path applies nullability for all delegate types. The "non-wrap" path only applies for void-returning delegates (Action<>) to avoid Func<> covariance issues with trampoline signatures.
  • tests/bgen/BGenTests.cs: Added GenericTypeNullability test with 10 assertions.
  • tests/bgen/tests/generic-type-nullability.cs: Test input covering nullable args, non-nullable args, value types, many args, mixed patterns, and alternating nullability.

Key design decisions

  1. Value types skip byte consumption: The C# compiler does NOT emit bytes for value types in the NullableAttribute array. The fix correctly identifies value types and skips them during traversal.
  2. Func<> covariance guard: Trampolines use non-nullable generic args. This is fine for Action<in T> (contravariant) but breaks for Func<out T> (covariant). The non-wrap path only applies nullability for void-returning delegates.
  3. Wrap path is unrestricted: The wrap path generates self-contained code without trampoline interaction, so it can safely apply nullability for any delegate type.

Fixes #16860

🤖 Pull request created by Copilot

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne marked this pull request as ready for review July 2, 2026 18:05
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #9955220] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 99552202a81159049d5ee5924ff8d649e6117913 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #9955220] Build passed (Build packages) ✅

Pipeline on Agent
Hash: 99552202a81159049d5ee5924ff8d649e6117913 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 99552202a81159049d5ee5924ff8d649e6117913 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #9955220] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 99552202a81159049d5ee5924ff8d649e6117913 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne enabled auto-merge (squash) July 3, 2026 10:55
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #9955220] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 199 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 17 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 18 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 99552202a81159049d5ee5924ff8d649e6117913 [PR build]

@rolfbjarne rolfbjarne merged commit 959aea1 into main Jul 3, 2026
56 checks passed
@rolfbjarne rolfbjarne deleted the dev/rolf/bgen-generic-actions branch July 3, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[generator] Add support for nullable annotations in api definitions

4 participants