diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2015-12-17 04:04:17 +0300 |
---|---|---|
committer | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2015-12-17 04:04:17 +0300 |
commit | 6cf6977b884f47d004972910af4a39e07be2df53 (patch) | |
tree | e86e73470f5ae693757796f788c93c651fcaec75 /src/Common | |
parent | db43904251bc7d8c0025534cf7d33ca1ce63a8b6 (diff) | |
parent | 14105d2e03cb38cf10347c4b118a7f69e0cc2056 (diff) |
Merge pull request #539 from MichalStrehovsky/constraintsAndVariance
Add constraints and variance to GenericParameterDesc
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/src/TypeSystem/Common/GenericParameterDesc.cs | 65 | ||||
-rw-r--r-- | src/Common/src/TypeSystem/Ecma/EcmaGenericParameter.cs | 42 |
2 files changed, 99 insertions, 8 deletions
diff --git a/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs b/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs index e159bf692..d388cec81 100644 --- a/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs +++ b/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; +using System.Collections.Generic; + namespace Internal.TypeSystem { public enum GenericParameterKind @@ -9,6 +12,53 @@ namespace Internal.TypeSystem Method, } + /// <summary> + /// Describes the variance on a generic type parameter of a generic type or method. + /// </summary> + public enum GenericVariance + { + None = 0, + + /// <summary> + /// The generic type parameter is covariant. A covariant type parameter can appear + /// as the result type of a method, the type of a read-only field, a declared base + /// type, or an implemented interface. + /// </summary> + Covariant = 1, + + /// <summary> + /// The generic type parameter is contravariant. A contravariant type parameter can + /// appear as a parameter type in method signatures. + /// </summary> + Contravariant = 2 + } + + /// <summary> + /// Describes the constraints on a generic type parameter of a generic type or method. + /// </summary> + [Flags] + public enum GenericConstraints + { + None = 0, + + /// <summary> + /// A type can be substituted for the generic type parameter only if it is a reference type. + /// </summary> + ReferenceTypeConstraint = 0x04, + + /// <summary> + // A type can be substituted for the generic type parameter only if it is a value + // type and is not nullable. + /// </summary> + NotNullableValueTypeConstraint = 0x08, + + /// <summary> + /// A type can be substituted for the generic type parameter only if it has a parameterless + /// constructor. + /// </summary> + DefaultConstructorConstraint = 0x10, + } + public abstract partial class GenericParameterDesc : TypeDesc { /// <summary> @@ -20,5 +70,20 @@ namespace Internal.TypeSystem /// Gets the zero based index of the generic parameter within the declaring type or method. /// </summary> public abstract int Index { get; } + + /// <summary> + /// Gets a value indicating the variance of this generic parameter. + /// </summary> + public abstract GenericVariance Variance { get; } + + /// <summary> + /// Gets a value indicating generic constraints of this generic parameter. + /// </summary> + public abstract GenericConstraints Constraints { get; } + + /// <summary> + /// Gets type constraints imposed on substitutions. + /// </summary> + public abstract IEnumerable<TypeDesc> TypeConstraints { get; } } } diff --git a/src/Common/src/TypeSystem/Ecma/EcmaGenericParameter.cs b/src/Common/src/TypeSystem/Ecma/EcmaGenericParameter.cs index ccd8032c2..7334ca05e 100644 --- a/src/Common/src/TypeSystem/Ecma/EcmaGenericParameter.cs +++ b/src/Common/src/TypeSystem/Ecma/EcmaGenericParameter.cs @@ -2,10 +2,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; using System.Reflection.Metadata; using Internal.NativeFormat; using Debug = System.Diagnostics.Debug; +using GenericParameterAttributes = System.Reflection.GenericParameterAttributes; namespace Internal.TypeSystem.Ecma { @@ -88,24 +90,48 @@ namespace Internal.TypeSystem.Ecma } } -#if CCIGLUE - public TypeDesc DefiningType + public override GenericVariance Variance { get { - var genericParameter = _module.MetadataReader.GetGenericParameter(_handle); - return _module.GetObject(genericParameter.Parent) as TypeDesc; + Debug.Assert((int)GenericVariance.Contravariant == (int)GenericParameterAttributes.Contravariant); + GenericParameter parameter = _module.MetadataReader.GetGenericParameter(_handle); + return (GenericVariance)(parameter.Attributes & GenericParameterAttributes.VarianceMask); } } - public MethodDesc DefiningMethod + public override GenericConstraints Constraints + { + get + { + Debug.Assert((int)GenericConstraints.DefaultConstructorConstraint == (int)GenericParameterAttributes.DefaultConstructorConstraint); + GenericParameter parameter = _module.MetadataReader.GetGenericParameter(_handle); + return (GenericConstraints)(parameter.Attributes & GenericParameterAttributes.SpecialConstraintMask); + } + } + + public override IEnumerable<TypeDesc> TypeConstraints { get { - var genericParameter = _module.MetadataReader.GetGenericParameter(_handle); - return _module.GetObject(genericParameter.Parent) as MethodDesc; + MetadataReader reader = _module.MetadataReader; + + GenericParameter parameter = reader.GetGenericParameter(_handle); + GenericParameterConstraintHandleCollection constraintHandles = parameter.GetConstraints(); + + if (constraintHandles.Count == 0) + return Array.Empty<TypeDesc>(); + + TypeDesc[] constraintTypes = new TypeDesc[constraintHandles.Count]; + + for (int i = 0; i < constraintTypes.Length; i++) + { + GenericParameterConstraint constraint = reader.GetGenericParameterConstraint(constraintHandles[i]); + constraintTypes[i] = _module.GetType(constraint.Type); + }; + + return constraintTypes; } } -#endif } } |