Skip to content

Mark descriptor-preserved members as reflection-visible#128272

Open
sbomer wants to merge 12 commits into
dotnet:mainfrom
sbomer:descriptor-abstract
Open

Mark descriptor-preserved members as reflection-visible#128272
sbomer wants to merge 12 commits into
dotnet:mainfrom
sbomer:descriptor-abstract

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 15, 2026

And mark their declaring types as reflection-visible.

When a member is marked via descriptor it should be considered visible to reflection. And when that is the case, its declaring type is accessible via reflection, so the requirements for reflection-visible types should be preserved too.

Fixes #128120

sbomer and others added 8 commits May 15, 2026 15:51
…t impls

Add a regression test for dotnet#128120. When a type is preserved
via an XML descriptor, ILLink should keep its static abstract interface
implementations if those methods are called through constrained generics
elsewhere in the program. Currently the test fails because ILLink strips
the interface and override from the descriptor-preserved type.

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
…ant casting

A method preserved via XML descriptor is reflection-visible, which means
its declaring type is also accessible (e.g., via
MethodBase.GetCurrentMethod().DeclaringType) and could be used as a
generic argument in constrained calls (e.g., via MakeGenericMethod).

Mark the declaring type as relevant to variant casting so that its static
abstract interface implementations are preserved by the linker.

Fixes dotnet#128120

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
…t be kept

Test that a reference type with explicit layout preserved via XML
descriptor retains its fields. This verifies the type is treated as
fully reflection-visible (MarkImplicitlyUsedFields), not just relevant
to variant casting.

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
…tion-visible

Descriptor-preserved methods and fields are reflection-visible. Their
declaring types are also accessible (e.g., via MethodBase.DeclaringType
or FieldInfo.DeclaringType) and could be used as generic arguments in
constrained calls via MakeGenericMethod.

Defer full reflection-visible treatment from DescriptorMarker to
MarkStep via pending sets in Annotations, so that MarkStep can call
MarkMethodVisibleToReflection, MarkFieldVisibleToReflection, and
MarkTypeVisibleToReflection on the declaring type. This ensures:
- Static abstract interface implementations are preserved
- Implicit fields for explicit-layout types are preserved
- Metadata names are not swept
- TypeMap entries are processed

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
Clarify that GetCurrentMethod produces IL2026 but the suppression is
justified because the descriptor preserves the method. Add
ExpectedNoWarnings to the explicit layout test.

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
- Remove unnecessary #pragma warning disable IL2060 from tests
- Add ExpectedNoWarnings to explicit layout test
- Remove issue references from test comments
- Clarify comment about IL2026 suppression justification
- Expose pending sets as properties, inline clear in ProcessMarkedPending
- Separate doc comments for method and field pending sets

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
Copilot AI review requested due to automatic review settings May 15, 2026 22:55
@github-actions github-actions Bot added the area-Tools-ILLink .NET linker development as well as trimming analyzers label May 15, 2026
@dotnet-policy-service dotnet-policy-service Bot added the linkable-framework Issues associated with delivering a linker friendly framework label May 15, 2026
@sbomer sbomer force-pushed the descriptor-abstract branch from bf799c8 to 323fb3e Compare May 15, 2026 22:56
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/illink
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the ILLink marking pipeline so that members preserved via XML descriptors are treated as reflection-visible, and it additionally marks their declaring types as reflection-visible to preserve reflection-dependent semantics (e.g., variant casting behaviors and explicit-layout field preservation).

Changes:

  • Add pending-tracking for descriptor-preserved methods/fields and process them in MarkStep via Mark*VisibleToReflection, also marking declaring types reflection-visible.
  • Extend DescriptorMarker to schedule descriptor-preserved fields/methods for reflection-visible processing.
  • Add new linker test cases + descriptors validating static abstract interface implementations and explicit-layout fields are preserved when reachability is via descriptor-preserved members.
Show a summary per file
File Description
src/tools/illink/src/linker/Linker/Annotations.cs Adds pending collections/APIs to schedule descriptor-preserved members for reflection-visible processing.
src/tools/illink/src/linker/Linker.Steps/MarkStep.cs Drains pending reflection-visible members and marks members + declaring types as reflection-visible.
src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs Schedules descriptor-preserved fields/methods for reflection-visible handling.
src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/StaticInterfaceMethods/StaticAbstractMethodsPreservedViaDescriptor.cs New regression test for static abstract interface implementations preserved via descriptor reachability.
src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/StaticInterfaceMethods/StaticAbstractMethodsPreservedViaDescriptor.xml Descriptor roots methods used by the static-abstract preservation test.
src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/StaticInterfaceMethods/DescriptorPreservedTypeIsReflectionVisible.cs New test validating descriptor-preserved type is fully treated as reflection-visible (variant casting + explicit layout fields).
src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/StaticInterfaceMethods/DescriptorPreservedTypeIsReflectionVisible.xml Descriptor roots methods used by the reflection-visible type behavior test.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 3

Comment thread src/tools/illink/src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/tools/illink/src/linker/Linker/Annotations.cs Outdated
sbomer and others added 3 commits May 15, 2026 16:35
ILTrim does not support static abstract interface methods or
descriptor-based reflection-visible marking.

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
- Convert tabs to spaces in test files to match .editorconfig
- Remove spaces before parentheses to match neighbor test style
- Make pending reflection-visible APIs internal

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
Pass DependencyInfo and MessageOrigin from DescriptorMarker through to
MarkStep so warnings and dependency tracking attribute correctly to the
descriptor XML location. Encapsulate the pending data behind a
DrainPendingReflectionVisibleMembers method.

Co-authored-by: Copilot <[email protected]>
Assisted-by: Claude:claude-opus-4.6-1m
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Comment thread src/tools/illink/src/linker/Linker/Annotations.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Copilot AI review requested due to automatic review settings May 16, 2026 00:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment on lines +260 to +270
internal List<(MethodDefinition Method, DependencyInfo Reason, MessageOrigin Origin)> DrainPendingReflectionVisibleMethods()
{
var result = pending_reflection_visible_methods;
pending_reflection_visible_methods = new List<(MethodDefinition, DependencyInfo, MessageOrigin)>();
return result;
}

internal List<(FieldDefinition Field, DependencyInfo Reason, MessageOrigin Origin)> DrainPendingReflectionVisibleFields()
{
var result = pending_reflection_visible_fields;
pending_reflection_visible_fields = new List<(FieldDefinition, DependencyInfo, MessageOrigin)>();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Tools-ILLink .NET linker development as well as trimming analyzers linkable-framework Issues associated with delivering a linker friendly framework

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Referencing type from ILLink.Descriptors doesn't preserve its static abstracts

2 participants