private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet <Symbol> partialClosure) { Debug.Assert((object)type != null); // NOTE: unlike in StructDependsClosure, we don't have to check for expanding cycles, // because as soon as we see something with non-zero arity we kick out (generic => managed). if (partialClosure.Add(type)) { foreach (var member in type.GetInstanceFieldsAndEvents()) { // Only instance fields (including field-like events) affect the outcome. FieldSymbol field; switch (member.Kind) { case SymbolKind.Field: field = (FieldSymbol)member; Debug.Assert((object)(field.AssociatedSymbol as EventSymbol) == null, "Didn't expect to find a field-like event backing field in the member list."); break; case SymbolKind.Event: field = ((EventSymbol)member).AssociatedField; break; default: throw ExceptionUtilities.UnexpectedValue(member.Kind); } if ((object)field == null) { continue; } // pointers are unmanaged // NOTE: If we do not check HasPointerType, we will unconditionally // bind Type and that may cause infinite recursion. // HasPointerType can use syntax directly and break recursion. if (field.HasPointerType) { continue; } TypeSymbol fieldType = field.Type; NamedTypeSymbol fieldNamedType = fieldType as NamedTypeSymbol; if ((object)fieldNamedType == null) { if (fieldType.IsManagedType) { return(true); } } else { // NOTE: don't use IsManagedType on a NamedTypeSymbol - that could lead // to infinite recursion. switch (IsManagedTypeHelper(fieldNamedType)) { case ThreeState.True: return(true); case ThreeState.False: continue; case ThreeState.Unknown: if (DependsOnDefinitelyManagedType(fieldNamedType, partialClosure)) { return(true); } continue; } } } } return(false); }
private static (bool definitelyManaged, bool hasGenerics) DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet <Symbol> partialClosure) { Debug.Assert((object)type != null); var hasGenerics = false; if (partialClosure.Add(type)) { foreach (var member in type.GetInstanceFieldsAndEvents()) { // Only instance fields (including field-like events) affect the outcome. FieldSymbol field; switch (member.Kind) { case SymbolKind.Field: field = (FieldSymbol)member; Debug.Assert((object)(field.AssociatedSymbol as EventSymbol) == null, "Didn't expect to find a field-like event backing field in the member list."); break; case SymbolKind.Event: field = ((EventSymbol)member).AssociatedField; break; default: throw ExceptionUtilities.UnexpectedValue(member.Kind); } if ((object)field == null) { continue; } // pointers are unmanaged // NOTE: If we do not check HasPointerType, we will unconditionally // bind Type and that may cause infinite recursion. // HasPointerType can use syntax directly and break recursion. if (field.HasPointerType) { continue; } TypeSymbol fieldType = field.Type.TypeSymbol; NamedTypeSymbol fieldNamedType = fieldType as NamedTypeSymbol; if ((object)fieldNamedType == null) { if (fieldType.IsManagedType) { return(true, hasGenerics); } } else { var result = IsManagedTypeHelper(fieldNamedType); hasGenerics = hasGenerics || result.hasGenerics; // NOTE: don't use ManagedKind.get on a NamedTypeSymbol - that could lead // to infinite recursion. switch (result.isManaged) { case ThreeState.True: return(true, hasGenerics); case ThreeState.False: continue; case ThreeState.Unknown: if (!fieldNamedType.OriginalDefinition.KnownCircularStruct) { var(definitelyManaged, childHasGenerics) = DependsOnDefinitelyManagedType(fieldNamedType, partialClosure); hasGenerics = hasGenerics || childHasGenerics; if (definitelyManaged) { return(true, hasGenerics); } } continue; } } } } return(false, hasGenerics); }
private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet<Symbol> partialClosure) { Debug.Assert((object)type != null); // NOTE: unlike in StructDependsClosure, we don't have to check for expanding cycles, // because as soon as we see something with non-zero arity we kick out (generic => managed). if (partialClosure.Add(type)) { foreach (var member in type.GetInstanceFieldsAndEvents()) { // Only instance fields (including field-like events) affect the outcome. FieldSymbol field; switch (member.Kind) { case SymbolKind.Field: field = (FieldSymbol)member; Debug.Assert((object)(field.AssociatedSymbol as EventSymbol) == null, "Didn't expect to find a field-like event backing field in the member list."); break; case SymbolKind.Event: field = ((EventSymbol)member).AssociatedField; break; default: throw ExceptionUtilities.UnexpectedValue(member.Kind); } if ((object)field == null) { continue; } // pointers are unmanaged // NOTE: If we do not check HasPointerType, we will unconditionally // bind Type and that may cause infinite recursion. // HasPointerType can use syntax directly and break recursion. if (field.HasPointerType) { continue; } TypeSymbol fieldType = field.Type; NamedTypeSymbol fieldNamedType = fieldType as NamedTypeSymbol; if ((object)fieldNamedType == null) { if (fieldType.IsManagedType) { return true; } } else { // NOTE: don't use IsManagedType on a NamedTypeSymbol - that could lead // to infinite recursion. switch (IsManagedTypeHelper(fieldNamedType)) { case ThreeState.True: return true; case ThreeState.False: continue; case ThreeState.Unknown: if (DependsOnDefinitelyManagedType(fieldNamedType, partialClosure)) { return true; } continue; } } } } return false; }