[ILVerify] Instantiate generic constraints on initialization (#4758)
* Implemented InstantiatedGenericParameter in order to be able to correctly cast constraints with generic parameter instantiations. * Added test case for casting constrained generic with generic parameter inside constraint. * Changed InstantiatedGenericParameter to be able to handle complex generic constraints. * Added GetInstantiatedGenericParameter to TypeSystemContext. * Changed generic type / method instantation to be created by InstantiatedGenericParameter.
This commit is contained in:
Родитель
d7a8b3aa83
Коммит
6af53ab981
|
@ -40,7 +40,6 @@ namespace Internal.IL
|
|||
readonly MethodDesc _method;
|
||||
readonly MethodSignature _methodSignature;
|
||||
readonly TypeSystemContext _typeSystemContext;
|
||||
readonly InstantiationContext _instantiationContext;
|
||||
|
||||
readonly TypeDesc _thisType;
|
||||
|
||||
|
@ -154,16 +153,21 @@ namespace Internal.IL
|
|||
var instantiatedMethod = method;
|
||||
if (instantiatedType.HasInstantiation)
|
||||
{
|
||||
instantiatedType = _typeSystemContext.GetInstantiatedType((MetadataType)instantiatedType, instantiatedType.Instantiation);
|
||||
Instantiation genericTypeInstantiation = InstantiatedGenericParameter.CreateGenericTypeInstantiaton(instantiatedType.Instantiation);
|
||||
instantiatedType = _typeSystemContext.GetInstantiatedType((MetadataType)instantiatedType, genericTypeInstantiation);
|
||||
instantiatedMethod = _typeSystemContext.GetMethodForInstantiatedType(instantiatedMethod.GetTypicalMethodDefinition(), (InstantiatedType)instantiatedType);
|
||||
}
|
||||
|
||||
if (instantiatedMethod.HasInstantiation)
|
||||
instantiatedMethod = _typeSystemContext.GetInstantiatedMethod(instantiatedMethod, instantiatedMethod.Instantiation);
|
||||
{
|
||||
Instantiation genericMethodInstantiation = InstantiatedGenericParameter.CreateGenericMethodInstantiation(
|
||||
instantiatedType.Instantiation, instantiatedMethod.Instantiation);
|
||||
instantiatedMethod = _typeSystemContext.GetInstantiatedMethod(instantiatedMethod, genericMethodInstantiation);
|
||||
}
|
||||
_method = instantiatedMethod;
|
||||
|
||||
_methodSignature = _method.Signature;
|
||||
_methodIL = method == instantiatedMethod ? methodIL : new InstantiatedMethodIL(instantiatedMethod, methodIL);
|
||||
_instantiationContext = new InstantiationContext(instantiatedType.Instantiation, instantiatedMethod.Instantiation);
|
||||
|
||||
// Determine this type
|
||||
if (!_method.Signature.IsStatic)
|
||||
|
@ -1293,9 +1297,9 @@ again:
|
|||
}
|
||||
|
||||
// Check any constraints on the callee's class and type parameters
|
||||
if (!method.OwningType.CheckConstraints(_instantiationContext))
|
||||
if (!method.OwningType.CheckConstraints())
|
||||
VerificationError(VerifierError.UnsatisfiedMethodParentInst, method.OwningType);
|
||||
else if (!method.CheckConstraints(_instantiationContext))
|
||||
else if (!method.CheckConstraints())
|
||||
VerificationError(VerifierError.UnsatisfiedMethodInst, method);
|
||||
|
||||
Check(_method.OwningType.CanAccess(method, instance), VerifierError.MethodAccess);
|
||||
|
@ -1404,9 +1408,9 @@ again:
|
|||
}
|
||||
|
||||
// Check any constraints on the callee's class and type parameters
|
||||
if (!method.OwningType.CheckConstraints(_instantiationContext))
|
||||
if (!method.OwningType.CheckConstraints())
|
||||
VerificationError(VerifierError.UnsatisfiedMethodParentInst, method.OwningType);
|
||||
else if (!method.CheckConstraints(_instantiationContext))
|
||||
else if (!method.CheckConstraints())
|
||||
VerificationError(VerifierError.UnsatisfiedMethodInst, method);
|
||||
|
||||
Check(_method.OwningType.CanAccess(method, instance), VerifierError.MethodAccess);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<Compile Include="SimpleTypeSystemContext.cs" />
|
||||
<Compile Include="VerifierError.cs" />
|
||||
<Compile Include="TypeSystemHelpers.cs" />
|
||||
<Compile Include="InstantiatedGenericParameter.cs" />
|
||||
<Compile Include="AccessVerificationHelpers.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Internal.TypeSystem
|
||||
{
|
||||
internal sealed partial class InstantiatedGenericParameter : GenericParameterDesc
|
||||
{
|
||||
private readonly GenericParameterDesc _genericParam;
|
||||
private Instantiation _typeInstantiation;
|
||||
private Instantiation _methodInstantiation;
|
||||
|
||||
public GenericParameterDesc GenericParameter
|
||||
{
|
||||
get
|
||||
{
|
||||
return _genericParam;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Instantiation CreateGenericTypeInstantiaton(Instantiation instantiation)
|
||||
{
|
||||
if (instantiation.Length == 0)
|
||||
return instantiation;
|
||||
|
||||
var genericInstantiation = CreateGenericInstantiation(instantiation);
|
||||
|
||||
foreach (var parameter in genericInstantiation)
|
||||
((InstantiatedGenericParameter)parameter)._typeInstantiation = genericInstantiation;
|
||||
|
||||
return genericInstantiation;
|
||||
}
|
||||
|
||||
internal static Instantiation CreateGenericMethodInstantiation(Instantiation typeInstantiation, Instantiation methodInstantiation)
|
||||
{
|
||||
if (methodInstantiation.Length == 0)
|
||||
return methodInstantiation;
|
||||
|
||||
var genericInstantiation = CreateGenericInstantiation(methodInstantiation);
|
||||
|
||||
foreach (var parameter in genericInstantiation)
|
||||
{
|
||||
var par = (InstantiatedGenericParameter)parameter;
|
||||
par._typeInstantiation = typeInstantiation;
|
||||
par._methodInstantiation = genericInstantiation;
|
||||
}
|
||||
|
||||
return genericInstantiation;
|
||||
}
|
||||
|
||||
private static Instantiation CreateGenericInstantiation(Instantiation fromInstantiation)
|
||||
{
|
||||
var parameters = new TypeDesc[fromInstantiation.Length];
|
||||
for (int i = 0; i < fromInstantiation.Length; ++i)
|
||||
parameters[i] = new InstantiatedGenericParameter((GenericParameterDesc)fromInstantiation[i]);
|
||||
|
||||
return new Instantiation(parameters);
|
||||
}
|
||||
|
||||
private InstantiatedGenericParameter(GenericParameterDesc genericParam)
|
||||
{
|
||||
Debug.Assert(!(genericParam is InstantiatedGenericParameter));
|
||||
_genericParam = genericParam;
|
||||
}
|
||||
|
||||
public override GenericParameterKind Kind => _genericParam.Kind;
|
||||
|
||||
public override int Index => _genericParam.Index;
|
||||
|
||||
public override TypeSystemContext Context => _genericParam.Context;
|
||||
|
||||
public override GenericVariance Variance => _genericParam.Variance;
|
||||
|
||||
public override GenericConstraints Constraints => _genericParam.Constraints;
|
||||
|
||||
public override IEnumerable<TypeDesc> TypeConstraints
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var constraint in _genericParam.TypeConstraints)
|
||||
{
|
||||
yield return constraint.InstantiateSignature(_typeInstantiation, _methodInstantiation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _genericParam.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,30 @@
|
|||
stloc.0
|
||||
ret
|
||||
}
|
||||
|
||||
.method static public hidebysig void Assign.ConstrainedGenericToComparable_Valid<(class [System.Runtime]System.IComparable`1<!!T>) T>(!!T t)
|
||||
{
|
||||
.locals init (
|
||||
class [System.Runtime]System.IComparable`1<!!T> c
|
||||
)
|
||||
|
||||
ldarg.0
|
||||
box !!T
|
||||
stloc.0
|
||||
ret
|
||||
}
|
||||
|
||||
.method static public hidebysig void Assign.ComplexConstrainedGenericToComparable_Valid<(!!S) T, (class [System.Runtime]System.IComparable`1<!!T>) S>(!!T t)
|
||||
{
|
||||
.locals init (
|
||||
class [System.Runtime]System.IComparable`1<!!T> c
|
||||
)
|
||||
|
||||
ldarg.0
|
||||
box !!T
|
||||
stloc.0
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
.class public sequential ansi sealed beforefieldinit GenericOtherFieldsType`1<T>
|
||||
|
|
Загрузка…
Ссылка в новой задаче