Skip to content

DependencyInjection generic constraint validation incorrectly rejects struct constraint on mobile #127564

Description

@github-actions

Reasoning

Microsoft.Extensions.DependencyInjection.Tests is failing on mobile platforms (iOS, tvOS, macCatalyst, Android) with errors related to generic constraint validation. The DI container's ValidateTrimmingAnnotations method is incorrectly rejecting implementations that have a new() constraint when the service interface doesn't have one.

The error states:

Generic implementation type 'ClassWithStructConstraint1' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type 'IFakeOpenGenericService1' doesn't.

This validation is overly restrictive. An implementation can have more constraints than the interface it implements — that's valid and safe. The constraint on the implementation guarantees that any type argument passed will satisfy the implementation's needs, which includes satisfying the less-restrictive interface. The validation logic appears to be requiring exact constraint matching instead of allowing implementation constraints to be a superset of interface constraints.

This is a product bug in the DI container's constraint validation logic, not a test issue. The same tests pass on desktop platforms.

Impact on platforms

Failing on all tested mobile platforms in build 1399212 (2026-04-28):

  • maccatalyst-arm64 / OSX.15.Arm64.Open / exit code 1
  • iossimulator-arm64 / OSX.15.Arm64.Open / exit code 1
  • iossimulator-x64 / OSX.15.Amd64.Open / exit code 1
  • tvos-arm64 / osx.15.amd64.appletv.open / exit code 1
  • android (multiple architectures) / Windows.11.Amd64.Android.Open / exit code 1

Errors log

From maccatalyst-arm64 Helix work item Microsoft.Extensions.DependencyInjection.Tests (console log):

1) 	[FAIL] Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.CreateCallSite_ReturnsService_IfClosedTypeSatisfiesStructGenericConstraint
   Assembly:  [Microsoft.Extensions.DependencyInjection.Tests, Version=11.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]
   Exception messages: System.ArgumentException : Generic implementation type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ClassWithStructConstraint`1' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1' doesn't.
   Exception stack traces:    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.ValidateTrimmingAnnotations(Type serviceType, Type[] serviceTypeGenericArguments, Type implementationType, Type[] implementationTypeGenericArguments)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.Populate()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.GetCallSiteFactory(ServiceDescriptor[] descriptors)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.CreateCallSite_ReturnsService_IfClosedTypeSatisfiesStructGenericConstraint()
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

2) 	[FAIL] Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.CreateCallSite_Throws_IfClosedTypeDoesNotSatisfyStructGenericConstraint
   Exception messages: System.ArgumentException : Generic implementation type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ClassWithNewConstraint`1' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1' doesn't.

3) 	[FAIL] Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.CreateCallSite_Throws_IfClosedTypeDoesNotSatisfyNewGenericConstraint
   Exception messages: System.ArgumentException : Generic implementation type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ClassWithStructConstraint`1' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1' doesn't.

4) 	[FAIL] Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactoryTest.CreateCallSite_ReturnsService_IfClosedTypeSatisfiesNewGenericConstraint
   Exception messages: System.ArgumentException : Generic implementation type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ClassWithNewConstraint`1' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1' doesn't.

First build it occurred

First observed (within the scanned window) in build 1399212, which finished on 2026-04-28T07:31:50Z (commit 2ac6372).

Note: This window represents the last ~8 days of builds. The true origin may be earlier.

Occurrences in scanned window: Present in mobile library test jobs in the most recent build (multiple test failures in the same assembly).

Recommended action

  1. Area owner: @dotnet/area-extensions-dependencyinjection should investigate why ValidateTrimmingAnnotations in CallSiteFactory is rejecting valid constraint combinations on mobile platforms.

  2. Root cause: The validation logic at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.ValidateTrimmingAnnotations appears to be enforcing exact constraint matching between service interface and implementation type. This is incorrect — implementations are allowed to have stricter (more specific) constraints than their interfaces.

    For example, if IService<T> has no constraints and Service<T> : IService<T> where T : struct, new(), this should be valid. The implementation's constraints are a subset of valid type arguments, which is safe.

  3. Investigation steps:

    • Locate ValidateTrimmingAnnotations in src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs
    • Check if the validation logic differs on mobile platforms (e.g., due to platform-specific compilation symbols or trimming mode)
    • Review recent changes to the constraint validation logic
    • Verify that desktop platforms don't hit this validation (or that they skip it via a different code path)
  4. Expected fix: Update ValidateTrimmingAnnotations to allow implementation types to have constraints that are a superset (more restrictive) of the service type's constraints. The validation should only fail when the implementation's constraints are less restrictive than required by the service interface.

Note

🔒 Integrity filter blocked 3 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #125825 search_issues: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #56828 search_issues: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #29927 search_issues: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by Mobile Platform Failure Scanner · ● 7.6M · ◷

Activity

  1. dotnet-policy-service commented on Apr 29, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
    See info in area-owners.md if you want to be subscribed.

  2. dotnet-policy-service commented on Apr 29, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to 'os-tvos': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
    See info in area-owners.md if you want to be subscribed.

  3. dotnet-policy-service commented on Apr 29, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger
    See info in area-owners.md if you want to be subscribed.

  4. dotnet-policy-service commented on Apr 29, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to 'os-maccatalyst': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
    See info in area-owners.md if you want to be subscribed.

  5. dotnet-policy-service commented on Apr 29, 2026

    @dotnet-policy-service
    Contributor

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

  6. svick commented on Apr 29, 2026

    @svick
    Member

    This looks like a duplicate of #127448.

  7. kotlarmilos commented on Apr 30, 2026

    @kotlarmilos
    Member

    Yes, it is. I created this issue instead to provide better context and clarity.

  8. added this to the Future milestone on May 7, 2026
  9. removed
    untriagedNew issue has not been triaged by the area owner
    on May 7, 2026
  10. kotlarmilos commented on May 13, 2026

    @kotlarmilos
    Member

    Can't find the new failures in the CI, closing it for now. The workflow will create a tracking issue if encountered again

  11. locked and limited conversation to collaborators on Jun 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions