[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:
Samuel Arzt 2017-10-20 21:00:21 +02:00 коммит произвёл Jan Kotas
Родитель d7a8b3aa83
Коммит 6af53ab981
4 изменённых файлов: 133 добавлений и 8 удалений

Просмотреть файл

@ -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>