Skip to content

MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])' violates the constraint of type parameter 'T' exception #3988

@Junjun-zhao

Description

@Junjun-zhao

Description: Apps that refer to the AutoMapper package failed to launch against .NET 7 dotnet-sdk-7.0.100-preview.5.22257.3 runtime with exception.

Please refer to more details information from dotnet/runtime#69119

Application Name: nopCommerceNetCore, blazorboilerplate, CastIt, grandnode, BlogSimpleAPI, NorthwindTraders, DevBetterWeb, piranha.core, Boilerplate
OS: Windows 10 RS5
CPU: X64
.NET Build Number: dotnet-sdk-7.0.100-preview.5.22257.3

Findings:

  1. The apps are thrown exception on new methods, like MaxInteger(), MaxtFloat(), which are not exist in previous version:
    finding
  2. The exception is thrown from MethodInfo.MakeGeneric method.
  3. All these apps are using AutoMapper , and when debuging with AutoMapper , we get below exception:
System.ArgumentException
  HResult=0x80070057
  Message=GenericArguments[0], 'Nop.Web.Framework.Models.BaseNopModel', on 'T MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])' violates the constraint of type 'T'.
  Source=System.Private.CoreLib
  StackTrace:
   at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
   at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   at AutoMapper.TypeDetails.<>c__DisplayClass28_1.<BuildPublicNoArgExtensionMethods>b__10(MethodInfo extensionMethod) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\TypeDetails.cs:line 161
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at System.Linq.Enumerable.<SelectManyIterator>d__227`3.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.HashSet`1.UnionWith(IEnumerable`1 other)
   at System.Linq.Enumerable.UnionIterator`1.FillSet()
   at System.Linq.Enumerable.UnionIterator`1.ToArray()
   at AutoMapper.TypeDetails.BuildPublicNoArgExtensionMethods(IEnumerable`1 sourceExtensionMethodSearch) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\TypeDetails.cs:line 148
   at AutoMapper.TypeDetails..ctor(Type type, ProfileMap config) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\TypeDetails.cs:line 34
   at AutoMapper.ProfileMap.TypeDetailsFactory(Type type) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\ProfileMap.cs:line 101
   at AutoMapper.Internal.LockingConcurrentDictionary`2.<>c__DisplayClass2_1.<.ctor>b__1() in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\Internal\LockingConcurrentDictionary.cs:line 15
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at AutoMapper.Internal.LockingConcurrentDictionary`2.GetOrAdd(TKey key) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\Internal\LockingConcurrentDictionary.cs:line 18
   at AutoMapper.ProfileMap.CreateTypeDetails(Type type) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\ProfileMap.cs:line 99
   at AutoMapper.TypeMapFactory.CreateTypeMap(Type sourceType, Type destinationType, ProfileMap options, Boolean isReverseMap) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\TypeMapFactory.cs:line 15
   at AutoMapper.ProfileMap.BuildTypeMap(IConfigurationProvider configurationProvider, ITypeMapConfiguration config) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\ProfileMap.cs:line 130
   at AutoMapper.ProfileMap.Register(IConfigurationProvider configurationProvider) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\ProfileMap.cs:line 107
   at AutoMapper.MapperConfiguration.Seal() in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\MapperConfiguration.cs:line 236
   at AutoMapper.MapperConfiguration..ctor(MapperConfigurationExpression configurationExpression) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\MapperConfiguration.cs:line 50
   at AutoMapper.MapperConfiguration..ctor(Action`1 configure) in F:\AutoMapper-10.1.1\AutoMapper-10.1.1\src\AutoMapper\MapperConfiguration.cs:line 54
   at Nop.Core.Infrastructure.NopEngine.AddAutoMapper() in F:\nopCommerce\src\Libraries\Nop.Core\Infrastructure\NopEngine.cs:line 72
   at Nop.Core.Infrastructure.NopEngine.ConfigureServices(IServiceCollection services, IConfiguration configuration) in F:\nopCommerce\src\Libraries\Nop.Core\Infrastructure\NopEngine.cs:line 127
   at Nop.Web.Framework.Infrastructure.Extensions.ServiceCollectionExtensions.ConfigureApplicationServices(IServiceCollection services, WebApplicationBuilder builder) in F:\nopCommerce\src\Presentation\Nop.Web.Framework\Infrastructure\Extensions\ServiceCollectionExtensions.cs:line 90
   at Program.<Main>$(String[] args) in F:\nopCommerce\src\Presentation\Nop.Web\Program.cs:line 14

  This exception was originally thrown at this call stack:
    System.Reflection.RuntimeMethodInfo.MakeGenericMethod(System.Type[])

Inner Exception 1:
VerificationException: Method System.Linq.Enumerable.MaxInteger: type argument 'Nop.Web.Framework.Models.BaseNopModel' violates the constraint of type parameter 'T'.

Investigation information of Dev:

This is a bug in the application. There are two issues here:

  1. The application is using private reflection to enumerate. The Profile.IncludeSourceExtensionMethods(Type) method is being called with typeof(Enumerable), producing an array of all one-parameter extension methods on Enumerable, including private implementation details of the type. That includes the new private implementation detail Enumerable.MaxFloat/MaxInteger methods added in .NET 7.

  2. The application isn't factoring in generic constraints. There are no public generic methods on Enumerable that have a generic constraint, and the code in TypeDetail.GetPublicNoArgExtenionMethods is, without constraint checks, trying to instantiate these arbitrary extension methods from Enumerable with the arbitrary generic type arguments it retrieved from elsewhere. Without constraints, that's viable. But this private MaxInteger method does have a constraint on the T, which means you can't just substitute any arbitrary value for the T; the type used must meet the constraints. In this case, the AutoMapper method tries to call MakeGenericMethod with a MethodInfo for the private Enumerable.MaxInteger/MaxFloat using types (e.g. Nop.Web.Framework.Models.BaseNopModel) that don't meet the necessary constraints on T, and it throws an exception.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions