/// <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;
     }
 }
示例#2
0
        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);
            }
        }
示例#3
0
        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()));
        }
示例#5
0
 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;
			}
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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);
                }
            }
        }
示例#10
0
        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);
            }
        }
示例#11
0
        /// <summary>
        /// Finds IList&lt;T&gt; or IEnumerable&lt;T&gt; base type.
        /// </summary>
        /// <param name="fullNamePrefix">Type code to search for (IList&lt;T&gt; or IEnumerable&lt;T&gt;)</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;
		}
示例#13
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 });
        }
示例#14
0
        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);
            }
        }
示例#15
0
        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);
        }
示例#16
0
        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);
            }
        }
示例#17
0
        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));
        }
示例#18
0
        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);
        }
示例#19
0
        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));
        }
示例#20
0
        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);
            }
        }
示例#21
0
        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);
            }
        }
示例#22
0
        /// <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));
        }
示例#23
0
        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);
        }
示例#24
0
        /// <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);
            }
        }
示例#25
0
            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);
            }
示例#26
0
 /// <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;
 }
示例#27
0
        /// <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();
            }
        }
示例#28
0
 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);
 }
示例#29
0
        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));
 }
示例#31
0
        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);
            }
        }
示例#32
0
 /// <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;
 }