internal override bool Equals(TypeSymbol t2, TypeCompareKind comparison)
            {
                if (ReferenceEquals(this, t2))
                {
                    return(true);
                }

                var other = t2 as Nested;

                return((object?)other != null && string.Equals(MetadataName, other.MetadataName, StringComparison.Ordinal) &&
                       arity == other.arity &&
                       _containingType.Equals(other._containingType, comparison));
            }
Пример #2
0
        // Determine if the symbol "member" is a member of the type "type" or one of its
        // base types.
        private bool IsMemberOfType(Symbol member, NamedTypeSymbol type)
        {
            Debug.Assert(type != null);
            Debug.Assert(member != null);

            NamedTypeSymbol container   = member.ContainingType;
            NamedTypeSymbol currentType = type;

            while (currentType != null)
            {
                if (container.Equals(currentType))
                {
                    return(true);
                }
                currentType = currentType.BaseType;
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Determine whether there is any substitution of type parameters that will
        /// make two types identical.
        /// </summary>
        /// <param name="t1">LHS</param>
        /// <param name="t2">RHS</param>
        /// <param name="substitution">
        /// Substitutions performed so far (or null for none).
        /// Keys are type parameters, values are types (possibly type parameters).
        /// Will be updated with new substitutions by the callee.
        /// Should be ignored when false is returned.
        /// </param>
        /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns>
        /// <remarks>
        /// Derived from Dev10's BSYMMGR::UnifyTypes.
        /// Two types will not unify if they have different custom modifiers.
        /// </remarks>
        private static bool CanUnifyHelper(
            TypeWithAnnotations t1,
            TypeWithAnnotations t2,
            ref MutableTypeMap?substitution
            )
        {
            if (!t1.HasType || !t2.HasType)
            {
                return(t1.IsSameAs(t2));
            }

            if (substitution != null)
            {
                t1 = t1.SubstituteType(substitution);
                t2 = t2.SubstituteType(substitution);
            }

            if (
                TypeSymbol.Equals(t1.Type, t2.Type, TypeCompareKind.CLRSignatureCompareOptions) &&
                t1.CustomModifiers.SequenceEqual(t2.CustomModifiers)
                )
            {
                return(true);
            }

            // We can avoid a lot of redundant checks if we ensure that we only have to check
            // for type parameters on the LHS
            if (!t1.Type.IsTypeParameter() && t2.Type.IsTypeParameter())
            {
                TypeWithAnnotations tmp = t1;
                t1 = t2;
                t2 = tmp;
            }

            // If t1 is not a type parameter, then neither is t2
            Debug.Assert(t1.Type.IsTypeParameter() || !t2.Type.IsTypeParameter());

            switch (t1.Type.Kind)
            {
            case SymbolKind.ArrayType:
            {
                if (
                    t2.TypeKind != t1.TypeKind ||
                    !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)
                    )
                {
                    return(false);
                }

                ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1.Type;
                ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2.Type;

                if (!at1.HasSameShapeAs(at2))
                {
                    return(false);
                }

                return(CanUnifyHelper(
                           at1.ElementTypeWithAnnotations,
                           at2.ElementTypeWithAnnotations,
                           ref substitution
                           ));
            }

            case SymbolKind.PointerType:
            {
                if (
                    t2.TypeKind != t1.TypeKind ||
                    !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)
                    )
                {
                    return(false);
                }

                PointerTypeSymbol pt1 = (PointerTypeSymbol)t1.Type;
                PointerTypeSymbol pt2 = (PointerTypeSymbol)t2.Type;

                return(CanUnifyHelper(
                           pt1.PointedAtTypeWithAnnotations,
                           pt2.PointedAtTypeWithAnnotations,
                           ref substitution
                           ));
            }

            case SymbolKind.NamedType:
            case SymbolKind.ErrorType:
            {
                if (
                    t2.TypeKind != t1.TypeKind ||
                    !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)
                    )
                {
                    return(false);
                }

                NamedTypeSymbol nt1 = (NamedTypeSymbol)t1.Type;
                NamedTypeSymbol nt2 = (NamedTypeSymbol)t2.Type;
                if (!nt1.IsGenericType || !nt2.IsGenericType)
                {
                    // Initial TypeSymbol.Equals(...) && CustomModifiers.SequenceEqual(...) failed above,
                    // and custom modifiers compared equal in this case block, so the types must be distinct.
                    Debug.Assert(!nt1.Equals(nt2, TypeCompareKind.CLRSignatureCompareOptions));
                    return(false);
                }

                int arity = nt1.Arity;

                if (
                    nt2.Arity != arity ||
                    !TypeSymbol.Equals(
                        nt2.OriginalDefinition,
                        nt1.OriginalDefinition,
                        TypeCompareKind.ConsiderEverything
                        )
                    )
                {
                    return(false);
                }

                var nt1Arguments = nt1.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;
                var nt2Arguments = nt2.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;

                for (int i = 0; i < arity; i++)
                {
                    if (!CanUnifyHelper(nt1Arguments[i], nt2Arguments[i], ref substitution))
                    {
                        return(false);
                    }
                }

                // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types
                // TODO: Calling CanUnifyHelper for the containing type is an overkill, we simply need to go through type arguments for all containers.
                return((object)nt1.ContainingType == null ||
                       CanUnifyHelper(nt1.ContainingType, nt2.ContainingType, ref substitution));
            }

            case SymbolKind.TypeParameter:
            {
                // These substitutions are not allowed in C#
                if (t2.Type.IsPointerOrFunctionPointer() || t2.IsVoidType())
                {
                    return(false);
                }

                TypeParameterSymbol tp1 = (TypeParameterSymbol)t1.Type;

                // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types
                // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above
                if (Contains(t2.Type, tp1))
                {
                    return(false);
                }

                if (t1.CustomModifiers.IsDefaultOrEmpty)
                {
                    AddSubstitution(ref substitution, tp1, t2);
                    return(true);
                }

                if (t1.CustomModifiers.SequenceEqual(t2.CustomModifiers))
                {
                    AddSubstitution(ref substitution, tp1, TypeWithAnnotations.Create(t2.Type));
                    return(true);
                }

                if (
                    t1.CustomModifiers.Length < t2.CustomModifiers.Length &&
                    t1.CustomModifiers.SequenceEqual(
                        t2.CustomModifiers.Take(t1.CustomModifiers.Length)
                        )
                    )
                {
                    AddSubstitution(
                        ref substitution,
                        tp1,
                        TypeWithAnnotations.Create(
                            t2.Type,
                            customModifiers: ImmutableArray.Create(
                                t2.CustomModifiers,
                                t1.CustomModifiers.Length,
                                t2.CustomModifiers.Length - t1.CustomModifiers.Length
                                )
                            )
                        );
                    return(true);
                }

                if (t2.Type.IsTypeParameter())
                {
                    var tp2 = (TypeParameterSymbol)t2.Type;

                    if (t2.CustomModifiers.IsDefaultOrEmpty)
                    {
                        AddSubstitution(ref substitution, tp2, t1);
                        return(true);
                    }

                    if (
                        t2.CustomModifiers.Length < t1.CustomModifiers.Length &&
                        t2.CustomModifiers.SequenceEqual(
                            t1.CustomModifiers.Take(t2.CustomModifiers.Length)
                            )
                        )
                    {
                        AddSubstitution(
                            ref substitution,
                            tp2,
                            TypeWithAnnotations.Create(
                                t1.Type,
                                customModifiers: ImmutableArray.Create(
                                    t1.CustomModifiers,
                                    t2.CustomModifiers.Length,
                                    t1.CustomModifiers.Length - t2.CustomModifiers.Length
                                    )
                                )
                            );
                        return(true);
                    }
                }

                return(false);
            }

            default:
            {
                return(false);
            }
            }
        }
