private static bool CanCastGenericParameterTo(this GenericParameterDesc thisType, TypeDesc otherType, StackOverflowProtect protect) { // A boxed variable type can be cast to any of its constraints, or object, if none are specified if (otherType.IsObject) { return(true); } if (thisType.HasNotNullableValueTypeConstraint && otherType.IsWellKnownType(WellKnownType.ValueType)) { return(true); } foreach (var typeConstraint in thisType.TypeConstraints) { if (typeConstraint.CanCastToInternal(otherType, protect)) { return(true); } } return(false); }
private static bool CanCastGenericParameterTo(this GenericParameterDesc thisType, TypeDesc otherType, StackOverflowProtect protect) { // A boxed variable type can be cast to any of its constraints, or object, if none are specified if (otherType.IsObject) { return true; } if (thisType.HasNotNullableValueTypeConstraint && otherType.IsWellKnownType(WellKnownType.ValueType)) { return true; } foreach (var typeConstraint in thisType.TypeConstraints) { if (typeConstraint.CanCastToInternal(otherType, protect)) { return true; } } return false; }
public static UInt16 ComputeFlags(TypeDesc type) { UInt16 flags = (UInt16)EETypeKind.CanonicalEEType; if (type.IsInterface) { flags |= (UInt16)EETypeFlags.IsInterfaceFlag; } if (type.IsValueType) { flags |= (UInt16)EETypeFlags.ValueTypeFlag; } if (type.IsGenericDefinition) { flags |= (UInt16)EETypeKind.GenericTypeDefEEType; // Generic type definition EETypes don't set the other flags. return flags; } if (type.IsArray || type.IsPointer) { flags = (UInt16)EETypeKind.ParameterizedEEType; } if (type.HasFinalizer) { flags |= (UInt16)EETypeFlags.HasFinalizerFlag; } if (type.IsDefType && ((DefType)type).ContainsGCPointers) { flags |= (UInt16)EETypeFlags.HasPointersFlag; } else if (type.IsArray) { var elementType = ((ArrayType)type).ElementType; if ((elementType.IsValueType && ((DefType)elementType).ContainsGCPointers) || elementType.IsGCPointer) { flags |= (UInt16)EETypeFlags.HasPointersFlag; } } if (type.HasInstantiation) { flags |= (UInt16)EETypeFlags.IsGenericFlag; if (type.HasVariance) { flags |= (UInt16)EETypeFlags.GenericVarianceFlag; } } CorElementType corElementType = CorElementType.ELEMENT_TYPE_END; // The top 5 bits of flags are used to convey enum underlying type, primitive type, or mark the type as being System.Array if (type.IsEnum) { TypeDesc underlyingType = type.UnderlyingType; Debug.Assert(TypeFlags.SByte <= underlyingType.Category && underlyingType.Category <= TypeFlags.UInt64); corElementType = ComputeRhCorElementType(underlyingType); } else if (type.IsPrimitive) { corElementType = ComputeRhCorElementType(type); } else if (type.IsWellKnownType(WellKnownType.Array)) { // Mark System.Array with CorElementType so casting code can distinguish it corElementType = CorElementType.ELEMENT_TYPE_ARRAY; } if (corElementType != CorElementType.ELEMENT_TYPE_END) { flags |= (UInt16)((UInt16)corElementType << (UInt16)EETypeFlags.CorElementTypeShift); } return flags; }
private void EncodeType(BlobBuilder blobBuilder, TypeDesc type, EmbeddedSignatureDataEmitter signatureDataEmitter) { signatureDataEmitter.Push(); signatureDataEmitter.Push(); signatureDataEmitter.EmitAtCurrentIndexStack(blobBuilder); signatureDataEmitter.Pop(); signatureDataEmitter.Push(); if (type.IsPrimitive) { SignatureTypeCode primitiveCode; switch (type.Category) { case TypeFlags.Void: primitiveCode = SignatureTypeCode.Void; break; case TypeFlags.Boolean: primitiveCode = SignatureTypeCode.Boolean; break; case TypeFlags.Char: primitiveCode = SignatureTypeCode.Char; break; case TypeFlags.SByte: primitiveCode = SignatureTypeCode.SByte; break; case TypeFlags.Byte: primitiveCode = SignatureTypeCode.Byte; break; case TypeFlags.Int16: primitiveCode = SignatureTypeCode.Int16; break; case TypeFlags.UInt16: primitiveCode = SignatureTypeCode.UInt16; break; case TypeFlags.Int32: primitiveCode = SignatureTypeCode.Int32; break; case TypeFlags.UInt32: primitiveCode = SignatureTypeCode.UInt32; break; case TypeFlags.Int64: primitiveCode = SignatureTypeCode.Int64; break; case TypeFlags.UInt64: primitiveCode = SignatureTypeCode.UInt64; break; case TypeFlags.IntPtr: primitiveCode = SignatureTypeCode.IntPtr; break; case TypeFlags.UIntPtr: primitiveCode = SignatureTypeCode.UIntPtr; break; case TypeFlags.Single: primitiveCode = SignatureTypeCode.Single; break; case TypeFlags.Double: primitiveCode = SignatureTypeCode.Double; break; default: throw new Exception("Unknown primitive type"); } blobBuilder.WriteByte((byte)primitiveCode); } else if (type.IsSzArray) { blobBuilder.WriteByte((byte)SignatureTypeCode.SZArray); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsArray) { var arrayType = (ArrayType)type; blobBuilder.WriteByte((byte)SignatureTypeCode.Array); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); signatureDataEmitter.EmitArrayShapeAtCurrentIndexStack(blobBuilder, arrayType.Rank); } else if (type.IsPointer) { blobBuilder.WriteByte((byte)SignatureTypeCode.Pointer); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsFunctionPointer) { FunctionPointerType fnptrType = (FunctionPointerType)type; blobBuilder.WriteByte((byte)SignatureTypeCode.FunctionPointer); EncodeMethodSignature(blobBuilder, fnptrType.Signature, signatureDataEmitter); } else if (type.IsByRef) { blobBuilder.WriteByte((byte)SignatureTypeCode.ByReference); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsObject) { blobBuilder.WriteByte((byte)SignatureTypeCode.Object); } else if (type.IsString) { blobBuilder.WriteByte((byte)SignatureTypeCode.String); } else if (type.IsWellKnownType(WellKnownType.TypedReference)) { blobBuilder.WriteByte((byte)SignatureTypeCode.TypedReference); } else if (type.IsWellKnownType(WellKnownType.Void)) { blobBuilder.WriteByte((byte)SignatureTypeCode.Void); } else if (type is SignatureVariable) { SignatureVariable sigVar = (SignatureVariable)type; SignatureTypeCode code = sigVar.IsMethodSignatureVariable ? SignatureTypeCode.GenericMethodParameter : SignatureTypeCode.GenericTypeParameter; blobBuilder.WriteByte((byte)code); blobBuilder.WriteCompressedInteger(sigVar.Index); } else if (type is InstantiatedType) { blobBuilder.WriteByte((byte)SignatureTypeCode.GenericTypeInstance); EncodeType(blobBuilder, type.GetTypeDefinition(), signatureDataEmitter); blobBuilder.WriteCompressedInteger(type.Instantiation.Length); foreach (var instantiationArg in type.Instantiation) { EncodeType(blobBuilder, instantiationArg, signatureDataEmitter); } } else if (type is MetadataType) { var metadataType = (MetadataType)type; // Must be class or valuetype blobBuilder.WriteByte(type.IsValueType ? (byte)SignatureTypeKind.ValueType : (byte)SignatureTypeKind.Class); int codedIndex = CodedIndex.TypeDefOrRef(GetTypeRef(metadataType)); blobBuilder.WriteCompressedInteger(codedIndex); } else { throw new Exception("Unexpected type"); } signatureDataEmitter.Pop(); signatureDataEmitter.Pop(); }