Skip to content

Conversation

@YoelDruxman
Copy link

@YoelDruxman YoelDruxman commented Jan 15, 2026

Fix unsafe accessor generic type args

Description

Fixes incorrect UnsafeAccessor code generation when multiple types inherit from different instantiations of the same generic base class.

Problem

When mapping types like:

class A<T> { protected T _value { get; set; } }
class A1 : A<IB> { }
class A2 : A<IC> { }

The UnsafeAccessor would generate code with wrong type arguments for the second type, causing: error CS1503: Argument 1: cannot convert from 'A2' to 'A<IB>'

Root Cause

UnsafeAccessorTypeContext caches accessors by symbol.OriginalDefinition, which ignores type arguments. When processing A1 : A<IB>, it caches the accessor. When processing A2 : A<IC>, it returns the cached accessor with IB type arguments instead of IC.

Solution

Pass the actual containingType at invocation time to BuildAssignment and BuildAccess methods, instead of using the cached symbol's type arguments. This preserves accessor caching (for class generation and naming) while using correct type arguments at each invocation site.

Checklist

  • The existing code style is followed
  • The commit message follows our guidelines
  • Performed a self-review of my code
  • Hard-to-understand areas of my code are commented
  • The documentation is updated (as applicable)
  • Unit tests are added/updated
  • Integration tests are added/updated (as applicable, especially if feature/bug depends on roslyn or framework version in use)

YoelDruxman and others added 2 commits January 15, 2026 09:25
This test exposes a bug where UnsafeAccessor caching causes wrong type
arguments when two types inherit from different instantiations of the
same generic base class (e.g., A<IB> and A<IC>).

The generated code incorrectly uses the cached type argument from the
first processed type for all subsequent types.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fix incorrect type arguments in generated UnsafeAccessor code when
multiple types inherit from different instantiations of the same
generic base class.

Previously, UnsafeAccessorTypeContext cached accessors by
symbol.OriginalDefinition, causing all derived types to use the
type arguments from the first processed type. This fix passes the
actual containing type at invocation time, ensuring each mapping
uses the correct type arguments.

Changes:
- Add containingType parameter to IMemberSetter.BuildAssignment
- Add containingType parameter to IMemberGetter.BuildAccess
- Update UnsafeAccessor implementations to use passed type
- Update callers to pass member's containing type

Fixes the CS1503 error when mapping types like:
- A1 : A<IB>  and  A2 : A<IC>
where both should use their respective type arguments.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@YoelDruxman YoelDruxman changed the title Fix Unsafe Accessor Generic Type Args Fix unsafe accessor generic type args Jan 15, 2026
@YoelDruxman
Copy link
Author

This issue is stopping me from updating from 4.2.1 to the latest version.

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.

1 participant