Пример #4
0
        /// <summary>
        /// Determine if "type" inherits from or implements "baseType", ignoring constructed types, and dealing
        /// only with original types.
        /// </summary>
        private static bool InheritsFromOrImplementsIgnoringConstruction(
            this TypeSymbol type,
            NamedTypeSymbol baseType,
            CSharpCompilation compilation,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics,
            ConsList <TypeSymbol> basesBeingResolved = null)
        {
            Debug.Assert(type.IsDefinition);
            Debug.Assert(baseType.IsDefinition);

            PooledHashSet <NamedTypeSymbol> interfacesLookedAt = null;
            ArrayBuilder <NamedTypeSymbol>  baseInterfaces     = null;

            bool baseTypeIsInterface = baseType.IsInterface;

            if (baseTypeIsInterface)
            {
                interfacesLookedAt = PooledHashSet <NamedTypeSymbol> .GetInstance();

                baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance();
            }

            PooledHashSet <NamedTypeSymbol> visited = null;
            var  current = type;
            bool result  = false;

            while ((object)current != null)
            {
                if (baseTypeIsInterface == current.IsInterfaceType() && current.Equals(baseType))
                {
                    result = true;
                    break;
                }

                if (baseTypeIsInterface)
                {
                    getBaseInterfaces(current, baseInterfaces, interfacesLookedAt, basesBeingResolved);
                }

                // NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e.
                // "class Goo : IBar<int>".  We must map it back to the 'original' when as we walk up
                // the base type hierarchy.
                var next = current.GetNextBaseTypeNoUseSiteDiagnostics(basesBeingResolved, compilation, ref visited);
                if ((object)next == null)
                {
                    current = null;
                }
                else
                {
                    current = (TypeSymbol)next.OriginalDefinition;
                    current.AddUseSiteDiagnostics(ref useSiteDiagnostics);
                }
            }

            visited?.Free();

            if (!result && baseTypeIsInterface)
            {
                Debug.Assert(!result);

                while (baseInterfaces.Count != 0)
                {
                    NamedTypeSymbol currentBase = baseInterfaces.Pop();

                    if (!currentBase.IsInterface)
                    {
                        continue;
                    }

                    if (currentBase.Equals(baseType))
                    {
                        result = true;
                        break;
                    }

                    getBaseInterfaces(currentBase, baseInterfaces, interfacesLookedAt, basesBeingResolved);
                }

                if (!result)
                {
                    foreach (var candidate in interfacesLookedAt)
                    {
                        candidate.AddUseSiteDiagnostics(ref useSiteDiagnostics);
                    }
                }
            }

            interfacesLookedAt?.Free();
            baseInterfaces?.Free();
            return(result);
        internal Microsoft.Cci.INamedTypeReference Translate(NamedTypeSymbol namedTypeSymbol, bool needDeclaration)
        {
            System.Diagnostics.Debug.Assert(ReferenceEquals(namedTypeSymbol, namedTypeSymbol.OriginalDefinition) ||
                !namedTypeSymbol.Equals(namedTypeSymbol.OriginalDefinition));

            if (!ReferenceEquals(namedTypeSymbol, namedTypeSymbol.OriginalDefinition))
            {
                // generic instantiation for sure
                System.Diagnostics.Debug.Assert(!needDeclaration);

                return namedTypeSymbol;
            }
            else if (!needDeclaration)
            {
                object reference;
                Microsoft.Cci.INamedTypeReference typeRef;

                NamedTypeSymbol container = namedTypeSymbol.ContainingType;

                if (namedTypeSymbol.Arity > 0)
                {
                    if (genericInstanceMap.TryGetValue(namedTypeSymbol, out reference))
                    {
                        return (Microsoft.Cci.INamedTypeReference)reference;
                    }

                    if (container != null)
                    {
                        if (IsGenericType(container))
                        {
                            // Container is a generic instance too.
                            typeRef = new SpecializedGenericNestedTypeInstanceReference(namedTypeSymbol);
                        }
                        else
                        {
                            typeRef = new GenericNestedTypeInstanceReference(namedTypeSymbol);
                        }
                    }
                    else
                    {
                        typeRef = new GenericNamespaceTypeInstanceReference(namedTypeSymbol);
                    }

                    genericInstanceMap.Add(namedTypeSymbol, typeRef);

                    return typeRef;
                }
                else if (IsGenericType(container))
                {
                    System.Diagnostics.Debug.Assert(container != null);

                    if (genericInstanceMap.TryGetValue(namedTypeSymbol, out reference))
                    {
                        return (Microsoft.Cci.INamedTypeReference)reference;
                    }

                    typeRef = new SpecializedNestedTypeReference(namedTypeSymbol);

                    genericInstanceMap.Add(namedTypeSymbol, typeRef);

                    return typeRef;
                }
            }

            return namedTypeSymbol;
        }
Пример #6
0
        internal Microsoft.Cci.INamedTypeReference Translate(NamedTypeSymbol namedTypeSymbol, bool needDeclaration)
        {
            System.Diagnostics.Debug.Assert(ReferenceEquals(namedTypeSymbol, namedTypeSymbol.OriginalDefinition) ||
                                            !namedTypeSymbol.Equals(namedTypeSymbol.OriginalDefinition));

            if (!ReferenceEquals(namedTypeSymbol, namedTypeSymbol.OriginalDefinition))
            {
                // generic instantiation for sure
                System.Diagnostics.Debug.Assert(!needDeclaration);

                return(namedTypeSymbol);
            }
            else if (!needDeclaration)
            {
                object reference;
                Microsoft.Cci.INamedTypeReference typeRef;

                NamedTypeSymbol container = namedTypeSymbol.ContainingType;

                if (namedTypeSymbol.Arity > 0)
                {
                    if (genericInstanceMap.TryGetValue(namedTypeSymbol, out reference))
                    {
                        return((Microsoft.Cci.INamedTypeReference)reference);
                    }

                    if (container != null)
                    {
                        if (IsGenericType(container))
                        {
                            // Container is a generic instance too.
                            typeRef = new SpecializedGenericNestedTypeInstanceReference(namedTypeSymbol);
                        }
                        else
                        {
                            typeRef = new GenericNestedTypeInstanceReference(namedTypeSymbol);
                        }
                    }
                    else
                    {
                        typeRef = new GenericNamespaceTypeInstanceReference(namedTypeSymbol);
                    }

                    genericInstanceMap.Add(namedTypeSymbol, typeRef);

                    return(typeRef);
                }
                else if (IsGenericType(container))
                {
                    System.Diagnostics.Debug.Assert(container != null);

                    if (genericInstanceMap.TryGetValue(namedTypeSymbol, out reference))
                    {
                        return((Microsoft.Cci.INamedTypeReference)reference);
                    }

                    typeRef = new SpecializedNestedTypeReference(namedTypeSymbol);

                    genericInstanceMap.Add(namedTypeSymbol, typeRef);

                    return(typeRef);
                }
            }

            return(namedTypeSymbol);
        }