Skip to content

ILLink: keep base-type interfaces when a derived type is relevant to variant casting - #135961

Merged
jtschuster merged 9 commits into
mainfrom
copilot/fix-generic-base-class-implementation
Oct 29, 2026
Merged

jtschuster merged 9 commits into
mainfrom
copilot/fix-generic-base-class-implementation

Conversation

Copilot AI commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

A type reached only through typeof is marked relevant to variant casting, and its marked interface implementations are kept. Its uninstantiated base type was not marked, so the base lost its interface implementations and explicit implementation methods (e.g. IEnumerable.GetEnumerator) while the derived type kept the same interfaces. The trimmed derived type then fails to load with TypeLoadException.

abstract class Base<T> : IEnumerable<T> { /* explicit IEnumerable.GetEnumerator */ }
interface IDerived<T> : IEnumerable<T> { }
class Derived<T> : Base<T>, IDerived<T> { }

var t = typeof(Derived<>);   // nothing instantiates Base<T> or Derived<T>
  • MarkStep.MarkRelevantToVariantCasting
    • Also marks the type's base types as relevant to variant casting. A type's interface set includes the interfaces from its base types, so this follows the same rule.
    • The walk stops at the first base type that is already marked, since its own bases are then marked too.
    • _typeMapHandler.ProcessType is still only invoked for the type itself, so type-map behavior for base types is unchanged.
  • Test
    • Added Inheritance.Interfaces/OnReferenceType/UninstantiatedGenericBaseWithInterfacesAndDerivedInterface.cs. It mirrors the repro with custom interfaces and an explicit implementation on Base<T>.
    • Without the fix, Base<T> loses its interfaces and the explicit method while Derived<T> keeps them.

Behavior change: base types of any reflection-visible (typeof/ldtoken) type now keep their marked interface implementations even when never instantiated. This costs a small amount of size and avoids the load failure.

@azure-pipelines

azure-pipelines Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

…d type

Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
@dotnet-policy-service dotnet-policy-service Bot added the linkable-framework Issues associated with delivering a linker friendly framework label Oct 16, 2026
Copilot AI changed the title [WIP] Fix issue with ILLink stripping interfaces of uninstantiated generics ILLink: keep base-type interfaces when a derived type is relevant to variant casting Oct 16, 2026
Copilot AI requested a review from jtschuster October 16, 2026 17:06
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
…ntries are handled

Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
@jtschuster

Copy link
Copy Markdown
Member

@copilot ilcompiler tests are failing. Make sure they pass before pushing.

…ler tests pass

Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>

Copilot AI commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot ilcompiler tests are failing. Make sure they pass before pushing.

Fixed in ae2dad5. The failing linux-x64 checked CLR_Tools_Tests job was ILCompiler.Trimming.Tests on Generics.VariantCasting: NativeAOT doesn't keep the unconstructed UninstantiatedBaseWithInterfaces<T>, its interfaces, or the unreachable interface methods. I scoped those expectations to By = Tool.Trimmer. I built clr.aot and libs.sfx locally and ran ILCompiler.Trimming.Tests for the Generics and Reflection suites; everything passes except Reflection.TypeUsedViaReflection, which needs ilasm (not built in my environment). Mono.Linker.Tests Generics and Reflection also pass (71/71).

@jtschuster
jtschuster marked this pull request as ready for review October 19, 2026 18:58
@jtschuster
jtschuster requested a review from sbomer as a code owner October 19, 2026 18:58

@sbomer sbomer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@jtschuster
jtschuster merged commit 75df8eb into main Oct 29, 2026
93 checks passed
@jtschuster
jtschuster deleted the copilot/fix-generic-base-class-implementation branch October 29, 2026 17:53
@github-project-automation github-project-automation Bot moved this to Done in AppModel Oct 29, 2026
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-TypeSystem-coreclr linkable-framework Issues associated with delivering a linker friendly framework

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

ILLink strips interfaces of an uninstantiated generic base class while the derived class keeps them, causing TypeLoadException

3 participants