Exemple #1
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;
                        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);
            }
Exemple #2
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 != 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);
            }
        static IEnumerable<IType> GetNestedTypesImpl(IType outerType, IList<IType> nestedTypeArguments, 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 (totalTypeParameterCount == 0 || (options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
                    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] = SpecialType.UnboundTypeArgument;
                    }
                    yield return new ParameterizedType(nestedType, newTypeArguments);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Unpacks the generic Task[T]. Returns null if the input is not Task[T].
        /// </summary>
        static IType UnpackTask(IType type)
        {
            ParameterizedType pt = type as ParameterizedType;

            if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Task" && pt.Namespace == "System.Threading.Tasks")
            {
                return(pt.GetTypeArgument(0));
            }
            return(null);
        }
Exemple #5
0
        static IMethod GetDelegateOrExpressionTreeSignature(IType t)
        {
            ParameterizedType pt = t as ParameterizedType;

            if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" &&
                pt.Namespace == "System.Linq.Expressions")
            {
                t = pt.GetTypeArgument(0);
            }
            return(t.GetDelegateInvokeMethod());
        }
Exemple #6
0
        /// <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 (U.Nullability == V.Nullability)
            {
                U = U.WithoutNullability();
                V = V.WithoutNullability();
            }

            // 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.AddExactBound(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.TupleUnderlyingTypeOrSelf() as ParameterizedType;
            ParameterizedType pV = V.TupleUnderlyingTypeOrSelf() as ParameterizedType;

            if (pU != null && pV != null &&
                object.Equals(pU.GenericType, pV.GenericType) &&
                pU.TypeParameterCount == pV.TypeParameterCount)
            {
                Log.Indent();
                for (int i = 0; i < pU.TypeParameterCount; i++)
                {
                    MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i));
                }
                Log.Unindent();
            }
        }
Exemple #7
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));
        }
Exemple #8
0
        static IType UnpackExpressionTreeType(IType type)
        {
            ParameterizedType pt = type as ParameterizedType;

            if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" && pt.Namespace == "System.Linq.Expressions")
            {
                return(pt.GetTypeArgument(0));
            }
            else
            {
                return(type);
            }
        }
Exemple #9
0
        bool IdentityOrVarianceConversion(IType s, IType t, int subtypeCheckNestingDepth)
        {
            ITypeDefinition def = s.GetDefinition();

            if (def != null && def.Equals(t.GetDefinition()))
            {
                ParameterizedType ps = s as ParameterizedType;
                ParameterizedType pt = t as ParameterizedType;
                if (ps != null && pt != null)
                {
                    // C# 4.0 spec: §13.1.3.2 Variance Conversion
                    for (int i = 0; i < def.TypeParameters.Count; i++)
                    {
                        IType si = ps.GetTypeArgument(i);
                        IType ti = pt.GetTypeArgument(i);
                        if (IdentityConversion(si, ti))
                        {
                            continue;
                        }
                        ITypeParameter xi = def.TypeParameters[i];
                        switch (xi.Variance)
                        {
                        case VarianceModifier.Covariant:
                            if (!ImplicitReferenceConversion(si, ti, subtypeCheckNestingDepth))
                            {
                                return(false);
                            }
                            break;

                        case VarianceModifier.Contravariant:
                            if (!ImplicitReferenceConversion(ti, si, subtypeCheckNestingDepth))
                            {
                                return(false);
                            }
                            break;

                        default:
                            return(false);
                        }
                    }
                }
                else if (ps != null || pt != null)
                {
                    return(false);                    // only of of them is parameterized, or counts don't match? -> not valid conversion
                }
                return(true);
            }
            return(false);
        }
Exemple #10
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);
        }
Exemple #11
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();
            }
        }
Exemple #12
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));
                }
            }
        }