Skip to content

Fix compatible-mode remap of pointer-to-fnptr-typedef fields#744

Merged
tannergooding merged 1 commit into
dotnet:mainfrom
tannergooding:tannergooding-fix-fnptr-remap-compatible
Jul 13, 2026
Merged

Fix compatible-mode remap of pointer-to-fnptr-typedef fields#744
tannergooding merged 1 commit into
dotnet:mainfrom
tannergooding:tannergooding-fix-fnptr-remap-compatible

Conversation

@tannergooding

Copy link
Copy Markdown
Member

In compatible mode (ExcludeFnptrCodegen) a function-pointer typedef is emitted as a managed delegate. GetTypeNameForPointeeType short-circuited a remapped typedef to a pointer of the remapped name, so a field pointing at such a typedef emitted a pointer to the managed delegate (e.g. PFoo*), which is invalid -- it produces CS8500 and forces the containing struct unsafe.

Given:

typedef void (ApiPFoo)(int);
struct ApiCallbacks { ApiPFoo* Foo; };

with --remap ApiCallbacks=Callbacks ApiPFoo=PFoo in compatible mode.

Before:

public unsafe partial struct Callbacks
{
    [NativeTypeName("ApiPFoo *")]
    public PFoo* Foo;
}

After (matches the no-remap case; the delegate is still renamed to PFoo, only the field changes):

public partial struct Callbacks
{
    [NativeTypeName("ApiPFoo *")]
    public IntPtr Foo;
}

The fix mirrors the non-remapped path: in the wasRemapped branch, when ExcludeFnptrCodegen is set and the typedef's underlying type is a function type, emit IntPtr. The unsafe modifier drops automatically once the field is IntPtr.


Scoped to compatible mode only. Latest/preview (function-pointer) codegen for remapped fnptr typedefs is intentionally untouched -- there's no named delegate there, so the correct rendering is a separate, ill-defined design question.

Added FunctionPointerRemapTest covering compatible Windows + Unix. Full generator suite passes (Failed: 0, Passed: 3726), zero golden churn.

Fixes #462

In compatible mode a function-pointer typedef is emitted as a managed
delegate. GetTypeNameForPointeeType short-circuited a remapped typedef
to a pointer of the remapped name, so a field pointing at such a typedef
emitted a pointer to the managed delegate (e.g. PFoo*), which is invalid
and produces CS8500 and forces the struct unsafe. Match the non-remapped
path and emit IntPtr when ExcludeFnptrCodegen is set and the typedef's
underlying type is a function type.

Fixes dotnet#462

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding tannergooding merged commit 9e2c19e into dotnet:main Jul 13, 2026
14 checks passed
@tannergooding tannergooding deleted the tannergooding-fix-fnptr-remap-compatible branch July 13, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect function pointer mapping in case of remapping

1 participant