Skip to content

Allow exact devirtualization for value-type variant instantiations in ilc#129905

Open
jtschuster wants to merge 1 commit into
dotnet:mainfrom
jtschuster:jtschuster/aot-variance-valuetype-devirt
Open

Allow exact devirtualization for value-type variant instantiations in ilc#129905
jtschuster wants to merge 1 commit into
dotnet:mainfrom
jtschuster:jtschuster/aot-variance-valuetype-devirt

Conversation

@jtschuster

Copy link
Copy Markdown
Member

Dictionary<int,int>'s getter regressed slightly in .NET 11 NativeAOT (see semi-related #129895).

PR #123476 made getExactClasses bail for any variant type to avoid unsoundly folding variant casts (e.g. Action vs Action). That guard is slightly over-broad: variance is only relevant for reference types and can be ignored for ValueType type arguments.

This regressed exact devirtualization of the contravariant IEqualityComparer calls in Dictionary<TKey, TValue>.FindValue for value-type keys, inflating the method and slowing the hot path.

We can tighten the condition for bailing early and do so only when a variant generic parameter is instantiated with a reference type.

… NativeAOT

PR dotnet#123476 made getExactClasses bail for any variant type to avoid unsoundly
folding variant casts (e.g. Action<string> vs Action<object>). That guard is
over-broad: variance conversions only happen through reference conversions of
the variant type arguments, so a type instantiated with only value-type variant
arguments cannot be substituted via variance and its implementor list is still
complete.

This regressed exact devirtualization of the contravariant IEqualityComparer<T>
calls in Dictionary<TKey, TValue>.FindValue for value-type keys, inflating the
method and slowing the hot path (issue dotnet#129895).

Bail only when a variant generic parameter is instantiated with a reference (GC)
type, matching CastingHelper's IsBoxedAndCanCastTo which requires IsGCPointer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jtschuster jtschuster self-assigned this Jun 26, 2026
Copilot AI review requested due to automatic review settings June 26, 2026 19:35
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 refines CorInfoImpl.getExactClasses behavior in the NativeAOT ILCompiler JIT interface so that variance only blocks exact-class reporting when variant generic parameters are instantiated with reference types, restoring exact devirtualization opportunities for value-type instantiations.

Changes:

  • Split the type == null || type.HasVariance early-bail to allow more granular variance handling.
  • Introduce a helper to detect whether a variant type instantiation includes any reference-type variant arguments.
  • Use that helper to decide when variance makes getExactClasses unsound.

Comment on lines +2345 to +2346
if (((GenericParameterDesc)genericParameters[i]).Variance != GenericVariance.None
&& typeInstantiation[i].IsGCPointer)
Comment on lines +2296 to +2298
// so reporting an exact class set would be unsound. This only happens through
// reference conversions of the variant arguments, so it's still safe when every
// variant argument is a value type (e.g. the contravariant IEqualityComparer<int>

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.

This is not true, variance can play role for valuetypes too. I had no confidence in being able to capture all the rules when variance and whole program analysis is involved. We had several bugs in this area.

// True
Console.WriteLine(G() is ICollection<uint>);

static object G() => new int[0];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants