/// <summary> /// Gets whether 'type' is the same as 'typeDef' parameterized with the given type arguments. /// </summary> bool TypeMatches(IType type, ITypeDefinition typeDef, IList<IType> typeArguments) { if (typeDef.TypeParameterCount == 0) { return typeDef.Equals(type); } else { if (!typeDef.Equals(type.GetDefinition())) return false; ParameterizedType pt = type as ParameterizedType; if (pt == null) { return typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument); } var ta = pt.TypeArguments; for (int i = 0; i < ta.Count; i++) { if (!ta[i].Equals(typeArguments[i])) return false; } return true; } }
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); } }
IEnumerable <CodeAction> GetActionsForAddNamespaceUsing(RefactoringContext context, AstNode node) { var nrr = context.Resolve(node) as NamespaceResolveResult; if (nrr == null) { return(EmptyList <CodeAction> .Instance); } var trr = context.Resolve(node.Parent) as TypeResolveResult; if (trr == null) { return(EmptyList <CodeAction> .Instance); } ITypeDefinition typeDef = trr.Type.GetDefinition(); if (typeDef == null) { return(EmptyList <CodeAction> .Instance); } IList <IType> typeArguments; ParameterizedType parameterizedType = trr.Type as ParameterizedType; if (parameterizedType != null) { typeArguments = parameterizedType.TypeArguments; } else { typeArguments = EmptyList <IType> .Instance; } var resolver = context.GetResolverStateBefore(node.Parent); if (resolver.ResolveSimpleName(typeDef.Name, typeArguments) is UnknownIdentifierResolveResult) { // It's possible to remove the explicit namespace usage and introduce a using instead return(new[] { NewUsingAction(context, node, typeDef.Namespace) }); } return(EmptyList <CodeAction> .Instance); }
static ICorDebugType ConvertTypeDefOrParameterizedType(IType type, out AppDomain appDomain) { ITypeDefinition typeDef = type.GetDefinition(); appDomain = GetAppDomain(typeDef.Compilation); var info = GetInfo(typeDef.ParentAssembly); uint token = info.GetMetadataToken(typeDef.Parts[0]); ICorDebugClass corClass = info.Module.CorModule.GetClassFromToken(token); List <ICorDebugType> corGenArgs = new List <ICorDebugType>(); ParameterizedType pt = type as ParameterizedType; if (pt != null) { foreach (var typeArg in pt.TypeArguments) { corGenArgs.Add(typeArg.ToCorDebug()); } } return(((ICorDebugClass2)corClass).GetParameterizedType((uint)(type.IsReferenceType == false ? CorElementType.VALUETYPE : CorElementType.CLASS), corGenArgs.ToArray())); }
ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList <IType> typeArguments) { if (typeArguments.Count > 0) { // parameterize the type if necessary ITypeDefinition returnedTypeDef = returnedType as ITypeDefinition; if (returnedTypeDef != null) { returnedType = new ParameterizedType(returnedTypeDef, typeArguments); } } if (isAmbiguous) { return(new AmbiguousTypeResolveResult(returnedType)); } else { return(new TypeResolveResult(returnedType)); } }
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; }
public void EnumerableToArrayInContravariantType() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition enumerableType = compilation.FindType(typeof(IEnumerable <>)).GetDefinition(); ITypeDefinition comparerType = compilation.FindType(typeof(IComparer <>)).GetDefinition(); var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType }) }); var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(compilation, tp) }); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(comparerOfIEnumerableOfString) }, new [] { comparerOfTpArray }, out success)); Assert.IsTrue(success); }
public void QueryableGroup() { string program = @"using System; using System.Linq; class TestClass { void Test(IQueryable<string> input) { var r = from e in input group e.ToUpper() by e.Length; $r$.ToString(); } } "; LocalResolveResult lrr = Resolve <LocalResolveResult>(program); Assert.AreEqual("System.Linq.IQueryable", lrr.Type.FullName); ParameterizedType rt = (ParameterizedType)((ParameterizedType)lrr.Type).TypeArguments[0]; Assert.AreEqual("System.Linq.IGrouping", rt.FullName); Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullName); Assert.AreEqual("System.String", rt.TypeArguments[1].FullName); }
static IEnumerable <IMethod> GetMethodsImpl(IType baseType, IList <IType> methodTypeArguments, Predicate <IUnresolvedMethod> filter, GetMemberOptions options) { IEnumerable <IMethod> declaredMethods = baseType.GetMethods(filter, options | declaredMembers); ParameterizedType pt = baseType as ParameterizedType; if ((options & GetMemberOptions.ReturnMemberDefinitions) == 0 && (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0))) { TypeParameterSubstitution substitution = null; foreach (IMethod m in declaredMethods) { if (methodTypeArguments != null && methodTypeArguments.Count > 0) { if (m.TypeParameters.Count != methodTypeArguments.Count) { continue; } } if (substitution == null) { if (pt != null) { substitution = pt.GetSubstitution(methodTypeArguments); } else { substitution = new TypeParameterSubstitution(null, methodTypeArguments); } } yield return(new SpecializedMethod(m, substitution)); } } else { foreach (IMethod m in declaredMethods) { yield return(m); } } }
static IEnumerable <IEvent> GetEventsImpl(IType baseType, ITypeResolveContext context, Predicate <IEvent> filter, GetMemberOptions options) { IEnumerable <IEvent> declaredEvents = baseType.GetEvents(context, filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return(declaredEvents); } ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); return(declaredEvents.Select(m => new SpecializedEvent(pt, m, substitution, context))); } else { return(declaredEvents); } }
/// <summary> /// Finds IList<T> or IEnumerable<T> base type. /// </summary> /// <param name="fullNamePrefix">Type code to search for (IList<T> or IEnumerable<T>)</param></param> /// <param name="implementation">Found implementation.</param> /// <param name="itemType">The only generic argument of <paramref name="implementation"/></param> /// <returns>True if found, false otherwise.</returns> private static bool ResolveKnownBaseType(this IType type, KnownTypeCode knownTypeCode, out ParameterizedType implementation, out IType itemType) { if (type == null) { throw new ArgumentNullException("type"); } implementation = null; itemType = null; ParameterizedType impl = type.GetAllBaseTypes().OfType <ParameterizedType>(). Where(t => t.IsKnownType(knownTypeCode) && t.TypeParameterCount == 1) .FirstOrDefault(); if (impl != null) { implementation = impl; itemType = impl.GetTypeArgument(0); return(true); } return(false); }
static int MoreSpecificFormalParameter(IType t1, IType t2) { if ((t1 is ITypeParameter) && !(t2 is ITypeParameter)) return 2; if ((t2 is ITypeParameter) && !(t1 is ITypeParameter)) return 1; ParameterizedType p1 = t1 as ParameterizedType; ParameterizedType p2 = t2 as ParameterizedType; if (p1 != null && p2 != null && p1.TypeParameterCount == p2.TypeParameterCount) { int r = MoreSpecificFormalParameters(p1.TypeArguments, p2.TypeArguments); if (r > 0) return r; } TypeWithElementType tew1 = t1 as TypeWithElementType; TypeWithElementType tew2 = t2 as TypeWithElementType; if (tew1 != null && tew2 != null) { return MoreSpecificFormalParameter(tew1.ElementType, tew2.ElementType); } return 0; }
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 }); }
static IEnumerable <IField> GetFieldsImpl(IType baseType, Predicate <IUnresolvedField> filter, GetMemberOptions options) { IEnumerable <IField> declaredFields = baseType.GetFields(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return(declaredFields); } ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); return(declaredFields.Select(m => new SpecializedField(pt, m, substitution))); } else { return(declaredFields); } }
static Value ConvertTypeDefOrParameterizedType(Thread evalThread, IType type) { var definition = type.GetDefinition(); if (definition == null) { throw new GetValueException("Cannot find type '{0}'", type.FullName); } var foundType = InvokeGetType(evalThread, new AssemblyQualifiedTypeName(definition)); ParameterizedType pt = type as ParameterizedType; if (pt != null) { var typeParams = new List <Value>(); foreach (var typeArg in pt.TypeArguments) { typeParams.Add(TypeOf(evalThread, typeArg)); } return(InvokeMakeGenericType(evalThread, foundType, typeParams.ToArray())); } return(foundType); }
static IEnumerable <IMethod> GetConstructorsOrAccessorsImpl(IType baseType, IEnumerable <IMethod> declaredMembers, Predicate <IUnresolvedMethod> filter, GetMemberOptions options) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return(declaredMembers); } ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); return(declaredMembers.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt })); } else { return(declaredMembers); } }
bool ImplicitReferenceConversion(IType fromType, IType toType, int subtypeCheckNestingDepth) { // C# 4.0 spec: §6.1.6 // reference conversions are possible only if both types are known to be reference types if (!(fromType.IsReferenceType == true && toType.IsReferenceType == true)) { return(false); } ArrayType fromArray = fromType as ArrayType; if (fromArray != null) { ArrayType toArray = toType as ArrayType; if (toArray != null) { // array covariance (the broken kind) return(fromArray.Dimensions == toArray.Dimensions && ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType, subtypeCheckNestingDepth)); } // conversion from single-dimensional array S[] to IList<T>: ParameterizedType toPT = toType as ParameterizedType; if (fromArray.Dimensions == 1 && toPT != null && toPT.TypeParameterCount == 1 && toPT.Namespace == "System.Collections.Generic" && (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable" || toPT.Name == "IReadOnlyList")) { // array covariance plays a part here as well (string[] is IList<object>) return(IdentityConversion(fromArray.ElementType, toPT.GetTypeArgument(0)) || ImplicitReferenceConversion(fromArray.ElementType, toPT.GetTypeArgument(0), subtypeCheckNestingDepth)); } // conversion from any array to System.Array and the interfaces it implements: IType systemArray = compilation.FindType(KnownTypeCode.Array); return(systemArray.Kind != TypeKind.Unknown && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType, subtypeCheckNestingDepth))); } // now comes the hard part: traverse the inheritance chain and figure out generics+variance return(IsSubtypeOf(fromType, toType, subtypeCheckNestingDepth)); }
public void IEnumerableCovarianceWithDynamic() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); var ienumerableOfT = new ParameterizedType(compilation.FindType(typeof(IEnumerable <>)).GetDefinition(), new[] { tp }); var ienumerableOfString = compilation.FindType(typeof(IEnumerable <string>)); var ienumerableOfDynamic = compilation.FindType(typeof(IEnumerable <ReflectionHelper.Dynamic>)); // static T M<T>(IEnumerable<T> x, IEnumerable<T> y) {} // M(IEnumerable<dynamic>, IEnumerable<string>); -> should infer T=dynamic, no ambiguity // See http://blogs.msdn.com/b/cburrows/archive/2010/04/01/errata-dynamic-conversions-and-overload-resolution.aspx // for details. bool success; Assert.AreEqual( new [] { SpecialType.Dynamic }, ti.InferTypeArguments( new [] { tp }, new [] { new ResolveResult(ienumerableOfDynamic), new ResolveResult(ienumerableOfString) }, new [] { ienumerableOfT, ienumerableOfT }, out success)); Assert.IsTrue(success); }
public void ExpansiveInheritance() { SimpleProjectContent pc = new SimpleProjectContent(); DefaultTypeDefinition a = new DefaultTypeDefinition(pc, string.Empty, "A"); DefaultTypeDefinition b = new DefaultTypeDefinition(pc, string.Empty, "B"); // interface A<in U> a.Kind = TypeKind.Interface; a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); // interface B<X> : A<A<B<X>>> { } DefaultTypeParameter x = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X"); b.TypeParameters.Add(x); b.BaseTypes.Add(new ParameterizedType(a, new[] { new ParameterizedType(a, new [] { new ParameterizedType(b, new [] { x }) }) })); IType type1 = new ParameterizedType(b, new[] { KnownTypeReference.Double.Resolve(ctx) }); IType type2 = new ParameterizedType(a, new [] { new ParameterizedType(b, new[] { KnownTypeReference.String.Resolve(ctx) }) }); Assert.IsFalse(conversions.ImplicitConversion(type1, type2)); }
static IEnumerable <IProperty> GetPropertiesImpl(IType baseType, Predicate <IUnresolvedProperty> filter, GetMemberOptions options) { IEnumerable <IProperty> declaredProperties = baseType.GetProperties(filter, options | declaredMembers); if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { return(declaredProperties); } ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); return(declaredProperties.Select(m => new SpecializedProperty(m, substitution) { DeclaringType = pt })); } else { return(declaredProperties); } }
public static IL.ILInstruction CreateTuple(ICompilation compilation, params IL.ILInstruction[] nodes) { var restTuple = typeof(ValueTuple <, , , , , , ,>); Debug.Assert(restTuple.GetGenericArguments().Last().Name == "TRest"); var maxSize = restTuple.GetGenericArguments().Length; if (nodes.Length >= maxSize) { return(makeTuple(nodes.Take(maxSize - 1).Append(CreateTuple(compilation, nodes.Skip(maxSize - 1).ToArray())).ToArray())); } else { return(makeTuple(nodes)); } IL.ILInstruction makeTuple(IL.ILInstruction[] n) { var t = //n.Length == 0 ? typeof(ValueTuple) : n.Length == 1 ? typeof(ValueTuple <>) : n.Length == 2 ? typeof(ValueTuple <,>) : n.Length == 3 ? typeof(ValueTuple <, ,>) : n.Length == 4 ? typeof(ValueTuple <, , ,>) : n.Length == 5 ? typeof(ValueTuple <, , , ,>) : n.Length == 6 ? typeof(ValueTuple <, , , , ,>) : n.Length == 7 ? typeof(ValueTuple <, , , , , ,>) : n.Length == 8 ? typeof(ValueTuple <, , , , , , ,>) : throw new NotSupportedException($"ValueTuple can not have {n.Length} parameters"); var tt = new ParameterizedType(compilation.FindType(t), n.Select(a => a.GetObjectResultType())); var ctor = tt.GetConstructors().Single(c => c.Parameters.Count == n.Length); var result = new IL.NewObj(ctor); result.Arguments.AddRange(n); return(result); } }
/// <summary> /// Build an output mapper for the return type of a given method. /// </summary> /// <param name="method"> the procedure method </param> /// <returns> an output mapper for the return type of the method. </returns> /// <exception cref="ProcedureException"> </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public OutputMapper mapper(Method method) throws org.neo4j.internal.kernel.api.exceptions.ProcedureException public virtual OutputMapper Mapper(System.Reflection.MethodInfo method) { Type cls = method.ReturnType; if (cls == typeof(Void) || cls == typeof(void)) { return(OutputMappers.VOID_MAPPER); } if (cls != typeof(Stream)) { throw InvalidReturnType(cls); } Type genericReturnType = method.GenericReturnType; if (!(genericReturnType is ParameterizedType)) { throw new ProcedureException(Org.Neo4j.Kernel.Api.Exceptions.Status_Procedure.TypeError, "Procedures must return a Stream of records, where a record is a concrete class%n" + "that you define and not a raw Stream."); } ParameterizedType genType = ( ParameterizedType )genericReturnType; Type recordType = genType.ActualTypeArguments[0]; if (recordType is WildcardType) { throw new ProcedureException(Org.Neo4j.Kernel.Api.Exceptions.Status_Procedure.TypeError, "Procedures must return a Stream of records, where a record is a concrete class%n" + "that you define and not a Stream<?>."); } if (recordType is ParameterizedType) { ParameterizedType type = ( ParameterizedType )recordType; throw new ProcedureException(Org.Neo4j.Kernel.Api.Exceptions.Status_Procedure.TypeError, "Procedures must return a Stream of records, where a record is a concrete class%n" + "that you define and not a parameterized type such as %s.", type); } return(Mapper(( Type )recordType)); }
IList <IType> FindTypesInBounds(IList <IType> lowerBounds, IList <IType> upperBounds) { // If there's only a single type; return that single type. // If both inputs are empty, return the empty list. if (lowerBounds.Count == 0 && upperBounds.Count <= 1) { return(upperBounds); } if (upperBounds.Count == 0 && lowerBounds.Count <= 1) { return(lowerBounds); } if (nestingLevel > maxNestingLevel) { return(EmptyList <IType> .Instance); } // Finds a type X so that "LB <: X <: UB" Log.WriteCollection("FindTypesInBound, LowerBounds=", lowerBounds); Log.WriteCollection("FindTypesInBound, UpperBounds=", upperBounds); // First try the Fixing algorithm from the C# spec (§7.5.2.11) List <IType> candidateTypes = lowerBounds.Union(upperBounds) .Where(c => lowerBounds.All(b => conversions.ImplicitConversion(b, c).IsValid)) .Where(c => upperBounds.All(b => conversions.ImplicitConversion(c, b).IsValid)) .ToList(); // evaluate the query only once Log.WriteCollection("FindTypesInBound, Candidates=", candidateTypes); // According to the C# specification, we need to pick the most specific // of the candidate types. (the type which has conversions to all others) // However, csc actually seems to choose the least specific. candidateTypes = candidateTypes.Where( c => candidateTypes.All(o => conversions.ImplicitConversion(o, c).IsValid) ).ToList(); // If the specified algorithm produces a single candidate, we return // that candidate. // We also return the whole candidate list if we're not using the improved // algorithm. if (candidateTypes.Count == 1 || !(algorithm == TypeInferenceAlgorithm.Improved || algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults)) { return(candidateTypes); } candidateTypes.Clear(); // Now try the improved algorithm Log.Indent(); List <ITypeDefinition> candidateTypeDefinitions; if (lowerBounds.Count > 0) { // Find candidates by using the lower bounds: var hashSet = new HashSet <ITypeDefinition>(lowerBounds[0].GetAllBaseTypeDefinitions()); for (int i = 1; i < lowerBounds.Count; i++) { hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions()); } candidateTypeDefinitions = hashSet.ToList(); } else { // Find candidates by looking at all classes in the project: candidateTypeDefinitions = compilation.GetAllTypeDefinitions().ToList(); } // Now filter out candidates that violate the upper bounds: foreach (IType ub in upperBounds) { ITypeDefinition ubDef = ub.GetDefinition(); if (ubDef != null) { candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef)); } } foreach (ITypeDefinition candidateDef in candidateTypeDefinitions) { // determine the type parameters for the candidate: IType candidate; if (candidateDef.TypeParameterCount == 0) { candidate = candidateDef; } else { Log.WriteLine("Inferring arguments for candidate type definition: " + candidateDef); bool success; IType[] result = InferTypeArgumentsFromBounds( candidateDef.TypeParameters, new ParameterizedType(candidateDef, candidateDef.TypeParameters), lowerBounds, upperBounds, out success); if (success) { candidate = new ParameterizedType(candidateDef, result); } else { Log.WriteLine("Inference failed; ignoring candidate"); continue; } } Log.WriteLine("Candidate type: " + candidate); if (upperBounds.Count == 0) { // if there were only lower bounds, we aim for the most specific candidate: // if this candidate isn't made redundant by an existing, more specific candidate: if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef))) { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition())); // add new candidate candidateTypes.Add(candidate); } } else { // if there were upper bounds, we aim for the least specific candidate: // if this candidate isn't made redundant by an existing, less specific candidate: if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition()))) { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef)); // add new candidate candidateTypes.Add(candidate); } } } Log.Unindent(); return(candidateTypes); }
/// <summary> /// Validates that it will be possible to create an EEType for '<paramref name="type"/>'. /// </summary> public static void CheckCanGenerateEEType(NodeFactory factory, TypeDesc type) { // Don't validate generic definitons if (type.IsGenericDefinition) { return; } // It must be possible to create an EEType for the base type of this type TypeDesc baseType = type.BaseType; if (baseType != null) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(baseType); } // We need EETypes for interfaces foreach (var intf in type.RuntimeInterfaces) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(intf); } // Validate classes, structs, enums, interfaces, and delegates DefType defType = type as DefType; if (defType != null) { // Ensure we can compute the type layout defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); // // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor. // We need to make sure this is possible. // if (factory.TypeSystemContext.HasLazyStaticConstructor(defType)) { defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields); } // Make sure instantiation length matches the expectation // TODO: it might be more resonable for the type system to enforce this (also for methods) if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } foreach (TypeDesc typeArg in defType.Instantiation) { // ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments if (typeArg.IsByRef || typeArg.IsPointer || typeArg.IsFunctionPointer || typeArg.IsVoid) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // TODO: validate constraints } } // Validate parameterized types ParameterizedType parameterizedType = type as ParameterizedType; if (parameterizedType != null) { TypeDesc parameterType = parameterizedType.ParameterType; // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(parameterType); if (parameterizedType.IsArray) { if (parameterType.IsPointer || parameterType.IsFunctionPointer) { // Arrays of pointers and function pointers are not currently supported throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } int elementSize = parameterType.GetElementSize(); if (elementSize >= ushort.MaxValue) { // Element size over 64k can't be encoded in the GCDesc throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType); } } // Validate we're not constructing a type over a ByRef if (parameterType.IsByRef) { // CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]" // will fail with a message about being unable to create an array of int32&. This is a middle ground. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard. // E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed. } // Function pointer EETypes are not currently supported if (type.IsFunctionPointer) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } }
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(context) != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArg, context)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } } return(newType); }
/// <summary> /// This is used to extract the class from the specified type. If /// there are no actual generic type arguments to the specified /// type then this will return null. Otherwise this will return /// the actual class, regardless of whether the class is an array. /// </summary> /// <param name="type"> /// this is the type to extract the class from /// </param> /// <returns> /// this returns the class type from the first parameter /// </returns> public Class[] GetClasses(ParameterizedType type) { Type[] list = type.getActualTypeArguments(); Class[] types = new Class[list.length]; for(int i = 0; i < list.length; i++) { types[i] = GetClass(list[i]); } return types; }
/// <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(); } }
private static ParameterExtractor ParameterExtractor(Type type, Parameter parameter, Description description) { if (type is ParameterizedType) { ParameterizedType paramType = ( ParameterizedType )type; Type raw = ( Type )paramType.RawType; Type componentType = paramType.ActualTypeArguments[0]; Type component = null; if (componentType is Type) { component = ( Type )componentType; } if (typeof(ISet <object>) == raw) { TypeCaster caster = _types[component]; if (caster != null) { return(new ListParameterExtractorAnonymousInnerClass(caster, component, parameter, description)); } } else if (typeof(System.Collections.IList) == raw || typeof(System.Collections.ICollection) == raw || typeof(System.Collections.IEnumerable) == raw) { TypeCaster caster = _types[component]; if (caster != null) { return(new ListParameterExtractorAnonymousInnerClass2(caster, component, parameter, description)); } } } else if (type is Type) { Type raw = ( Type )type; if (raw.IsArray) { TypeCaster caster = _types[raw.GetElementType()]; if (caster != null) { return(new ListParameterExtractorAnonymousInnerClass3(caster, raw.GetElementType(), parameter, description)); } } else { TypeCaster caster = _types[raw]; if (caster != null) { return(new ParameterExtractor(caster, raw, parameter, description)); } } } else if (type is GenericArrayType) { GenericArrayType array = ( GenericArrayType )type; Type component = array.GenericComponentType; if (component is Type) { TypeCaster caster = _types[component]; if (caster != null) { return(new ListParameterExtractorAnonymousInnerClass4(caster, parameter, description)); } } } throw new System.InvalidOperationException("Unsupported parameter type: " + type); }
static IEnumerable <IType> GetNestedTypesImpl(IType outerType, IList <IType> nestedTypeArguments, ITypeResolveContext context, Predicate <ITypeDefinition> filter, GetMemberOptions options) { ITypeDefinition outerTypeDef = outerType.GetDefinition(); if (outerTypeDef == null) { yield break; } int outerTypeParameterCount = outerTypeDef.TypeParameterCount; ParameterizedType pt = outerType as ParameterizedType; foreach (ITypeDefinition nestedType in outerTypeDef.NestedTypes) { int totalTypeParameterCount = nestedType.TypeParameterCount; if (nestedTypeArguments != null) { if (totalTypeParameterCount - outerTypeParameterCount != nestedTypeArguments.Count) { continue; } } if (!(filter == null || filter(nestedType))) { continue; } if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { yield return(nestedType); } else if (totalTypeParameterCount == 0 || (pt == null && totalTypeParameterCount == outerTypeParameterCount)) { // The nested type has no new type parameters, and there are no type arguments // to copy from the outer type // -> we can directly return the nested type definition yield return(nestedType); } else { // We need to parameterize the nested type IType[] newTypeArguments = new IType[totalTypeParameterCount]; for (int i = 0; i < outerTypeParameterCount; i++) { newTypeArguments[i] = pt != null?pt.GetTypeArgument(i) : outerTypeDef.TypeParameters[i]; } for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) { if (nestedTypeArguments != null) { newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount]; } else { newTypeArguments[i] = SharedTypes.UnboundTypeArgument; } } yield return(new ParameterizedType(nestedType, newTypeArguments)); } } }
public virtual IType VisitParameterizedType(ParameterizedType type) { return(type.VisitChildren(this)); }
void RunTypeInference(Candidate candidate) { IMethod method = candidate.Member as IMethod; if (method == null || method.TypeParameters.Count == 0) { if (explicitlyGivenTypeArguments != null) { // method does not expect type arguments, but was given some candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); } return; } ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType; IList <IType> classTypeArguments; if (parameterizedDeclaringType != null) { classTypeArguments = parameterizedDeclaringType.TypeArguments; } else { classTypeArguments = null; } // The method is generic: if (explicitlyGivenTypeArguments != null) { if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) { candidate.InferredTypes = explicitlyGivenTypeArguments; } else { candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); // wrong number of type arguments given, so truncate the list or pad with UnknownType candidate.InferredTypes = new IType[method.TypeParameters.Count]; for (int i = 0; i < candidate.InferredTypes.Length; i++) { if (i < explicitlyGivenTypeArguments.Length) { candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; } else { candidate.InferredTypes[i] = SpecialType.UnknownType; } } } } else { TypeInference ti = new TypeInference(compilation, conversions); bool success; candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); if (!success) { candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } } // Now substitute in the formal parameters: var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this); for (int i = 0; i < candidate.ParameterTypes.Length; i++) { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } if (!substitution.ConstraintsValid) { candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); } }
/// <summary> /// This is used to extract the class from the specified type. If /// there are no actual generic type arguments to the specified /// type then this will return null. Otherwise this will return /// the actual class, regardless of whether the class is an array. /// </summary> /// <param name="type"> /// this is the type to extract the class from /// </param> /// <returns> /// this returns the class type from the first parameter /// </returns> public Class GetClass(ParameterizedType type) { Type[] list = type.getActualTypeArguments(); if(list.length > 0) { return GetClass(list[0]); } return null; }