Skip to content

Make constructor selection in CallSiteFactory deterministic and allocation-lighter#129119

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-activatorutilities-constructor-order
Draft

Make constructor selection in CallSiteFactory deterministic and allocation-lighter#129119
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-activatorutilities-constructor-order

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 8, 2026

CallSiteFactory.CreateConstructorCallSite previously depended on an unstable Array.Sort for multi-constructor selection, which made same-arity/same-parameter-set resolution implementation-defined. This change replaces sort-based selection with deterministic reflection-order tracking while preserving existing behavior outside that tie case.

  • What changed

    • Replaced sort-and-walk with a single-pass constructor scan in reflection (declaration) order.
    • Precomputes each constructor’s ParameterInfo[] exactly once and reuses it.
    • Tracks the best resolvable constructor by arity; larger resolvable constructors replace smaller ones.
    • Skips CreateArgumentCallSites for constructors smaller than the current best.
    • Preserves existing ambiguity and activation exception shapes/messages.
    • Preserves constructors.Length == 0 and constructors.Length == 1 short-circuit paths unchanged.
  • Behavioral delta (intended and scoped)

    • Only changed case: when two resolvable constructors have the same arity and identical parameter type sets, selection is now deterministic (first in declaration order) instead of depending on unstable sort ordering.
    • All other selection outcomes remain unchanged.
  • Tests added

    • Same-arity, identical parameter-type set, different parameter order → verifies declaration-order constructor is selected.
    • Same-arity, disjoint parameter types, both resolvable → verifies existing ambiguous-constructor InvalidOperationException.
    • Short resolvable declared before longer resolvable → verifies longer constructor wins.
    • Short resolvable declared before longer non-resolvable → verifies short constructor wins.
// Before: unstable ordering + repeated GetParameters allocations
// Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length));

// After: deterministic single-pass with cached parameters
ParameterInfo[][] parametersByConstructor = new ParameterInfo[constructors.Length][];
for (int i = 0; i < constructors.Length; i++)
{
    parametersByConstructor[i] = constructors[i].GetParameters();
}

// Walk in reflection order, keep best resolvable by arity, handle ties via existing ambiguity rule.
  • DI suite status
    • DI.Tests and DI.External.Tests pass locally with this change.

Copilot AI self-assigned this Jun 8, 2026
Copilot AI review requested due to automatic review settings June 8, 2026 07:48
Copilot AI review requested due to automatic review settings June 8, 2026 07:48
…n order

Co-authored-by: rosebyte <14963300+rosebyte@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 8, 2026 08:31
Copilot AI changed the title [WIP] Fix ActivatorUtilities constructor selection based on order Make constructor selection in CallSiteFactory deterministic and allocation-lighter Jun 8, 2026
Copilot AI requested a review from rosebyte June 8, 2026 08:32
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ActivatorUtilities - matching preferred constructor depends on the constructors order

2 participants