/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { // Check explicit implementation overrides before implicit methods IMethodDefinition foundImplementation = null; foreach (var classInHierarchy in classHierarchyChain) { IMethodDefinition specializedImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (specializedImplementation != null) { foundImplementation = specializedImplementation; break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }
private void NoteDispatch(IMethodDefinition compileTimeMethod, IMethodDefinition runtimeMethod, ITypeDefinition runtimeType) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(compileTimeMethod)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(runtimeMethod)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(runtimeType)); // Note: runtimeType may not be type containing runtimeMethod, but it will be a subtype of it. // Might want a contract for this. if (virtualCallsInDemand.NoteVirtualMethodMayDispatchToMethod(compileTimeMethod, runtimeMethod)) { AddToWorklist(runtimeMethod); analysisReasons.NoteMethodReachableForReason(runtimeMethod, analysisReasons.MethodReachedByDispatchAgainstVirtualMethodWithTypeConstructed(compileTimeMethod, runtimeType)); } }
private void ConstructionFound(ITypeDefinition t) { Contract.Requires(t != null); Contract.Requires(!(t is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(t)); Contract.Requires(GarbageCollectHelper.TypeIsConstructable(t)); Contract.Ensures(this.constructed.Contains(t)); //Console.WriteLine("Found construction of {0}", t); if (this.constructed.Contains(t)) { return; } this.constructed.Add(t); // t-devinc: should change AllSuperTypes, etc. to include t foreach (var baseclass in new ITypeDefinition[] { t }.Concat(GarbageCollectHelper.AllSuperTypes(t))) { ITypeDefinition unspecializedBaseClass = GarbageCollectHelper.UnspecializeAndResolveTypeReference(baseclass); foreach (var m in unspecializedBaseClass.Methods) { if (m.IsVirtual && VirtualMethodIsInDemand(m)) { ICollection <IMethodDefinition> implementationsOfMForT = GarbageCollectHelper.Implements(t, unspecializedBaseClass, m); Contract.Assert(implementationsOfMForT.Count() > 0); foreach (IMethodDefinition mprime in implementationsOfMForT) { NoteDispatch(m, GarbageCollectHelper.UnspecializeAndResolveMethodReference(mprime), t); } } } } // If a type is constructed then its Finalize method may be called ICollection <IMethodDefinition> implementationsOfFinalizeForT = GarbageCollectHelper.Implements(t, systemObjectType, systemObjectFinalizeMethod); Contract.Assert(implementationsOfFinalizeForT.Count() == 1); // t-devinc: Need to to add reason for this this.AddToWorklist(GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationsOfFinalizeForT.First())); }
/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { IMethodDefinition foundImplementation = null; // If this is a method defined on an inteface, we must first search the hierarchy for explicit implementations, // since an explicit implementation on a base type supercedes an implicit implementation on a derived type if (m.ContainingTypeDefinition.IsInterface) { foreach (var classInHierarchy in classHierarchyChain) { foreach (IMethodImplementation methodImplementation in classInHierarchy.ExplicitImplementationOverrides) { if (methodImplementation.ImplementedMethod.InternedKey == mSpecializedForDerived.InternedKey) { foundImplementation = methodImplementation.ImplementingMethod.ResolvedMethod; break; } } if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // If we found an explicit implementation, don't seach for an implicit one if (foundImplementation == null) { foreach (var classInHierarchy in classHierarchyChain) { foundImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }