Esempio n. 1
0
            public override IType VisitParameterizedType(ParameterizedTypeSpec type)
            {
                IType newType = base.VisitParameterizedType(type);

                if (newType != type && ConstraintsValid)
                {
                    // something was changed, so we need to validate the constraints
                    ParameterizedTypeSpec newParameterizedType = newType as ParameterizedTypeSpec;
                    if (newParameterizedType != null)
                    {
                        // V# 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);
            }
Esempio n. 2
0
        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);
            }

            ParameterizedTypeSpec p1 = t1 as ParameterizedTypeSpec;
            ParameterizedTypeSpec p2 = t2 as ParameterizedTypeSpec;

            if (p1 != null && p2 != null && p1.TypeParameterCount == p2.TypeParameterCount)
            {
                int r = MoreSpecificFormalParameters(p1.TypeArguments, p2.TypeArguments);
                if (r > 0)
                {
                    return(r);
                }
            }
            ElementTypeSpec tew1 = t1 as ElementTypeSpec;
            ElementTypeSpec tew2 = t2 as ElementTypeSpec;

            if (tew1 != null && tew2 != null)
            {
                return(MoreSpecificFormalParameter(tew1.ElementType, tew2.ElementType));
            }
            return(0);
        }
Esempio n. 3
0
        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;
            ParameterizedTypeSpec pt    = outerType as ParameterizedTypeSpec;

            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] = SpecialTypeSpec.UnboundTypeArgument;
                        }
                    }
                    yield return(new ParameterizedTypeSpec(nestedType, newTypeArguments));
                }
            }
        }
Esempio n. 4
0
        static IMethod GetDelegateOrExpressionTreeSignature(IType t)
        {
            ParameterizedTypeSpec pt = t as ParameterizedTypeSpec;

            if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" &&
                pt.Namespace == "Std.Linq.Expressions")
            {
                t = pt.GetTypeArgument(0);
            }
            return(t.GetDelegateInvokeMethod());
        }
Esempio n. 5
0
        Expression LookInUsingScopeNamespace(ResolveContext rc, ResolvedUsingScope usingScope, INamespace n, string identifier, IList <IType> typeArguments, bool parameterizeResultType)
        {
            if (n == null)
            {
                return(null);
            }
            // first look for a namespace
            int k = typeArguments.Count;

            if (k == 0)
            {
                INamespace childNamespace = n.GetChildNamespace(identifier);
                if (childNamespace != null)
                {
                    if (usingScope != null && usingScope.HasAlias(identifier))
                    {
                        rc.Report.Error(7, loc, "The name `{0}' is ambigious", name);
                        return(new TypeExpression((IType) new UnknownTypeSpec(null, identifier), Location)); // ambigious
                    }

                    return(new AliasNamespace(childNamespace, Location));
                }
            }
            // then look for a type
            ITypeDefinition def = n.GetTypeDefinition(identifier, k);

            if (def != null)
            {
                IType result = def;
                if (parameterizeResultType && k > 0)
                {
                    result = new ParameterizedTypeSpec(def, typeArguments);
                }

                if (usingScope != null && usingScope.HasAlias(identifier))
                {
                    rc.Report.Error(7, loc, "The name `{0}' is ambigious", name);
                    return(new TypeExpression((IType) new UnknownTypeSpec(null, identifier), Location)); // ambigious
                }
                else
                {
                    return(new TypeExpression(result, Location));
                }
            }
            return(null);
        }
Esempio n. 6
0
        static bool IsGenericInterfaceImplementedByArray(ParameterizedTypeSpec 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);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Make exact inference from U to V.
        /// V# 4.0 spec: §7.5.2.8 Exact inferences
        /// </summary>
        void MakeExactInference(IType U, IType 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)
            {
                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:
            ParameterizedTypeSpec pU = U as ParameterizedTypeSpec;
            ParameterizedTypeSpec pV = V as ParameterizedTypeSpec;

            if (pU != null && pV != null &&
                object.Equals(pU.GetDefinition(), pV.GetDefinition()) &&
                pU.TypeParameterCount == pV.TypeParameterCount)
            {
                for (int i = 0; i < pU.TypeParameterCount; i++)
                {
                    MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i));
                }
            }
        }
Esempio n. 8
0
        public void ResolveSelfType(ResolveContext rc)
        {
            eclass = ExprClass.Variable;
            if (!IsSelfOrSuperAvailable(rc, false))
            {
                if (rc.IsStatic && !rc.HasSet(ResolveContext.Options.ConstantScope))
                {
                    rc.Report.Error(241, loc, "Keyword `self' is not valid in a static property, static method, or static field initializer");
                }
                else if (rc.CurrentAnonymousMethod != null)
                {
                    rc.Report.Error(242, loc,
                                    "Anonymous methods inside structs cannot access instance members of `self'. " +
                                    "Consider copying `self' to a local variable outside the anonymous method and using the local instead");
                }
                else
                {
                    rc.Report.Error(243, loc, "Keyword `self' is not available in the current context");
                }

                return;
            }


            ITypeDefinition t = rc.CurrentTypeDefinition;

            if (t != null)
            {
                if (t.TypeParameterCount != 0)
                {
                    // Self-parameterize the type
                    ResolvedType = new ParameterizedTypeSpec(t, t.TypeParameters);
                }
                else
                {
                    ResolvedType = t;
                }
            }


            _resolved = true;
        }
Esempio n. 9
0
        static IEnumerable <IMethod> GetMethodsImpl(IType baseType, IList <IType> methodTypeArguments, Predicate <IUnresolvedMethod> filter, GetMemberOptions options)
        {
            IEnumerable <IMethod> declaredMethods = baseType.GetMethods(filter, options | declaredMembers);

            ParameterizedTypeSpec pt = baseType as ParameterizedTypeSpec;

            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);
                }
            }
        }
Esempio n. 10
0
        static IEnumerable <IMethod> GetConstructorsOrAccessorsImpl(IType baseType, IEnumerable <IMethod> declaredMembers, Predicate <IUnresolvedMethod> filter, GetMemberOptions options)
        {
            if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
            {
                return(declaredMembers);
            }

            ParameterizedTypeSpec pt = baseType as ParameterizedTypeSpec;

            if (pt != null)
            {
                var substitution = pt.GetSubstitution();
                return(declaredMembers.Select(m => new SpecializedMethod(m, substitution)
                {
                    DeclaringType = pt
                }));
            }
            else
            {
                return(declaredMembers);
            }
        }
Esempio n. 11
0
        static IEnumerable <IEvent> GetEventsImpl(IType baseType, Predicate <IUnresolvedEvent> filter, GetMemberOptions options)
        {
            IEnumerable <IEvent> declaredEvents = baseType.GetEvents(filter, options | declaredMembers);

            if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
            {
                return(declaredEvents);
            }

            ParameterizedTypeSpec pt = baseType as ParameterizedTypeSpec;

            if (pt != null)
            {
                var substitution = pt.GetSubstitution();
                return(declaredEvents.Select(m => new SpecializedEvent(m, substitution)
                {
                    DeclaringType = pt
                }));
            }
            else
            {
                return(declaredEvents);
            }
        }
