Esempio n. 1
0
 /// <summary>
 /// Add the type to the builder and then recurse on its interfaces.
 /// </summary>
 /// <remarks>
 /// Pre-order depth-first search.
 /// </remarks>
 private static void InterfacesVisit(NamedTypeSymbol namedType, ArrayBuilder <NamedTypeSymbol> builder, ref HashSet <NamedTypeSymbol> seen)
 {
     // It's not clear how important the order of these interfaces is, but Dev10
     // maintains pre-order depth-first/declaration order, so we probably should as well.
     // That's why we're not using InterfacesAndTheirBaseInterfaces - it's an unordered set.
     foreach (NamedTypeSymbol @interface in namedType.InterfacesNoUseSiteDiagnostics())
     {
         if (seen == null)
         {
             // Don't allocate until we see at least one interface.
             seen = new HashSet <NamedTypeSymbol>(Symbols.SymbolEqualityComparer.CLRSignature);
         }
         if (seen.Add(@interface))
         {
             builder.Add(@interface);
             InterfacesVisit(@interface, builder, ref seen);
         }
     }
 }
Esempio n. 2
0
        // C# does not let you declare a type in which it would be possible for distinct base interfaces
        // to unify under some instantiations.  But such ill-formed classes can come in through
        // metadata and be instantiated in C#.  We check to see if that's happened.
        private static bool HasDuplicateInterfaces(NamedTypeSymbol type, ConsList <Symbol> basesBeingResolved)
        {
            // PERF: avoid instantiating all interfaces here
            //       Ex: if class implements just IEnumerable<> and IComparable<> it cannot have conflicting implementations
            var array = type.OriginalDefinition.InterfacesNoUseSiteDiagnostics(basesBeingResolved);

            switch (array.Length)
            {
            case 0:
            case 1:
                // less than 2 interfaces
                return(false);

            case 2:
                if ((object)array[0].OriginalDefinition == array[1].OriginalDefinition)
                {
                    break;
                }

                // two unrelated interfaces
                return(false);

            default:
                var set = new HashSet <NamedTypeSymbol>(ReferenceEqualityComparer.Instance);
                foreach (var i in array)
                {
                    if (!set.Add(i.OriginalDefinition))
                    {
                        goto hasRelatedInterfaces;
                    }
                }

                // all interfaces are unrelated
                return(false);
            }

            // very rare case.
            // some implemented interfaces are related
            // will have to instantiate interfaces and check
hasRelatedInterfaces:
            return(type.InterfacesNoUseSiteDiagnostics(basesBeingResolved).HasDuplicates(TypeSymbol.EqualsIgnoringDynamicComparer));
        }
Esempio n. 3
0
        /// <summary>
        /// Accumulate diagnostics related to the variance safety of an interface.
        /// </summary>
        internal static void CheckInterfaceVarianceSafety(this NamedTypeSymbol interfaceType, DiagnosticBag diagnostics)
        {
            Debug.Assert((object)interfaceType != null && interfaceType.IsInterface);

            foreach (NamedTypeSymbol baseInterface in interfaceType.InterfacesNoUseSiteDiagnostics())
            {
                IsVarianceUnsafe(
                    baseInterface,
                    requireOutputSafety: true,
                    requireInputSafety: false,
                    context: baseInterface,
                    locationProvider: i => null,
                    locationArg: baseInterface,
                    diagnostics: diagnostics);
            }

            foreach (Symbol member in interfaceType.GetMembersUnordered())
            {
                switch (member.Kind)
                {
                case SymbolKind.Method:
                    if (!member.IsAccessor())
                    {
                        CheckMethodVarianceSafety((MethodSymbol)member, diagnostics);
                    }
                    break;

                case SymbolKind.Property:
                    CheckPropertyVarianceSafety((PropertySymbol)member, diagnostics);
                    break;

                case SymbolKind.Event:
                    CheckEventVarianceSafety((EventSymbol)member, diagnostics);
                    break;

                case SymbolKind.NamedType:
                    CheckNestedTypeVarianceSafety((NamedTypeSymbol)member, diagnostics);
                    break;
                }
            }
        }
