public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.GetTypeArgument(i); switch (typeArg.Kind) // void, null, and pointers cannot be used as type arguments { case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: ConstraintsValid = false; break; } if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArg)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.DirectBaseTypes) { IType c = constraintType.AcceptVisitor(newParameterizedType.GetSubstitution()); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } } return(newType); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; var substitution = newParameterizedType.GetSubstitution(); for (int i = 0; i < typeParameters.Count; i++) { if (!ValidateConstraints(typeParameters[i], newParameterizedType.GetTypeArgument(i), substitution, conversions)) { ConstraintsValid = false; break; } } } } return(newType); }
AstType ConvertTypeHelper(IType type) { TypeWithElementType typeWithElementType = type as TypeWithElementType; if (typeWithElementType != null) { if (typeWithElementType is PointerType) { return ConvertType(typeWithElementType.ElementType).MakePointerType(); } else if (typeWithElementType is ArrayType) { return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); } else { // e.g. ByReferenceType; not supported as type in C# return ConvertType(typeWithElementType.ElementType); } } ParameterizedType pt = type as ParameterizedType; if (pt != null) { if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { return ConvertType(pt.TypeArguments[0]).MakeNullableType(); } return ConvertTypeHelper(pt.GetDefinition(), pt.TypeArguments); } ITypeDefinition typeDef = type as ITypeDefinition; if (typeDef != null) { if (typeDef.TypeParameterCount > 0) { // Unbound type IType[] typeArguments = new IType[typeDef.TypeParameterCount]; for (int i = 0; i < typeArguments.Length; i++) { typeArguments[i] = SpecialType.UnboundTypeArgument; } return ConvertTypeHelper(typeDef, typeArguments); } else { return ConvertTypeHelper(typeDef, EmptyList<IType>.Instance); } } return new SimpleType(type.Name); }
protected virtual string GetCastCode(Expression expression, AstType astType, string op, out bool isCastAttr) { var resolveResult = this.Emitter.Resolver.ResolveNode(astType, this.Emitter) as TypeResolveResult; isCastAttr = false; if (resolveResult == null) { return(null); } var exprResolveResult = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); string inline = null; bool isOp = op == CS.Ops.IS; var method = isOp ? null : this.GetCastMethod(exprResolveResult.Type, resolveResult.Type, out inline); if (method == null && !isOp && (NullableType.IsNullable(exprResolveResult.Type) || NullableType.IsNullable(resolveResult.Type))) { method = this.GetCastMethod(NullableType.IsNullable(exprResolveResult.Type) ? NullableType.GetUnderlyingType(exprResolveResult.Type) : exprResolveResult.Type, NullableType.IsNullable(resolveResult.Type) ? NullableType.GetUnderlyingType(resolveResult.Type) : resolveResult.Type, out inline); } if (inline != null) { this.InlineMethod = method; return(inline); } IEnumerable <IAttribute> attributes = null; var type = resolveResult.Type.GetDefinition(); if (type != null) { attributes = type.Attributes; } else { ParameterizedType paramType = resolveResult.Type as ParameterizedType; if (paramType != null) { attributes = paramType.GetDefinition().Attributes; } } if (attributes != null) { var attribute = this.Emitter.GetAttribute(attributes, Translator.Bridge_ASSEMBLY + ".CastAttribute"); if (attribute != null) { isCastAttr = true; return(attribute.PositionalArguments[0].ConstantValue.ToString()); } } return(null); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.TypeArguments[i]; if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType(overloadResolution.context) != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (typeArg.IsReferenceType(overloadResolution.context) != false) { ConstraintsValid = false; } if (NullableType.IsNullable(typeArg)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( overloadResolution.context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c); } } } } return(newType); }
public AstType ConvertType(IType type) { if (type == null) { throw new ArgumentNullException("type"); } TypeWithElementType typeWithElementType = type as TypeWithElementType; if (typeWithElementType != null) { if (typeWithElementType is PointerType) { return(ConvertType(typeWithElementType.ElementType).MakePointerType()); } else if (typeWithElementType is ArrayType) { return(ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions)); } else { // e.g. ByReferenceType; not supported as type in C# return(ConvertType(typeWithElementType.ElementType)); } } ParameterizedType pt = type as ParameterizedType; if (pt != null) { if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { return(ConvertType(pt.TypeArguments[0]).MakeNullableType()); } return(ConvertTypeDefinition(pt.GetDefinition(), pt.TypeArguments)); } ITypeDefinition typeDef = type as ITypeDefinition; if (typeDef != null) { if (typeDef.TypeParameterCount > 0) { // Create an unbound type IType[] typeArguments = new IType[typeDef.TypeParameterCount]; for (int i = 0; i < typeArguments.Length; i++) { typeArguments[i] = SharedTypes.UnknownType; } return(ConvertTypeDefinition(typeDef, typeArguments)); } else { return(ConvertTypeDefinition(typeDef, EmptyList <IType> .Instance)); } } return(new SimpleType(type.Name)); }
/// <summary> /// Make exact inference from U to V. /// C# 4.0 spec: §7.5.2.8 Exact inferences /// </summary> void MakeExactInference(IType U, IType V) { Log.WriteLine("MakeExactInference from " + U + " to " + V); // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. TP tp = GetTPForType(V); if (tp != null && tp.IsFixed == false) { Log.WriteLine(" Add exact bound '" + U + "' to " + tp); tp.LowerBounds.Add(U); tp.UpperBounds.Add(U); return; } // Handle by reference types: ByReferenceType brU = U as ByReferenceType; ByReferenceType brV = V as ByReferenceType; if (brU != null && brV != null) { MakeExactInference(brU.ElementType, brV.ElementType); return; } // Handle array types: ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { MakeExactInference(arrU.ElementType, arrV.ElementType); return; } // Handle parameterized type: ParameterizedType pU = U as ParameterizedType; ParameterizedType pV = V as ParameterizedType; if (pU != null && pV != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { Log.Indent(); for (int i = 0; i < pU.TypeParameterCount; i++) { MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i)); } Log.Unindent(); } }
static bool IsIEnumerableCollectionOrList(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) { return(false); } switch (rt.GetDefinition().FullName) { case "System.Collections.Generic.IList": case "System.Collections.Generic.ICollection": case "System.Collections.Generic.IEnumerable": return(true); default: return(false); } }
static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) { return(false); } switch (rt.GetDefinition().FullName) { case "System.Collections.Generic.IEnumerable": case "System.Collections.Generic.ICollection": case "System.Collections.Generic.IList": case "System.Collections.Generic.IReadOnlyList": return(true); default: return(false); } }
static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) { return(false); } switch (rt.GetDefinition().KnownTypeCode) { case KnownTypeCode.IEnumerableOfT: case KnownTypeCode.ICollectionOfT: case KnownTypeCode.IListOfT: case KnownTypeCode.IReadOnlyCollectionOfT: case KnownTypeCode.IReadOnlyListOfT: return(true); default: return(false); } }
/// <summary> /// Make upper bound inference from U to V. /// C# 4.0 spec: §7.5.2.10 Upper-bound inferences /// </summary> void MakeUpperBoundInference(IType U, IType V) { Log.WriteLine(" MakeUpperBoundInference from " + U + " to " + V); // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. TP tp = GetTPForType(V); if (tp != null && tp.IsFixed == false) { Log.WriteLine(" Add upper bound '" + U + "' to " + tp); tp.UpperBounds.Add(U); return; } // Handle array types: ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; ParameterizedType pU = U as ParameterizedType; if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) { MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); return; } else if (arrV != null && IsGenericInterfaceImplementedByArray(pU) && arrV.Dimensions == 1) { MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType); return; } // Handle parameterized types: if (pU != null) { ParameterizedType uniqueBaseType = null; foreach (IType baseV in V.GetAllBaseTypes()) { ParameterizedType pV = baseV as ParameterizedType; if (pV != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { if (uniqueBaseType == null) { uniqueBaseType = pV; } else { return; // cannot make an inference because it's not unique } } } Log.Indent(); if (uniqueBaseType != null) { for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { IType Ui = pU.GetTypeArgument(i); IType Vi = uniqueBaseType.GetTypeArgument(i); if (Ui.IsReferenceType == true) { // look for variance ITypeParameter Xi = pU.GetDefinition().TypeParameters[i]; switch (Xi.Variance) { case VarianceModifier.Covariant: MakeUpperBoundInference(Ui, Vi); break; case VarianceModifier.Contravariant: MakeLowerBoundInference(Ui, Vi); break; default: // invariant MakeExactInference(Ui, Vi); break; } } else { // not known to be a reference type MakeExactInference(Ui, Vi); } } } Log.Unindent(); } }
static IEnumerable <IType> ExpandIntersections(IType type) { IntersectionType it = type as IntersectionType; if (it != null) { return(it.Types.SelectMany(t => ExpandIntersections(t))); } ParameterizedType pt = type as ParameterizedType; if (pt != null) { IType[][] typeArguments = new IType[pt.TypeArguments.Count][]; for (int i = 0; i < typeArguments.Length; i++) { typeArguments[i] = ExpandIntersections(pt.TypeArguments[i]).ToArray(); } return(AllCombinations(typeArguments).Select(ta => new ParameterizedType(pt.GetDefinition(), ta))); } return(new [] { type }); }
protected virtual string GetCastCode(Expression expression, AstType astType, out bool isInline) { var resolveResult = this.Emitter.Resolver.ResolveNode(astType, this.Emitter) as TypeResolveResult; var exprResolveResult = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); string inline = null; isInline = false; var method = exprResolveResult.Type.GetMethods().FirstOrDefault(m => { if (m.IsOperator && m.Name == "op_Explicit" && m.Parameters.Count == 1 && m.ReturnType.ReflectionName == resolveResult.Type.ReflectionName && m.Parameters[0].Type.ReflectionName == exprResolveResult.Type.ReflectionName ) { string tmpInline = this.Emitter.GetInline(m); if (!string.IsNullOrWhiteSpace(tmpInline)) { inline = tmpInline; return(true); } } return(false); }); if (inline != null) { isInline = true; return(inline); } if (resolveResult != null) { IEnumerable <IAttribute> attributes = null; DefaultResolvedTypeDefinition type = resolveResult.Type as DefaultResolvedTypeDefinition; if (type != null) { attributes = type.Attributes; } else { ParameterizedType paramType = resolveResult.Type as ParameterizedType; if (paramType != null) { attributes = paramType.GetDefinition().Attributes; } } if (attributes != null) { var attribute = this.Emitter.GetAttribute(attributes, Translator.Bridge_ASSEMBLY + ".CastAttribute"); if (attribute != null) { return(attribute.PositionalArguments[0].ConstantValue.ToString()); } } } return(null); }