Esempio n. 12
0
        void RunTypeInference(Candidate candidate)
        {
            if (candidate.TypeParameters == null)
            {
                if (explicitlyGivenTypeArguments != null)
                {
                    // method does not expect type arguments, but was given some
                    candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
                }
                // Grab new parameter types:
                ResolveParameterTypes(candidate, true);
                return;
            }
            ParameterizedTypeSpec parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedTypeSpec;
            IList <IType>         classTypeArguments;

            if (parameterizedDeclaringType != null)
            {
                classTypeArguments = parameterizedDeclaringType.TypeArguments;
            }
            else
            {
                classTypeArguments = null;
            }
            // The method is generic:
            if (explicitlyGivenTypeArguments != null)
            {
                if (explicitlyGivenTypeArguments.Length == candidate.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[candidate.TypeParameters.Count];
                    for (int i = 0; i < candidate.InferredTypes.Length; i++)
                    {
                        if (i < explicitlyGivenTypeArguments.Length)
                        {
                            candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i];
                        }
                        else
                        {
                            candidate.InferredTypes[i] = SpecialTypeSpec.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);
            }
        }
Esempio n. 13
0
        Expression LookInCurrentUsingScope(ResolveContext rc, string identifier, IList <IType> typeArguments, bool isInUsingDeclaration, bool parameterizeResultType)
        {
            // look in current namespace definitions
            ResolvedUsingScope currentUsingScope = rc.CurrentUsingScope;

            for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent)
            {
                var resultInNamespace = LookInUsingScopeNamespace(rc, u, u.Namespace, identifier, typeArguments, parameterizeResultType);
                if (resultInNamespace != null)
                {
                    return(resultInNamespace);
                }
                // then look for aliases:
                if (typeArguments.Count == 0)
                {
                    if (u.ExternAliases.Contains(identifier))
                    {
                        return(ResolveExternAlias(rc, identifier));
                    }
                    if (!(isInUsingDeclaration && u == currentUsingScope))
                    {
                        foreach (var pair in u.UsingAliases)
                        {
                            if (pair.Key == identifier)
                            {
                                return(pair.Value.ShallowClone());
                            }
                        }
                    }
                }
                // finally, look in the imported namespaces:
                if (!(isInUsingDeclaration && u == currentUsingScope))
                {
                    IType firstResult = null;
                    foreach (var importedNamespace in u.Usings)
                    {
                        ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, typeArguments.Count);
                        if (def != null)
                        {
                            IType resultType;
                            if (parameterizeResultType && typeArguments.Count > 0)
                            {
                                resultType = new ParameterizedTypeSpec(def, typeArguments);
                            }
                            else
                            {
                                resultType = def;
                            }

                            if (firstResult == null || !TopLevelTypeDefinitionIsAccessible(rc, firstResult.GetDefinition()))
                            {
                                if (TopLevelTypeDefinitionIsAccessible(rc, resultType.GetDefinition()))
                                {
                                    firstResult = resultType;
                                }
                            }
                            else if (TopLevelTypeDefinitionIsAccessible(rc, def))
                            {
                                rc.Report.Error(7, loc, "The name `{0}' is ambigious", name);
                                return(new TypeExpression(firstResult, Location)); // ambigious
                            }
                        }
                    }
                    if (firstResult != null)
                    {
                        return(new TypeExpression(firstResult, Location));
                    }
                }
                // if we didn't find anything: repeat lookup with parent namespace
            }
            return(null);
        }
Esempio n. 14
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"

            // First try the Fixing algorithm from the V# 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



            // According to the V# 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

            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
                {
                    bool    success;
                    IType[] result = InferTypeArgumentsFromBounds(
                        candidateDef.TypeParameters,
                        new ParameterizedTypeSpec(candidateDef, candidateDef.TypeParameters),
                        lowerBounds, upperBounds,
                        out success);
                    if (success)
                    {
                        candidate = new ParameterizedTypeSpec(candidateDef, result);
                    }
                    else
                    {
                        continue;
                    }
                }


                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);
                    }
                }
            }

            return(candidateTypes);
        }
Esempio n. 15
0
        /// <summary>
        /// Make upper bound inference from U to V.
        /// V# 4.0 spec: §7.5.2.10 Upper-bound inferences
        /// </summary>
        void MakeUpperBoundInference(IType U, IType 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)
            {
                tp.UpperBounds.Add(U);
                return;
            }

            // Handle array types:
            ArrayType             arrU = U as ArrayType;
            ArrayType             arrV = V as ArrayType;
            ParameterizedTypeSpec pU   = U as ParameterizedTypeSpec;

            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)
            {
                ParameterizedTypeSpec uniqueBaseType = null;
                foreach (IType baseV in V.GetAllBaseTypes())
                {
                    ParameterizedTypeSpec pV = baseV as ParameterizedTypeSpec;
                    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
                        }
                    }
                }

                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];
                            MakeExactInference(Ui, Vi);
                        }
                        else
                        {
                            // not known to be a reference type
                            MakeExactInference(Ui, Vi);
                        }
                    }
                }
            }
        }