Esempio n. 4
0
        // C# does not let you declare a type in which it would be possible for distinct base interfaces
        // to unify under some instantiations.  But such ill-formed classes can come in through
        // metadata and be instantiated in C#.  We check to see if that's happened.
        private static bool HasDuplicateInterfaces(NamedTypeSymbol type, ConsList<Symbol> basesBeingResolved)
        {
            // PERF: avoid instantiating all interfaces here
            //       Ex: if class implements just IEnumerable<> and IComparable<> it cannot have conflicting implementations
            var array = type.OriginalDefinition.InterfacesNoUseSiteDiagnostics(basesBeingResolved);

            switch (array.Length)
            {
                case 0:
                case 1:
                    // less than 2 interfaces
                    return false;

                case 2:
                    if ((object)array[0].OriginalDefinition == array[1].OriginalDefinition)
                    {
                        break;
                    }

                    // two unrelated interfaces 
                    return false;

                default:
                    var set = PooledHashSet<object>.GetInstance();
                    foreach (var i in array)
                    {
                        if (!set.Add(i.OriginalDefinition))
                        {
                            set.Free();
                            goto hasRelatedInterfaces;
                        }
                    }

                    // all interfaces are unrelated
                    set.Free();
                    return false;
            }
            
            // very rare case. 
            // some implemented interfaces are related
            // will have to instantiate interfaces and check
            hasRelatedInterfaces:
            return type.InterfacesNoUseSiteDiagnostics(basesBeingResolved).HasDuplicates(TypeSymbol.EqualsIgnoringDynamicAndTupleNamesComparer);
        }
Esempio n. 5
0
 internal sealed override ImmutableArray <NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList <Symbol> basesBeingResolved)
 {
     return(_unbound ? ImmutableArray <NamedTypeSymbol> .Empty : Map.SubstituteNamedTypes(OriginalDefinition.InterfacesNoUseSiteDiagnostics(basesBeingResolved)));
 }
 // C# does not let you declare a type in which it would be possible for distinct base interfaces
 // to unify under some instantiations.  But such ill-formed classes can come in through
 // metadata and be instantiated in C#.  We check to see if that's happened.
 private static bool InterfacesAreDistinct(NamedTypeSymbol type, ConsList<Symbol> basesBeingResolved)
 {
     return !type.InterfacesNoUseSiteDiagnostics(basesBeingResolved).HasDuplicates(TypeSymbol.EqualsIgnoringDynamicComparer);
 }
Esempio n. 7
0
        private void CheckBaseTypeCompliance(NamedTypeSymbol symbol)
        {
            System.Diagnostics.Debug.Assert(IsTrue(GetDeclaredOrInheritedCompliance(symbol)), "Only call on compliant symbols");

            // NOTE: implemented interfaces do not have to be CLS-compliant (unless the type itself is an interface).

            if (symbol.IsInterface)
            {
                foreach (NamedTypeSymbol interfaceType in symbol.InterfacesNoUseSiteDiagnostics())
                {
                    if (!IsCompliantType(interfaceType, symbol))
                    {
                        // TODO: it would be nice to report this on the base type clause.
                        this.AddDiagnostic(ErrorCode.WRN_CLS_BadInterface, symbol.Locations[0], symbol, interfaceType);
                    }
                }
            }
            else
            {
                NamedTypeSymbol baseType = symbol.EnumUnderlyingType ?? symbol.BaseTypeNoUseSiteDiagnostics; // null for interfaces
                System.Diagnostics.Debug.Assert((object)baseType != null || symbol.SpecialType == SpecialType.System_Object, "Only object has no base.");
                if ((object)baseType != null && !IsCompliantType(baseType, symbol))
                {
                    // TODO: it would be nice to report this on the base type clause.
                    this.AddDiagnostic(ErrorCode.WRN_CLS_BadBase, symbol.Locations[0], symbol, baseType);
                }
            }
        }
 /// <summary>
 /// Add the type to the builder and then recurse on its interfaces.
 /// </summary>
 /// <remarks>
 /// Pre-order depth-first search.
 /// </remarks>
 private static void InterfacesVisit(NamedTypeSymbol namedType, ArrayBuilder<NamedTypeSymbol> builder, ref HashSet<NamedTypeSymbol> seen)
 {
     // It's not clear how important the order of these interfaces is, but Dev10
     // maintains pre-order depth-first/declaration order, so we probably should as well.
     // That's why we're not using InterfacesAndTheirBaseInterfaces - it's an unordered set.
     foreach (NamedTypeSymbol @interface in namedType.InterfacesNoUseSiteDiagnostics())
     {
         if (seen == null)
         {
             // Don't allocate until we see at least one interface.
             seen = new HashSet<NamedTypeSymbol>();
         }
         if (seen.Add(@interface))
         {
             builder.Add(@interface);
             InterfacesVisit(@interface, builder, ref seen);
         }
     }
 }
Esempio n. 9
0
 // C# does not let you declare a type in which it would be possible for distinct base interfaces
 // to unify under some instantiations.  But such ill-formed classes can come in through
 // metadata and be instantiated in C#.  We check to see if that's happened.
 private static bool InterfacesAreDistinct(NamedTypeSymbol type, ConsList <Symbol> basesBeingResolved)
 {
     return(!type.InterfacesNoUseSiteDiagnostics(basesBeingResolved).HasDuplicates(TypeSymbol.EqualsIgnoringDynamicComparer));
 }