private string BuildArrayTypeString(ArrayTypeSymbol arrayType, out string assemblyNameSuffix) { TypeSymbol elementType = arrayType.ElementType; string typeArgumentsOpt = null; string elementTypeString = elementType.IsArray() ? BuildArrayTypeString((ArrayTypeSymbol)elementType, out assemblyNameSuffix) : BuildTypeString(elementType, out typeArgumentsOpt, out assemblyNameSuffix); PooledStringBuilder pool = PooledStringBuilder.GetInstance(); StringBuilder builder = pool.Builder; builder.Append(elementTypeString); AppendTypeArguments(builder, typeArgumentsOpt); builder.Append(BuildArrayShapeString(arrayType)); return(pool.ToStringAndFree()); }
private string BuildTypeArgumentString(TypeSymbol typeArg) { Debug.Assert(typeArg.Kind != SymbolKind.TypeParameter); //must be a closed type string typeArgumentsOpt = null; string assemblyNameSuffix; string typeArgString = typeArg.IsArray() ? BuildArrayTypeString((ArrayTypeSymbol)typeArg, out assemblyNameSuffix) : BuildTypeString(typeArg, out typeArgumentsOpt, out assemblyNameSuffix); PooledStringBuilder pool = PooledStringBuilder.GetInstance(); StringBuilder builder = pool.Builder; builder.Append("["); builder.Append(typeArgString); AppendTypeArguments(builder, typeArgumentsOpt); builder.Append(assemblyNameSuffix); builder.Append("]"); return(pool.ToStringAndFree()); }
/// <summary> /// Returns qualified name of type (without the full assembly name), with square brackets in place of /// angle brackets and around type arguments. /// Full assembly name of the type is stored in <paramref name="assemblyNameSuffix"/>. /// </summary> private string BuildTypeString(TypeSymbol symbol, out string typeArgumentsOpt, out string assemblyNameSuffix) { Debug.Assert((object)symbol != null); Debug.Assert(!symbol.IsArray()); if (symbol.TypeKind == TypeKind.Dynamic) { return(BuildTypeString(this.compilation.GetSpecialType(SpecialType.System_Object), out typeArgumentsOpt, out assemblyNameSuffix)); } Symbol containing = symbol.ContainingSymbol; Debug.Assert((object)containing != null); if (containing.Kind == SymbolKind.Namespace) { return(BuildNamespaceString((NamespaceSymbol)containing, isContainer: true) + BuildTypeStringHelper(symbol, out typeArgumentsOpt, out assemblyNameSuffix)); } else { Debug.Assert(containing is TypeSymbol); string outerTypeArgumentsOpt; string outerAssemblyNameSuffix; string outer = BuildTypeString((TypeSymbol)containing, out outerTypeArgumentsOpt, out outerAssemblyNameSuffix); string inner = BuildTypeStringHelper(symbol, out typeArgumentsOpt, out assemblyNameSuffix); Debug.Assert(outerAssemblyNameSuffix == assemblyNameSuffix); if (typeArgumentsOpt == null) { typeArgumentsOpt = outerTypeArgumentsOpt; } else if (outerTypeArgumentsOpt != null) { typeArgumentsOpt = outerTypeArgumentsOpt + "," + typeArgumentsOpt; } return(outer + "+" + inner); } }
/// <summary> /// Emits conversion to an object of given type. /// </summary> /// <param name="from">Type of value on top of the evaluation stack.</param> /// <param name="fromHint">Hint in case of multitype value.</param> /// <param name="to">Target type.</param> private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to) { Contract.ThrowIfNull(from); Contract.ThrowIfNull(to); Debug.Assert(to.IsReferenceType); Debug.Assert(to != CoreTypes.PhpAlias); Debug.Assert(!to.IsErrorType(), "Trying to convert to an ErrorType"); // -> IPhpCallable if (to == CoreTypes.IPhpCallable) { EmitConvertToIPhpCallable(from, fromHint); return; } // -> System.Array if (to.IsArray()) { var arrt = (ArrayTypeSymbol)to; if (arrt.IsSZArray) { // byte[] if (arrt.ElementType.SpecialType == SpecialType.System_Byte) { // Template: (PhpString).ToBytes(Context) EmitConvertToPhpString(from, fromHint); // PhpString EmitPhpStringAddr(); this.EmitLoadContext(); // Context EmitCall(ILOpCode.Call, CoreMethods.PhpString.ToBytes_Context) .Expect(to); // ToBytes() return; } throw this.NotImplementedException($"Conversion from {from.Name} to {arrt.ElementType.Name}[] is not implemented."); } throw this.NotImplementedException($"Conversion from {from.Name} to array {to.Name} is not implemented."); } // dereference if (from == CoreTypes.PhpAlias) { // <alias>.Value.AsObject() : object Emit_PhpAlias_GetValueAddr(); from = EmitCall(ILOpCode.Call, CoreMethods.PhpValue.AsObject) .Expect(SpecialType.System_Object); } if (from.IsReferenceType && from.IsOfType(to)) { return; } Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias); switch (from.SpecialType) { case SpecialType.System_Void: case SpecialType.System_Int32: case SpecialType.System_Int64: case SpecialType.System_Boolean: case SpecialType.System_Double: case SpecialType.System_String: // Template: null EmitPop(from); _il.EmitNullConstant(); return; default: Debug.Assert(from != CoreTypes.PhpAlias); if (from.IsValueType) { if (from == CoreTypes.PhpValue) { if (IsClassOnly(fromHint)) { // <STACK>.Object EmitPhpValueAddr(); from = EmitCall(ILOpCode.Call, CoreMethods.PhpValue.Object.Getter) .Expect(SpecialType.System_Object); } else { // Convert.AsObject( <STACK> ) from = EmitCall(ILOpCode.Call, CoreMethods.Operators.AsObject_PhpValue) .Expect(SpecialType.System_Object); } } else { // null EmitPop(from); _il.EmitNullConstant(); return; } } // break; } // Template: (T)object EmitCastClass(from, to); }
// Although III.1.8.1.3 seems to imply that verifier understands variance casts. // It appears that verifier/JIT gets easily confused. // So to not rely on whether that should work or not we will flag potentially // "complicated" casts and make them static casts to ensure we are all on // the same page with what type should be tracked. private static bool IsVarianceCast(TypeSymbol to, TypeSymbol from) { if (to == from) { return false; } if ((object)from == null) { // from unknown type - this could be a variance conversion. return true; } // while technically variance casts, array conversions do not seem to be a problem // unless the element types are converted via variance. if (to.IsArray()) { return IsVarianceCast(((ArrayTypeSymbol)to).ElementType, ((ArrayTypeSymbol)from).ElementType); } return (to.IsDelegateType() && to != from) || (to.IsInterfaceType() && from.IsInterfaceType() && !from.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics.Contains((NamedTypeSymbol)to)); }
public CommonConversion ClassifyConversion(TypeSymbol from, TypeSymbol to, ConversionKind kinds) { if (from == to) { return(IdentityConversion); } // implicit conversions handled by 'EmitConversion': if (to.SpecialType == SpecialType.System_Void) { return(IdentityConversion); } // object cast possible implicitly: if ((kinds & ConversionKind.Reference) == ConversionKind.Reference) { if (from.IsReferenceType && to.IsReferenceType && from.IsOfType(to)) { // (PHP) string, resource, array, alias -> object: NoConversion if (to.SpecialType != SpecialType.System_Object || !IsSpecialReferenceType(from)) { return(ReferenceConversion); } } if (to.SpecialType == SpecialType.System_Object && (from.IsInterfaceType() || (from.IsReferenceType && from.IsTypeParameter()))) { return(ReferenceConversion); } } // resolve conversion operator method: if ((kinds & ConversionKind.Numeric) == ConversionKind.Numeric) { var conv = ClassifyNumericConversion(from, to); if (conv.Exists) { return(conv); } } // strict: if ((kinds & ConversionKind.Strict) == ConversionKind.Strict) { var op = ResolveOperator(from, false, ImplicitConversionOpNames(to), new[] { _compilation.CoreTypes.StrictConvert.Symbol }, target: to); if (op != null) { return(new CommonConversion(true, false, false, false, true, op)); } } // implicit if ((kinds & ConversionKind.Implicit) == ConversionKind.Implicit) { var op = TryWellKnownImplicitConversion(from, to) ?? ResolveOperator(from, false, ImplicitConversionOpNames(to), new[] { to, _compilation.CoreTypes.Convert.Symbol }, target: to); if (op != null) { return(new CommonConversion(true, false, false, false, true, op)); } } // explicit: if ((kinds & ConversionKind.Explicit) == ConversionKind.Explicit) { var op = ResolveOperator(from, false, ExplicitConversionOpNames(to), new[] { to, _compilation.CoreTypes.Convert.Symbol }, target: to); if (op != null) { return(new CommonConversion(true, false, false, false, false, op)); } // explicit reference conversion (reference type -> reference type) else if ( from.IsReferenceType && to.IsReferenceType && !IsSpecialReferenceType(from) && !IsSpecialReferenceType(to) && !from.IsArray() && !to.IsArray()) { return(ExplicitReferenceConversion); } } // return(NoConversion); }
public CommonConversion ClassifyConversion(TypeSymbol from, TypeSymbol to, bool checkimplicit = true, bool checkexplicit = true) { if (from == to) { return(IdentityConversion); } if (from.IsReferenceType && to.IsReferenceType && from.IsOfType(to)) { // (PHP) string, resource, array, alias -> object: NoConversion if (to.SpecialType != SpecialType.System_Object || !IsSpecialReferenceType(from)) { return(ReferenceConversion); } } if (to.SpecialType == SpecialType.System_Object && (from.IsInterfaceType() || (from.IsReferenceType && from.IsTypeParameter()))) { return(ReferenceConversion); } // implicit conversions handled by 'EmitConversion': if (to.SpecialType == SpecialType.System_Void) { return(IdentityConversion); } // resolve conversion operator method: var conv = ClassifyNumericConversion(from, to); if (!conv.Exists) { // TODO: cache result var op = checkimplicit ? TryWellKnownImplicitConversion(from, to) ?? ResolveOperator(from, false, ImplicitConversionOpNames(to), new[] { to, _compilation.CoreTypes.Convert.Symbol }, target: to) : null; if (op != null) { conv = new CommonConversion(true, false, false, false, true, op); } else if (checkexplicit) { op = ResolveOperator(from, false, ExplicitConversionOpNames(to), new[] { to, _compilation.CoreTypes.Convert.Symbol }, target: to); if (op != null) { conv = new CommonConversion(true, false, false, false, false, op); } // explicit reference conversion (reference type -> reference type) else if ( from.IsReferenceType && to.IsReferenceType && !IsSpecialReferenceType(from) && !IsSpecialReferenceType(to) && !from.IsArray() && !to.IsArray()) { conv = ExplicitReferenceConversion; } } } return(conv); }
/// <summary> /// Emits conversion to a class object. /// </summary> /// <param name="from">Type of value on top of the evaluation stack.</param> /// <param name="fromHint">Hint in case of multitype value.</param> /// <param name="to">Target type.</param> private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to) { Contract.ThrowIfNull(from); Contract.ThrowIfNull(to); Debug.Assert(to.IsReferenceType); // TODO: structs other than primitive types Debug.Assert(to != CoreTypes.PhpAlias); // dereference if (from == CoreTypes.PhpAlias) { Emit_PhpAlias_GetValue(); from = CoreTypes.PhpValue; } if (from == to) { return; } Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias); if (to == CoreTypes.IPhpCallable) { // (IPhpCallable) if (!from.IsEqualToOrDerivedFrom(CoreTypes.IPhpCallable)) { if (from.SpecialType == SpecialType.System_String) { EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_String); } else if ( from.SpecialType == SpecialType.System_Int64 || from.SpecialType == SpecialType.System_Boolean || from.SpecialType == SpecialType.System_Double) { throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!"); // TODO: ErrCode } else { EmitConvertToPhpValue(from, fromHint); EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_PhpValue); } } return; } if (to.IsArray()) { var arrt = (ArrayTypeSymbol)to; if (arrt.IsSZArray) { if (arrt.ElementType.SpecialType == SpecialType.System_Byte) { // byte[] // Template: (PhpString).ToBytes(Context) EmitConvertToPhpString(from, fromHint); // PhpString this.EmitLoadContext(); // Context EmitCall(ILOpCode.Call, CoreMethods.PhpString.ToBytes_Context) .Expect(to); // ToBytes() return; } } throw new NotImplementedException($"Conversion from {from.Name} to {to.Name} is not implemented."); } switch (from.SpecialType) { case SpecialType.System_Void: case SpecialType.System_Int32: case SpecialType.System_Int64: case SpecialType.System_Boolean: case SpecialType.System_Double: case SpecialType.System_String: if (to == CoreTypes.Object) { from = EmitConvertToPhpValue(from, fromHint); goto default; } else { throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!"); // TODO: ErrCode } default: if (from == CoreTypes.PhpValue) { if (!fromHint.IsRef && IsClassOnly(fromHint)) { // <value>.Object EmitPhpValueAddr(); from = EmitCall(ILOpCode.Call, CoreMethods.PhpValue.Object.Getter) .Expect(SpecialType.System_Object); } else { // Convert.ToClass( value ) from = EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_PhpValue) .Expect(SpecialType.System_Object); } // (T) EmitCastClass(from, to); return; } if (from == CoreTypes.PhpNumber) { // Object EmitPhpNumberAddr(); EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToClass) .Expect(SpecialType.System_Object); // (T) EmitCastClass(to); return; } else if (from.IsOfType(CoreTypes.PhpArray)) { // (T)PhpArray.ToClass(); EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.PhpArray.ToClass), to); return; } else if (from.IsOfType(CoreTypes.IPhpArray)) { // (T)Convert.ToClass(IPhpArray) EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_IPhpArray), to); return; } else if (from.IsReferenceType) { Debug.Assert(from != CoreTypes.PhpAlias); // (T)obj // let .NET deal with eventual cast error for now EmitCastClass(from, to); return; } throw new NotImplementedException(); } }
internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description) { if (!IsTargetAttribute(description.Namespace, description.Name)) { return(-1); } var ctor = this.AttributeConstructor; // Ensure that the attribute data really has a constructor before comparing the signature. if (ctor is null) { return(-1); } // Lazily loaded System.Type type symbol TypeSymbol?lazySystemType = null; ImmutableArray <ParameterSymbol> parameters = ctor.Parameters; bool foundMatch = false; for (int i = 0; i < description.Signatures.Length; i++) { byte[] targetSignature = description.Signatures[i]; if (targetSignature[0] != (byte)SignatureAttributes.Instance) { continue; } byte parameterCount = targetSignature[1]; if (parameterCount != parameters.Length) { continue; } if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void) { continue; } foundMatch = (targetSignature.Length == 3); int k = 0; for (int j = 3; j < targetSignature.Length; j++) { if (k >= parameters.Length) { break; } TypeSymbol parameterType = parameters[k].Type; SpecialType specType = parameterType.SpecialType; byte targetType = targetSignature[j]; if (targetType == (byte)SignatureTypeCode.TypeHandle) { j++; if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType) { foundMatch = false; break; } var namedType = (NamedTypeSymbol)parameterType; AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[j]]; // Compare name and containing symbol name. Uses HasNameQualifier // extension method to avoid string allocations. if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) || !namedType.HasNameQualifier(targetInfo.Namespace)) { foundMatch = false; break; } targetType = (byte)targetInfo.Underlying; if (parameterType.IsEnumType()) { specType = parameterType.GetEnumUnderlyingType() !.SpecialType; } } else if (parameterType.IsArray()) { specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType; } switch (targetType) { case (byte)SignatureTypeCode.Boolean: foundMatch = specType == SpecialType.System_Boolean; k += 1; break; case (byte)SignatureTypeCode.Char: foundMatch = specType == SpecialType.System_Char; k += 1; break; case (byte)SignatureTypeCode.SByte: foundMatch = specType == SpecialType.System_SByte; k += 1; break; case (byte)SignatureTypeCode.Byte: foundMatch = specType == SpecialType.System_Byte; k += 1; break; case (byte)SignatureTypeCode.Int16: foundMatch = specType == SpecialType.System_Int16; k += 1; break; case (byte)SignatureTypeCode.UInt16: foundMatch = specType == SpecialType.System_UInt16; k += 1; break; case (byte)SignatureTypeCode.Int32: foundMatch = specType == SpecialType.System_Int32; k += 1; break; case (byte)SignatureTypeCode.UInt32: foundMatch = specType == SpecialType.System_UInt32; k += 1; break; case (byte)SignatureTypeCode.Int64: foundMatch = specType == SpecialType.System_Int64; k += 1; break; case (byte)SignatureTypeCode.UInt64: foundMatch = specType == SpecialType.System_UInt64; k += 1; break; case (byte)SignatureTypeCode.Single: foundMatch = specType == SpecialType.System_Single; k += 1; break; case (byte)SignatureTypeCode.Double: foundMatch = specType == SpecialType.System_Double; k += 1; break; case (byte)SignatureTypeCode.String: foundMatch = specType == SpecialType.System_String; k += 1; break; case (byte)SignatureTypeCode.Object: foundMatch = specType == SpecialType.System_Object; k += 1; break; case (byte)SerializationTypeCode.Type: if (lazySystemType is null) { lazySystemType = GetSystemType(targetSymbol); } foundMatch = TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything2); k += 1; break; case (byte)SignatureTypeCode.SZArray: // Skip over and check the next byte foundMatch = parameterType.IsArray(); break; default: return(-1); } if (!foundMatch) { break; } } if (foundMatch) { return(i); } } Debug.Assert(!foundMatch); return(-1); }
private bool UpperBoundArrayInference(TypeSymbol source, TypeSymbol target, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)target != null); // SPEC: * Otherwise, if V is an array type Ve[...] and U is an array // SPEC: type Ue[...] of the same rank, or if V is a one-dimensional array // SPEC: type Ve[] and U is one of IEnumerable<Ue>, ICollection<Ue> or // SPEC: IList<Ue> then // SPEC: * if Ue is known to be a reference type then an upper-bound inference // SPEC: from Ue to Ve is made. // SPEC: * otherwise an exact inference from Ue to Ve is made. if (!target.IsArray()) { return false; } var arrayTarget = (ArrayTypeSymbol)target; var elementTarget = arrayTarget.ElementType; var elementSource = GetMatchingElementType(arrayTarget, source, ref useSiteDiagnostics); if ((object)elementSource == null) { return false; } if (elementSource.IsReferenceType) { UpperBoundInference(elementSource, elementTarget, ref useSiteDiagnostics); } else { ExactInference(elementSource, elementTarget, ref useSiteDiagnostics); } return true; }
private static TypeSymbol GetMatchingElementType(ArrayTypeSymbol source, TypeSymbol target, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)target != null); // It might be an array of same rank. if (target.IsArray()) { var arrayTarget = (ArrayTypeSymbol)target; if (!arrayTarget.HasSameShapeAs(source)) { return null; } return arrayTarget.ElementType; } // Or it might be IEnum<T> and source is rank one. if (!source.IsSZArray) { return null; } // Arrays are specified as being convertible to IEnumerable<T>, ICollection<T> and // IList<T>; we also honor their convertibility to IReadOnlyCollection<T> and // IReadOnlyList<T>, and make inferences accordingly. if (!target.IsPossibleArrayGenericInterface()) { return null; } return ((NamedTypeSymbol)target).TypeArgumentWithDefinitionUseSiteDiagnostics(0, ref useSiteDiagnostics); }
private bool ExactArrayInference(TypeSymbol source, TypeSymbol target, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)target != null); // SPEC: * Otherwise, if U is an array type UE[...] and V is an array type VE[...] // SPEC: of the same rank then an exact inference from UE to VE is made. if (!source.IsArray() || !target.IsArray()) { return false; } var arraySource = (ArrayTypeSymbol)source; var arrayTarget = (ArrayTypeSymbol)target; if (!arraySource.HasSameShapeAs(arrayTarget)) { return false; } ExactInference(arraySource.ElementType, arrayTarget.ElementType, ref useSiteDiagnostics); return true; }
internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description) { if (!IsTargetAttribute(description.Namespace, description.Name)) { return(-1); } var ctor = this.AttributeConstructor; // Ensure that the attribute data really has a constructor before comparing the signature. if (ctor is null) { return(-1); } // Lazily loaded System.Type type symbol TypeSymbol?lazySystemType = null; ImmutableArray <ParameterSymbol> parameters = ctor.Parameters; for (int signatureIndex = 0; signatureIndex < description.Signatures.Length; signatureIndex++) { byte[] targetSignature = description.Signatures[signatureIndex]; if (matches(targetSignature, parameters, ref lazySystemType)) { return(signatureIndex); } } return(-1); bool matches(byte[] targetSignature, ImmutableArray <ParameterSymbol> parameters, ref TypeSymbol?lazySystemType) { if (targetSignature[0] != (byte)SignatureAttributes.Instance) { return(false); } byte parameterCount = targetSignature[1]; if (parameterCount != parameters.Length) { return(false); } if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void) { return(false); } int parameterIndex = 0; for (int signatureByteIndex = 3; signatureByteIndex < targetSignature.Length; signatureByteIndex++) { if (parameterIndex >= parameters.Length) { return(false); } TypeSymbol parameterType = parameters[parameterIndex].Type; SpecialType specType = parameterType.SpecialType; byte targetType = targetSignature[signatureByteIndex]; if (targetType == (byte)SignatureTypeCode.TypeHandle) { signatureByteIndex++; if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType) { return(false); } var namedType = (NamedTypeSymbol)parameterType; AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[signatureByteIndex]]; // Compare name and containing symbol name. Uses HasNameQualifier // extension method to avoid string allocations. if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) || !namedType.HasNameQualifier(targetInfo.Namespace)) { return(false); } targetType = (byte)targetInfo.Underlying; if (parameterType.IsEnumType()) { specType = parameterType.GetEnumUnderlyingType() !.SpecialType; } } else if (targetType != (byte)SignatureTypeCode.SZArray && parameterType.IsArray()) { if (targetSignature[signatureByteIndex - 1] != (byte)SignatureTypeCode.SZArray) { return(false); } specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType; } switch (targetType) { case (byte)SignatureTypeCode.Boolean: if (specType != SpecialType.System_Boolean) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Char: if (specType != SpecialType.System_Char) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.SByte: if (specType != SpecialType.System_SByte) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Byte: if (specType != SpecialType.System_Byte) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Int16: if (specType != SpecialType.System_Int16) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.UInt16: if (specType != SpecialType.System_UInt16) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Int32: if (specType != SpecialType.System_Int32) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.UInt32: if (specType != SpecialType.System_UInt32) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Int64: if (specType != SpecialType.System_Int64) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.UInt64: if (specType != SpecialType.System_UInt64) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Single: if (specType != SpecialType.System_Single) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Double: if (specType != SpecialType.System_Double) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.String: if (specType != SpecialType.System_String) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.Object: if (specType != SpecialType.System_Object) { return(false); } parameterIndex += 1; break; case (byte)SerializationTypeCode.Type: lazySystemType ??= GetSystemType(targetSymbol); if (!TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything)) { return(false); } parameterIndex += 1; break; case (byte)SignatureTypeCode.SZArray: // Skip over and check the next byte if (!parameterType.IsArray()) { return(false); } break; default: return(false); } } return(true); } }
private static bool IsInvariantArray(TypeSymbol type) { return(type.IsArray() && type.GetArrayElementType().TypeSymbol.IsSealed); }
private string BuildTypeArgumentString(TypeSymbol typeArg) { Debug.Assert(typeArg.Kind != SymbolKind.TypeParameter); //must be a closed type string typeArgumentsOpt = null; string assemblyNameSuffix; string typeArgString = typeArg.IsArray() ? BuildArrayTypeString((ArrayTypeSymbol)typeArg, out assemblyNameSuffix) : BuildTypeString(typeArg, out typeArgumentsOpt, out assemblyNameSuffix); PooledStringBuilder pool = PooledStringBuilder.GetInstance(); StringBuilder builder = pool.Builder; builder.Append("["); builder.Append(typeArgString); AppendTypeArguments(builder, typeArgumentsOpt); builder.Append(assemblyNameSuffix); builder.Append("]"); return pool.ToStringAndFree(); }
/// <summary> /// Returns qualified name of type (without the full assembly name), with square brackets in place of /// angle brackets and around type arguments. /// Full assembly name of the type is stored in <paramref name="assemblyNameSuffix"/>. /// </summary> private string BuildTypeString(TypeSymbol symbol, out string typeArgumentsOpt, out string assemblyNameSuffix) { Debug.Assert((object)symbol != null); Debug.Assert(!symbol.IsArray()); if (symbol.TypeKind == TypeKind.DynamicType) { return BuildTypeString(this.compilation.GetSpecialType(SpecialType.System_Object), out typeArgumentsOpt, out assemblyNameSuffix); } Symbol containing = symbol.ContainingSymbol; Debug.Assert((object)containing != null); if (containing.Kind == SymbolKind.Namespace) { return BuildNamespaceString((NamespaceSymbol)containing, isContainer: true) + BuildTypeStringHelper(symbol, out typeArgumentsOpt, out assemblyNameSuffix); } else { Debug.Assert(containing is TypeSymbol); string outerTypeArgumentsOpt; string outerAssemblyNameSuffix; string outer = BuildTypeString((TypeSymbol)containing, out outerTypeArgumentsOpt, out outerAssemblyNameSuffix); string inner = BuildTypeStringHelper(symbol, out typeArgumentsOpt, out assemblyNameSuffix); Debug.Assert(outerAssemblyNameSuffix == assemblyNameSuffix); if (typeArgumentsOpt == null) { typeArgumentsOpt = outerTypeArgumentsOpt; } else if (outerTypeArgumentsOpt != null) { typeArgumentsOpt = outerTypeArgumentsOpt + "," + typeArgumentsOpt; } return outer + "+" + inner; } }