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