/// <summary> /// Returns true if the members of superType are accessible from subType due to inheritance. /// </summary> public static bool IsAccessibleViaInheritance( this NamedTypeSymbol superType, NamedTypeSymbol subType, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo ) { // NOTE: we don't use strict inheritance. Instead we ignore constructed generic types // and only consider the unconstructed types. Ecma-334, 4th edition contained the // following text supporting this (although, for instance members) in 10.5.3 Protected // access for instance members: // In the context of generics (25.1.6), the rules for accessing protected and // protected internal instance members are augmented by the following: // o Within a generic class G, access to an inherited protected instance member M // using a primary-expression of the form E.M is permitted if the type of E is a // class type constructed from G or a class type derived from a class type // constructed from G. // This text is missing in the current version of the spec, but we believe this is accidental. NamedTypeSymbol originalSuperType = superType.OriginalDefinition; for ( NamedTypeSymbol?current = subType; (object?)current != null; current = current.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo) ) { if (ReferenceEquals(current.OriginalDefinition, originalSuperType)) { return(true); } } if (originalSuperType.IsInterface) { foreach ( NamedTypeSymbol current in subType.AllInterfacesWithDefinitionUseSiteDiagnostics( ref useSiteInfo ) ) { if (ReferenceEquals(current.OriginalDefinition, originalSuperType)) { return(true); } } } // The method returns true for superType == subType. // Two different submission type symbols semantically represent a single type, so we should also return true. return(superType.TypeKind == TypeKind.Submission && subType.TypeKind == TypeKind.Submission); }