public override void TransferStateTo(Visitor targetVisitor) { base.TransferStateTo(targetVisitor); Specializer target = targetVisitor as Specializer; if (target == null) { return; } target.args = this.args; target.pars = this.pars; target.CurrentMethod = this.CurrentMethod; target.CurrentType = this.CurrentType; }
public virtual Member VisitMemberReference(Member member) { if (member == null) { return(null); } TypeNode specializedType = this.VisitTypeReference(member.DeclaringType); if (specializedType == member.DeclaringType || specializedType == null) { return(member); } return(Specializer.GetCorrespondingMember(member, specializedType)); }
private static void TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(Method dupMethod, Method closureMethod, Method closureInstanceMethod, out TypeNodeList actuals) { // make sure that if we copy it from a generic context, the method becomes generic in the target context // if we are copying from the same declaring type (not instantiated), then don't add enclosing type parameters. var originals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null ? null : closureMethod.DeclaringType.ConsolidatedTemplateParameters; if (originals != null) { originals = originals.Clone(); } if (closureMethod.TemplateParameters != null && closureMethod.TemplateParameters.Count > 0) { if (originals == null) { originals = closureMethod.TemplateParameters.Clone(); } else { foreach (var tp in closureMethod.TemplateParameters) { originals.Add(tp); } } } if (originals == null) { actuals = null; return; } actuals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null ? null : closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments.Clone(); if (closureInstanceMethod.TemplateArguments != null && closureInstanceMethod.TemplateArguments.Count > 0) { if (actuals == null) { actuals = closureInstanceMethod.TemplateArguments.Clone(); } else { foreach (var tp in closureInstanceMethod.TemplateArguments) { actuals.Add(tp); } } } var declaringModule = dupMethod.DeclaringType.DeclaringModule; // new method formals var tparams = originals.Clone(); for (int i = 0; i < originals.Count; i++) { // setup forwarding of tparams to method params ITypeParameter tp = originals[i] as ITypeParameter; TypeNode mtp = NewEqualMethodTypeParameter(tp, dupMethod, i); tparams[i] = mtp; } var specializer = new Specializer(declaringModule, originals, tparams); // System.Console.WriteLine("Made {0} a generic method", dupMethod.FullName); dupMethod.TemplateParameters = tparams; dupMethod.IsGeneric = true; specializer.VisitMethod(dupMethod); var bodySpecializer = new MethodBodySpecializer(declaringModule, originals, tparams); bodySpecializer.CurrentType = dupMethod.DeclaringType; bodySpecializer.CurrentMethod = dupMethod; bodySpecializer.VisitBlock(dupMethod.Body); }
private static void DuplicateMember(DuplicatorForContractsAndClosures dup, FindClosurePartsToDuplicate fmd, int memindex, TypeNode targetType) { Member mem = fmd.MembersToDuplicate[memindex]; TypeNode nestedType = mem as TypeNode; Method closureInstanceMethod = mem as Method; Method closureMethodTemplate = closureInstanceMethod; while (closureMethodTemplate != null && closureMethodTemplate.Template != null) { closureMethodTemplate = closureMethodTemplate.Template; } if (nestedType != null) { // if nested type is nested inside another type to be duplicated, skip it if (nestedType.DeclaringType != null && fmd.MembersToDuplicate.Contains(nestedType.DeclaringType)) return; // For call-site wrappers, we end up having multiple methods from the same original contract method // thus we have to avoid duplicating the same closure type multiple times. var duplicatedNestedType = FindExistingClosureType(targetType, nestedType); if (duplicatedNestedType == null) { dup.FindTypesToBeDuplicated(new TypeNodeList(nestedType)); // if parent type is generic and different from the target type, then we may have to include all the // consolidated type parameters excluding the ones from the target type. TypeNodeList originalTemplateParameters = FindNonStandardTypeParametersToBeDuplicated(fmd, nestedType, targetType); duplicatedNestedType = dup.Visit(mem) as TypeNode; if (originalTemplateParameters != null) { int parentParameters = (targetType.ConsolidatedTemplateParameters == null) ? 0 : targetType.ConsolidatedTemplateParameters.Count; if (parentParameters > 0 && (nestedType.DeclaringType.ConsolidatedTemplateParameters == null || nestedType.DeclaringType.ConsolidatedTemplateParameters.Count == 0)) { // type is turning from non-generic to generic Debug.Assert(false); } TypeNodeList dupTPs = DuplicateTypeParameterList(originalTemplateParameters, parentParameters, duplicatedNestedType); duplicatedNestedType.TemplateParameters = dupTPs; dup.SafeAddMember(targetType, duplicatedNestedType, mem); // populate the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //var oldSelfInstanceType = nestedType.GetGenericTemplateInstance(targetModule, nestedType.ConsolidatedTemplateParameters); //var newSelfInstanceType = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = newSelfInstanceType; // specialize duplicated type var specializer = new Specializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); specializer.VisitTypeParameterList(dupTPs); // for constraints etc. specializer.VisitTypeNode(duplicatedNestedType); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); bodySpecializer.Visit(duplicatedNestedType); // after copying the closure class, clear the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = null; } else { dup.SafeAddMember(targetType, duplicatedNestedType, mem); } } else { // already copied type previously dup.DuplicateFor[nestedType.UniqueKey] = duplicatedNestedType; #if false if (nestedType.ConsolidatedTemplateArguments != null) { // populate the self specialization forwarding // NestedType<Self1,Self2> -> NewNestedType<NewSelf1,NewSelf2> var origSelfInstantiation = nestedType.DeclaringType.GetTemplateInstance(nestedType, nestedType.DeclaringType.TemplateParameters).GetNestedType(nestedType.Name); var newSelfInstantiation = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); dup.DuplicateFor[origSelfInstantiation.UniqueKey] = newSelfInstantiation; // Also forward ContractType<A,B>.NestedType instantiated at target ContractType<X,Y>.NestedType to // TargetType<X,Y,Z>.NewNestedType<X,Y>, since this reference may appear in the contract itself. var consolidatedContractTemplateArguments = sourceMethod.DeclaringType.ConsolidatedTemplateArguments; var instantiatedNestedOriginal = nestedType.DeclaringType.GetGenericTemplateInstance(targetModule, consolidatedContractTemplateArguments).GetNestedType(nestedType.Name); dup.DuplicateFor[instantiatedNestedOriginal.UniqueKey] = duplicatedNestedType.GetTemplateInstance(targetType, consolidatedContractTemplateArguments); } else { Debugger.Break(); } #endif } } else if (closureInstanceMethod != null && closureMethodTemplate != null && !fmd.MembersToDuplicate.Contains(closureMethodTemplate.DeclaringType)) { Method closureMethod = closureMethodTemplate; Debug.Assert(closureMethod.Template == null); //var m = FindExistingClosureMethod(targetType, closureMethod); Method m = null; // why did we ever try to find an existing one? This can capture a completely unrelated closure that happens to match by name. if (m == null) { Method dupMethod = dup.Visit(closureMethod) as Method; TypeNodeList actuals; TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(dupMethod, closureMethod, closureInstanceMethod, out actuals); // now setup a forwarding from the closureInstanceMethod to the new instance Method newInstance = dupMethod.GetTemplateInstance(dupMethod.DeclaringType, actuals); newInstance.Name = dupMethod.Name; dup.DuplicateFor[closureInstanceMethod.UniqueKey] = newInstance; dup.SafeAddMember(targetType, dupMethod, closureMethod); // special case when resulting method is generic and instance, then we need to make "this" a parameter // and the method static, otherwise, there's a type mismatch between the "this" and the explicitly generic parameter types used // in arguments. var originalParentTemplateParameters = closureMethod.DeclaringType.ConsolidatedTemplateParameters; if (!dupMethod.IsStatic && originalParentTemplateParameters != null && originalParentTemplateParameters.Count > 0) { var oldThis = dupMethod.ThisParameter; oldThis.Type = dup.PossiblyRemapContractClassToInterface(oldThis.Type); dupMethod.Flags |= MethodFlags.Static; dupMethod.CallingConvention &= ~CallingConventionFlags.HasThis; var oldParameters = dupMethod.Parameters; dupMethod.Parameters = new ParameterList(oldParameters.Count + 1); dupMethod.Parameters.Add(oldThis); // make explicit for (int i = 0; i < oldParameters.Count; i++) { dupMethod.Parameters.Add(oldParameters[i]); } // now need to specialize transforming original parameters into first n method template parameters var targetTypeParameters = new TypeNodeList(originalParentTemplateParameters.Count); for (int i = 0; i < originalParentTemplateParameters.Count; i++) { targetTypeParameters.Add(dupMethod.TemplateParameters[i]); } var specializer = new Specializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); specializer.VisitMethod(dupMethod); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); bodySpecializer.VisitMethod(dupMethod); } } } else if (closureInstanceMethod != null) { var m = FindExistingClosureMethod(targetType, closureInstanceMethod); if (m == null) { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } } else { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } }
private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext) { bool isProtected = IsProtected(templateMethod); Identifier name = templateMethod.Name; if (virtcall) { if (virtcallConstraint != null) { name = Identifier.For("CV$" + name.Name); } else { name = Identifier.For("V$" + name.Name); } } else { name = Identifier.For("NV$" + name.Name); } Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType); TypeNodeList typeParameters = null; TypeNodeList typeParameterFormals = new TypeNodeList(); TypeNodeList typeParameterActuals = new TypeNodeList(); if (templateMethod.TemplateParameters != null) { dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters); typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters); for (int i = 0; i < typeParameters.Count; i++) { typeParameterFormals.Add(typeParameters[i]); typeParameterActuals.Add(templateMethod.TemplateParameters[i]); } } ITypeParameter constraintTypeParam = null; if (virtcallConstraint != null) { if (typeParameters == null) { typeParameters = new TypeNodeList(); } var constraint = templateMethod.DeclaringType; var classConstraint = constraint as Class; if (classConstraint != null) { var classParam = new MethodClassParameter(); classParam.BaseClass = classConstraint; classParam.Name = Identifier.For("TC"); classParam.DeclaringType = wrapperType; typeParameters.Add(classParam); constraintTypeParam = classParam; } else { var mtp = new MethodTypeParameter(); Interface intf = constraint as Interface; if (intf != null) { mtp.Interfaces.Add(intf); } mtp.Name = Identifier.For("TC"); mtp.DeclaringType = wrapperType; typeParameters.Add(mtp); constraintTypeParam = mtp; } } var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters; if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) { var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters; for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) { typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]); typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]); } } Specializer spec = null; if (typeParameterActuals.Count > 0) { spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals); } var parameters = new ParameterList(); var asTypeConstraintTypeParam = constraintTypeParam as TypeNode; if (!isProtected && !templateMethod.IsStatic) { TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam); parameters.Add(new Parameter(Identifier.For("@this"), thisType)); } for (int i = 0; i < templateMethod.Parameters.Count; i++) { parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i])); } var retType = dup.VisitTypeReference(templateMethod.ReturnType); if (spec != null) { parameters = spec.VisitParameterList(parameters); retType = spec.VisitTypeReference(retType); } var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null); RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod); if (isProtected) { wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract; wrapperMethod.CallingConvention = templateMethod.CallingConvention; } else { wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly; } if (constraintTypeParam != null) { constraintTypeParam.DeclaringMember = wrapperMethod; } if (typeParameters != null) { if (spec != null) { typeParameters = spec.VisitTypeParameterList(typeParameters); } wrapperMethod.IsGeneric = true; wrapperMethod.TemplateParameters = typeParameters; } // create body var sl = new StatementList(); Block b = new Block(sl); // insert requires AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract); // create original call var targetType = templateType; if (isProtected) { // need to use base chain instantiation of target type. targetType = instanceMethod.DeclaringType; } else { if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0) { // need selfinstantiation targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters); } } Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod); if (targetMethod.IsGeneric) { if (typeParameters.Count > targetMethod.TemplateParameters.Count) { // omit the extra constrained type arg. TypeNodeList origArgs = new TypeNodeList(); for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) { origArgs.Add(typeParameters[i]); } targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs); } else { targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters); } } MethodCall call; NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call; if (isProtected) { var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } else if (templateMethod.IsStatic) { var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType); } else { var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1); for (int i = 1; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } if (constraintTypeParam != null) { call.Constraint = asTypeConstraintTypeParam; } if (HelperMethods.IsVoidType(templateMethod.ReturnType)) { sl.Add(new ExpressionStatement(call,callingContext)); sl.Add(new Return(callingContext)); } else { sl.Add(new Return(call,callingContext)); } wrapperMethod.Body = b; wrapperType.Members.Add(wrapperMethod); return wrapperMethod; }
private TypeNode CreateWrapperType(TypeNode original, TypeNode declaringWrapper/*?*/) { TypeNode wrapper = null; switch (original.NodeType) { case NodeType.Class: wrapper = CreateWrapperClass((Class)original); break; case NodeType.Struct: wrapper = CreateWrapperStruct((Struct)original); break; case NodeType.Interface: wrapper = CreateWrapperInterface((Interface)original); break; default: throw new Exception("Don' know how to produce a wrapper type for " + original.NodeType.ToString()); } if (declaringWrapper != null) { wrapper.DeclaringType = declaringWrapper; } // need to specialize w.r.t type parameters due to type parameter bounds referring to each other var origConsolidatedTemplateParameters = original.ConsolidatedTemplateParameters; var wrapperConsolideateTemplateParameters = wrapper.ConsolidatedTemplateParameters; if (origConsolidatedTemplateParameters != null && origConsolidatedTemplateParameters.Count > 0) { var spec = new Specializer(this.assemblyBeingRewritten, origConsolidatedTemplateParameters, wrapperConsolideateTemplateParameters); spec.VisitTypeParameterList(wrapper.TemplateParameters); } return wrapper; }
/// <summary> /// There are 2 cases: /// 1) Task has no return value. In this case, we emit /// void CheckMethod(Task t) { /// var ae = t.Exception as AggregateException; /// if (ae != null) { ae.Handle(this.CheckException); throw ae; } /// } /// bool CheckException(Exception e) { /// .. check exceptional post /// } /// 2) Task(T) returns a T value /// T CheckMethod(Task t) { /// try { /// var r = t.Result; /// .. check ensures on r .. /// return r; /// } /// catch (AggregateException ae) { /// ae.Handle(this.CheckException); /// throw; /// } /// } /// bool CheckException(Exception e) { /// .. check exceptional post /// } /// </summary> public EmitAsyncClosure(Method from, Rewriter parent) { this.fromMethod = from; this.parent = parent; this.checkMethodId = Identifier.For("CheckPost"); this.checkExceptionMethodId = Identifier.For("CheckException"); this.declaringType = from.DeclaringType; var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure"); this.closureClass = new Class(declaringType.DeclaringModule, declaringType, null, TypeFlags.NestedPrivate, null, Identifier.For(closureName), SystemTypes.Object, null, null); declaringType.Members.Add(this.closureClass); RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass); this.dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType); var taskType = from.ReturnType; var taskArgs = taskType.TemplateArguments == null ? 0 : taskType.TemplateArguments.Count; this.AggregateExceptionType = new Cache<TypeNode>(() => HelperMethods.FindType(parent.assemblyBeingRewritten, StandardIds.System, Identifier.For("AggregateException"))); this.Func2Type = new Cache<TypeNode>(() => HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2"))); if (from.IsGeneric) { this.closureClass.TemplateParameters = new TypeNodeList(); var parentCount = this.declaringType.ConsolidatedTemplateParameters == null ? 0 : this.declaringType.ConsolidatedTemplateParameters.Count; for (int i = 0; i < from.TemplateParameters.Count; i++) { var tp = HelperMethods.NewEqualTypeParameter(dup, (ITypeParameter)from.TemplateParameters[i], this.closureClass, parentCount + i); this.closureClass.TemplateParameters.Add(tp); } this.closureClass.IsGeneric = true; this.closureClass.EnsureMangledName(); this.forwarder = new Specializer(this.declaringType.DeclaringModule, from.TemplateParameters, this.closureClass.TemplateParameters); this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters); taskType = this.forwarder.VisitTypeReference(taskType); } else { this.closureClassInstance = this.closureClass; } var taskTemplate = HelperMethods.Unspecialize(taskType); var continueWithCandidates = taskTemplate.GetMembersNamed(Identifier.For("ContinueWith")); Method continueWithMethod = null; for (int i = 0; i < continueWithCandidates.Count; i++) { var cand = continueWithCandidates[i] as Method; if (cand == null) continue; if (taskArgs == 0) { if (cand.IsGeneric) continue; if (cand.ParameterCount != 1) continue; var p = cand.Parameters[0]; var ptype = p.Type; var ptypeTemplate = ptype; while (ptypeTemplate.Template != null) { ptypeTemplate = ptypeTemplate.Template; } if (ptypeTemplate.Name.Name != "Action`1") continue; continueWithMethod = cand; break; } else { if (!cand.IsGeneric) continue; if (cand.TemplateParameters.Count != 1) continue; if (cand.ParameterCount != 1) continue; var p = cand.Parameters[0]; var ptype = p.Type; var ptypeTemplate = ptype; while (ptypeTemplate.Template != null) { ptypeTemplate = ptypeTemplate.Template; } if (ptypeTemplate.Name.Name != "Func`2") continue; // now create instance, first of task var taskInstance = taskTemplate.GetTemplateInstance(this.closureClass.DeclaringModule, taskType.TemplateArguments[0]); var candMethod = taskInstance.GetMembersNamed(Identifier.For("ContinueWith"))[i] as Method; continueWithMethod = candMethod.GetTemplateInstance(null, taskType.TemplateArguments[0]); break; } } if (continueWithMethod != null) { this.continuewithMethod = continueWithMethod; EmitCheckMethod(taskType, taskArgs == 1); var ctor = new InstanceInitializer(this.closureClass, null, null, null); this.constructor = ctor; ctor.CallingConvention = CallingConventionFlags.HasThis; ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig; ctor.Body = new Block(new StatementList( new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, SystemTypes.Object.GetConstructor()), new ExpressionList())), new Return() )); this.closureClass.Members.Add(ctor); } // now that we added the ctor and the check method, let's instantiate the closure class if necessary if (this.closureClassInstance == null) { var consArgs = new TypeNodeList(); var args = new TypeNodeList(); var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null ? 0 : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count; for (int i = 0; i < parentCount; i++) { consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]); } var methodCount = from.TemplateParameters == null ? 0: from.TemplateParameters.Count; for (int i = 0; i < methodCount; i++) { consArgs.Add(from.TemplateParameters[i]); args.Add(from.TemplateParameters[i]); } this.closureClassInstance = (Class)this.closureClass.GetConsolidatedTemplateInstance(this.parent.assemblyBeingRewritten, closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs); } // create closure initializer for context method this.ClosureLocal = new Local(this.ClosureClass); this.ClosureInitializer = new Block(new StatementList()); this.ClosureInitializer.Statements.Add(new AssignmentStatement(this.ClosureLocal, new Construct(new MemberBinding(null, this.Ctor), new ExpressionList()))); }
/// <summary> /// If there is an anonymous delegate within a postcondition, then there /// will be a call to a delegate constructor. /// That call looks like "d..ctor(o,m)" where d is the type of the delegate. /// There are two cases depending on whether the anonymous delegate captured /// anything. In both cases, m is the method implementing the anonymous delegate. /// (1) It does capture something. Then o is the instance of the closure class /// implementing the delegate, and m is an instance method in the closure /// class. /// (2) It does *not* capture anything. Then o is the literal for null and /// m is a static method that was added directly to the class. /// /// This method will cause the method (i.e., m) to be visited to collect any /// Result<T>() expressions that occur in it. /// </summary> /// <param name="cons">The AST representing the call to the constructor /// of the delegate type.</param> /// <returns>Whatever the base visitor returns</returns> public override Expression VisitConstruct(Construct cons) { if (cons.Type is DelegateNode) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; if (!HelperMethods.IsCompilerGenerated(m)) goto JustVisit; Contract.Assume(m != null); m = Definition(m); this.delegateNestingLevel++; TypeNode savedClosureClass = this.currentClosureClassInstance; Method savedClosureMethod = this.currentClosureMethod; Expression savedCurrentAccessToTopLevelClosure = this.currentAccessToTopLevelClosure; try { this.currentClosureMethod = m; if (m.IsStatic) { this.currentClosureClassInstance = null; // no closure object } else { this.currentClosureClassInstance = cons.Operands[0].Type; if (savedClosureClass == null) { // Then this is the top-level closure class. this.topLevelClosureClassInstance = this.currentClosureClassInstance; this.topLevelClosureClassDefinition = Definition(this.topLevelClosureClassInstance); this.currentAccessToTopLevelClosure = new This(this.topLevelClosureClassDefinition); this.properlyInstantiatedFieldType = this.originalLocalForResult.Type; if (this.topLevelMethodFormals != null) { Contract.Assume(this.topLevelClosureClassDefinition.IsGeneric); Contract.Assume(topLevelClosureClassDefinition.TemplateParameters.Count >= this.topLevelMethodFormals.Count); // replace method type parameters in result properly with last n corresponding type parameters of closure class TypeNodeList closureFormals = topLevelClosureClassDefinition.TemplateParameters; if (closureFormals.Count > this.topLevelMethodFormals.Count) { int offset = closureFormals.Count - this.topLevelMethodFormals.Count; closureFormals = new TypeNodeList(this.topLevelMethodFormals.Count); for (int i = 0; i < this.topLevelMethodFormals.Count; i++) { closureFormals.Add(topLevelClosureClassDefinition.TemplateParameters[i + offset]); } } Duplicator dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType); Specializer spec = new Specializer(this.declaringType.DeclaringModule, topLevelMethodFormals, closureFormals); var type = dup.VisitTypeReference(this.originalLocalForResult.Type); type = spec.VisitTypeReference(type); this.properlyInstantiatedFieldType = type; } } else { while (currentClosureClassInstance.Template != null) currentClosureClassInstance = currentClosureClassInstance.Template; // Find the field in this.closureClass that the C# compiler generated // to point to the top-level closure foreach (Member mem in this.currentClosureClassInstance.Members) { Field f = mem as Field; if (f == null) continue; if (f.Type == this.topLevelClosureClassDefinition) { var consolidatedTemplateParams = this.currentClosureClassInstance.ConsolidatedTemplateParameters; TypeNode thisType; if (consolidatedTemplateParams != null && consolidatedTemplateParams.Count > 0) { thisType = this.currentClosureClassInstance.GetGenericTemplateInstance(this.assemblyBeingRewritten, consolidatedTemplateParams); } else { thisType = this.currentClosureClassInstance; } this.currentAccessToTopLevelClosure = new MemberBinding(new This(thisType), f); break; } } } } this.VisitBlock(m.Body); } finally { this.delegateNestingLevel--; this.currentClosureMethod = savedClosureMethod; this.currentClosureClassInstance = savedClosureClass; this.currentAccessToTopLevelClosure = savedCurrentAccessToTopLevelClosure; } } JustVisit: return base.VisitConstruct(cons); }
public virtual TypeNode/*!*/ GetTemplateInstance(Module module, TypeNode referringType, TypeNode declaringType, TypeNodeList templateArguments) { TypeNodeList templateParameters = this.TemplateParameters; if(module == null || templateArguments == null || (declaringType == null && (templateParameters == null || templateParameters.Count == 0))) return this; if(this.IsGeneric) { referringType = null; module = TypeNode.cachingModuleForGenericInstances; } bool notFullySpecialized; Identifier/*!*/ uniqueMangledName; Identifier mangledName = this.GetMangledTemplateInstanceName(templateArguments, out uniqueMangledName, out notFullySpecialized); TypeNode result; Identifier dummyId; this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out dummyId); if(result != null) return result; if(this.NewTemplateInstanceIsRecursive) return this; //An instance of this template is trying to instantiate the template again lock(Module.GlobalLock) { Identifier unusedMangledName; this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out unusedMangledName); if(result != null) return result; //^ assume unusedMangledName != null; TypeNodeList consolidatedTemplateArguments = declaringType == null ? templateArguments : declaringType.GetConsolidatedTemplateArguments(templateArguments); Duplicator duplicator = new Duplicator(module, referringType); duplicator.RecordOriginalAsTemplate = true; duplicator.SkipBodies = true; duplicator.TypesToBeDuplicated[this.UniqueKey] = this; result = duplicator.VisitTypeNode(this, unusedMangledName, consolidatedTemplateArguments, this.Template == null ? this : this.Template, true); //^ assume result != null; if(module == this.DeclaringModule) { if(this.TemplateInstances == null) this.TemplateInstances = new TypeNodeList(); this.TemplateInstances.Add(result); } result.Name = unusedMangledName; result.Name.SourceContext = this.Name.SourceContext; result.fullName = null; if(this.IsGeneric) result.DeclaringModule = this.DeclaringModule; result.DeclaringType = this.IsGeneric || referringType == null ? declaringType : referringType; result.Template = this; result.templateParameters = new TypeNodeList(); result.consolidatedTemplateParameters = new TypeNodeList(); result.templateArguments = templateArguments; result.consolidatedTemplateArguments = consolidatedTemplateArguments; result.IsNotFullySpecialized = notFullySpecialized || (declaringType != null && declaringType.IsNotFullySpecialized); module.StructurallyEquivalentType[unusedMangledName.UniqueIdKey] = result; module.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result; Specializer specializer = new Specializer(module, this.ConsolidatedTemplateParameters, consolidatedTemplateArguments); specializer.VisitTypeNode(result); TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask; for(int i = 0, m = templateArguments.Count; i < m; i++) { TypeNode t = templateArguments[i]; if(t == null) continue; if(t is TypeParameter || t is ClassParameter || t.IsNotFullySpecialized) continue; visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask); } result.Flags &= ~TypeFlags.VisibilityMask; result.Flags |= visibility; if(this.IsGeneric) return result; return result; } }
public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList typeArguments) { if(referringType == null || this.DeclaringType == null) { Debug.Assert(false); return this; } if(this.IsGeneric) referringType = this.DeclaringType; if(referringType != this.DeclaringType && referringType.DeclaringModule == this.DeclaringType.DeclaringModule) return this.GetTemplateInstance(this.DeclaringType, typeArguments); if(referringType.structurallyEquivalentMethod == null) referringType.structurallyEquivalentMethod = new TrivialHashtableUsingWeakReferences(); Module module = referringType.DeclaringModule; if(module == null) return this; int n = typeArguments == null ? 0 : typeArguments.Count; if(n == 0 || typeArguments == null) return this; StringBuilder sb = new StringBuilder(this.Name.ToString()); sb.Append('<'); for(int i = 0; i < n; i++) { TypeNode ta = typeArguments[i]; if(ta == null) continue; sb.Append(ta.FullName); if(i < n - 1) sb.Append(','); } sb.Append('>'); Identifier mangledName = Identifier.For(sb.ToString()); lock(this) { Method m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey]; int counter = 1; while(m != null) { if(m.template == this && Method.TypeListsAreEquivalent(m.TemplateArguments, typeArguments)) return m; mangledName = Identifier.For(mangledName.ToString() + counter++); m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey]; } Duplicator duplicator = new Duplicator(referringType.DeclaringModule, referringType); duplicator.RecordOriginalAsTemplate = true; duplicator.SkipBodies = true; Method result = duplicator.VisitMethod(this); //^ assume result != null; result.Attributes = this.Attributes; //These do not get specialized, but may need to get normalized result.Name = mangledName; result.fullName = null; result.template = this; result.TemplateArguments = typeArguments; TypeNodeList templateParameters = result.TemplateParameters; result.TemplateParameters = null; result.IsNormalized = true; if(!this.IsGeneric) { ParameterList pars = this.Parameters; ParameterList rpars = result.Parameters; if(pars != null && rpars != null && rpars.Count >= pars.Count) for(int i = 0, count = pars.Count; i < count; i++) { Parameter p = pars[i]; Parameter rp = rpars[i]; if(p == null || rp == null) continue; rp.Attributes = p.Attributes; //These do not get specialized, but may need to get normalized } } if(!this.IsGeneric && !(result.IsStatic) && this.DeclaringType != referringType) { result.Flags &= ~(MethodFlags.Virtual | MethodFlags.NewSlot); result.Flags |= MethodFlags.Static; result.CallingConvention &= ~CallingConventionFlags.HasThis; result.CallingConvention |= CallingConventionFlags.ExplicitThis; ParameterList pars = result.Parameters; if(pars == null) result.Parameters = pars = new ParameterList(); Parameter thisPar = new Parameter(StandardIds.This, this.DeclaringType); pars.Add(thisPar); for(int i = pars.Count - 1; i > 0; i--) pars[i] = pars[i - 1]; pars[0] = thisPar; } referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey] = result; Specializer specializer = new Specializer(module, templateParameters, typeArguments); specializer.VisitMethod(result); if(this.IsGeneric) { result.DeclaringType = this.DeclaringType; return result; } if(this.IsAbstract) return result; referringType.Members.Add(result); return result; } }
public EmitAsyncClosure(Method from, Rewriter rewriter) { Contract.Requires(from != null); Contract.Requires(from.DeclaringType != null); Contract.Requires(rewriter != null); if (TaskExtensionsTypeNode == null) { throw new InvalidOperationException( "Can't generate async closure because System.Threading.Tasks.TaskExceptions class is unavailable."); } this.rewriter = rewriter; this.declaringType = from.DeclaringType; var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure"); this.closureClass = new Class( declaringModule: declaringType.DeclaringModule, declaringType: declaringType, attributes: null, flags: TypeFlags.NestedPrivate, Namespace: null, name: Identifier.For(closureName), baseClass: SystemTypes.Object, interfaces: null, members: null); declaringType.Members.Add(this.closureClass); RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass); var taskType = from.ReturnType; this.aggregateExceptionType = new Cache<TypeNode>(() => HelperMethods.FindType(rewriter.AssemblyBeingRewritten, StandardIds.System, Identifier.For("AggregateException"))); this.func2Type = new Cache<TypeNode>(() => HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2"))); // Should distinguish between generic enclosing method and non-generic method in enclosing type. // In both cases generated closure should be generic. var enclosingTemplateParameters = GetGenericTypesFrom(from); if (!enclosingTemplateParameters.IsNullOrEmpty()) { this.closureClass.TemplateParameters = CreateTemplateParameters(closureClass, enclosingTemplateParameters, declaringType); this.closureClass.IsGeneric = true; this.closureClass.EnsureMangledName(); this.forwarder = new Specializer( targetModule: this.declaringType.DeclaringModule, pars: enclosingTemplateParameters, args: this.closureClass.TemplateParameters); this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters); taskType = this.forwarder.VisitTypeReference(taskType); for (int i = 0; i < enclosingTemplateParameters.Count; i++) { this.genericTypeMapper.AddMapping(enclosingTemplateParameters[i], closureClass.TemplateParameters[i]); } } else { this.closureClassInstance = this.closureClass; } this.checkMethodTaskType = taskType; // Emiting CheckPost method declaration EmitCheckPostMethodCore(checkMethodTaskType); // Generate closure constructor. // Constructor should be generated AFTER visiting type parameters in // the previous block of code. Otherwise current class would not have // appropriate number of generic arguments! var ctor = CreateConstructor(closureClass); closureClass.Members.Add(ctor); // Now that we added the ctor and the check method, let's instantiate the closure class if necessary if (this.closureClassInstance == null) { var consArgs = new TypeNodeList(); var args = new TypeNodeList(); var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null ? 0 : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count; for (int i = 0; i < parentCount; i++) { consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]); } if (!enclosingTemplateParameters.IsNullOrEmpty()) { for (int i = 0; i < enclosingTemplateParameters.Count; i++) { consArgs.Add(enclosingTemplateParameters[i]); args.Add(enclosingTemplateParameters[i]); } } this.closureClassInstance = (Class) this.closureClass.GetConsolidatedTemplateInstance(this.rewriter.AssemblyBeingRewritten, closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs); } // create closure initializer for context method this.closureLocal = new Local(this.ClosureClass); this.ClosureInitializer = new Block(new StatementList()); // Generate constructor call that initializes closure instance this.ClosureInitializer.Statements.Add( new AssignmentStatement( this.closureLocal, new Construct(new MemberBinding(null, this.Ctor), new ExpressionList()))); }
internal static MethodContract DuplicateContractAndClosureParts( DuplicatorForContractsAndClosures dup, Method targetMethod, Method sourceMethod, ContractNodes contractNodes, bool copyValidations ) { //System.Console.WriteLine(">>>" + sourceMethod.FullName); // materialize source contract: var sourceContract = sourceMethod.Contract; ForceSideEffect(sourceContract.ContractInitializer); TypeNode targetType = targetMethod.DeclaringType; TypeNode sourceType = sourceMethod.DeclaringType; // need to null out ProvideNestedTypes so the NestedTypes property doesn't use // metadata to fill in the list of nested types. Because maybe sourceType has // had nested types added to it in memory and those nested types don't exist // in the assembly that sourceType is defined in. // The source type itself shouldn't be duplicated, because any references to its // members (e.g., method calls) in a contract should remain as references to that // member. I.e., a contract on virtual method B.M might contain a call to "this.P()". When copying // the contract from B.M to an override C.M, "this" of type B should become "this" of type C (which // is why the self parameter is mapped below), but the member B.P() should remain B.P(). // However, any nested types within the source type, such as any closure classes, *should* be // duplicated. sourceType.ProvideNestedTypes = null; targetType.ProvideNestedTypes = null; #region HACK // For some reason, it is important to materialize the name of the targetType here!!! // Otherwise the duplicator will fail. ForceSideEffect(targetType.Name.Name); #endregion Local closureLocal; FindClosureInitialization(sourceMethod, sourceContract.ContractInitializer, out closureLocal); #region Duplicate anonymous delegates that turn into static methods (and their caching fields) FindClosurePartsToDuplicate fmd = new FindClosurePartsToDuplicate(sourceType, sourceMethod); fmd.VisitMethodContract(sourceContract); // special handling of closures that are not used. if (closureLocal != null) { var closureType = Unspecialize(closureLocal.Type); if (!fmd.MembersToDuplicate.Contains(closureType)) { // contracts do not depend on closure and won't copy it, so remove the initialization, otherwise debugger gets confused DeleteClosureInitialization(sourceMethod, sourceContract, closureLocal); } } for (var memindex = fmd.MembersToDuplicate.Count - 1; memindex >= 0; memindex--) { Member mem = fmd.MembersToDuplicate[memindex]; TypeNode nestedType = mem as TypeNode; Method closureInstanceMethod = mem as Method; Method closureMethodTemplate = closureInstanceMethod; while (closureMethodTemplate != null && closureMethodTemplate.Template != null) { closureMethodTemplate = closureMethodTemplate.Template; } if (nestedType != null) { // if nested type is nested inside another type to be duplicated, skip it if (nestedType.DeclaringType != null && fmd.MembersToDuplicate.Contains(nestedType.DeclaringType)) continue; // For call-site wrappers, we end up having multiple methods from the same original contract method // thus we have to avoid duplicating the same closure type multiple times. var duplicatedNestedType = FindExistingClosureType(targetType, nestedType); if (duplicatedNestedType == null) { dup.FindTypesToBeDuplicated(new TypeNodeList(nestedType)); // if parent type is generic and different from the target type, then we may have to include all the // consolidated type parameters excluding the ones from the target type. TypeNodeList originalTemplateParameters = FindNonStandardTypeParametersToBeDuplicated(fmd, nestedType, targetType); duplicatedNestedType = dup.Visit(mem) as TypeNode; if (originalTemplateParameters != null) { int parentParameters = (targetType.ConsolidatedTemplateParameters == null) ? 0 : targetType.ConsolidatedTemplateParameters.Count; if (parentParameters > 0 && (nestedType.DeclaringType.ConsolidatedTemplateParameters == null || nestedType.DeclaringType.ConsolidatedTemplateParameters.Count == 0)) { // type is turning from non-generic to generic Debug.Assert(false); } TypeNodeList dupTPs = DuplicateTypeParameterList(originalTemplateParameters, parentParameters, duplicatedNestedType); duplicatedNestedType.TemplateParameters = dupTPs; dup.SafeAddMember(targetType, duplicatedNestedType, mem); // populate the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //var oldSelfInstanceType = nestedType.GetGenericTemplateInstance(targetModule, nestedType.ConsolidatedTemplateParameters); //var newSelfInstanceType = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = newSelfInstanceType; // specialize duplicated type var specializer = new Specializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); specializer.VisitTypeParameterList(dupTPs); // for constraints etc. specializer.VisitTypeNode(duplicatedNestedType); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); bodySpecializer.Visit(duplicatedNestedType); // after copying the closure class, clear the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = null; } else { dup.SafeAddMember(targetType, duplicatedNestedType, mem); } } else { // already copied type previously dup.DuplicateFor[nestedType.UniqueKey] = duplicatedNestedType; #if false if (nestedType.ConsolidatedTemplateArguments != null) { // populate the self specialization forwarding // NestedType<Self1,Self2> -> NewNestedType<NewSelf1,NewSelf2> var origSelfInstantiation = nestedType.DeclaringType.GetTemplateInstance(nestedType, nestedType.DeclaringType.TemplateParameters).GetNestedType(nestedType.Name); var newSelfInstantiation = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); dup.DuplicateFor[origSelfInstantiation.UniqueKey] = newSelfInstantiation; // Also forward ContractType<A,B>.NestedType instantiated at target ContractType<X,Y>.NestedType to // TargetType<X,Y,Z>.NewNestedType<X,Y>, since this reference may appear in the contract itself. var consolidatedContractTemplateArguments = sourceMethod.DeclaringType.ConsolidatedTemplateArguments; var instantiatedNestedOriginal = nestedType.DeclaringType.GetGenericTemplateInstance(targetModule, consolidatedContractTemplateArguments).GetNestedType(nestedType.Name); dup.DuplicateFor[instantiatedNestedOriginal.UniqueKey] = duplicatedNestedType.GetTemplateInstance(targetType, consolidatedContractTemplateArguments); } else { Debugger.Break(); } #endif } } else if (closureInstanceMethod != null && closureMethodTemplate != null && !fmd.MembersToDuplicate.Contains(closureMethodTemplate.DeclaringType)) { Method closureMethod = closureMethodTemplate; Debug.Assert(closureMethod.Template == null); //var m = FindExistingClosureMethod(targetType, closureMethod); Method m = null; // why did we ever try to find an existing one? This can capture a completely unrelated closure that happens to match by name. if (m == null) { Method dupMethod = dup.Visit(closureMethod) as Method; TypeNodeList actuals; TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(dupMethod, closureMethod, closureInstanceMethod, out actuals); // now setup a forwarding from the closureInstanceMethod to the new instance Method newInstance = dupMethod.GetTemplateInstance(dupMethod.DeclaringType, actuals); newInstance.Name = dupMethod.Name; dup.DuplicateFor[closureInstanceMethod.UniqueKey] = newInstance; dup.SafeAddMember(targetType, dupMethod, closureMethod); // special case when resulting method is generic and instance, then we need to make "this" a parameter // and the method static, otherwise, there's a type mismatch between the "this" and the explicitly generic parameter types used // in arguments. var originalParentTemplateParameters = closureMethod.DeclaringType.ConsolidatedTemplateParameters; if (!dupMethod.IsStatic && originalParentTemplateParameters != null && originalParentTemplateParameters.Count > 0) { var oldThis = dupMethod.ThisParameter; oldThis.Type = dup.PossiblyRemapContractClassToInterface(oldThis.Type); dupMethod.Flags |= MethodFlags.Static; dupMethod.CallingConvention &= ~CallingConventionFlags.HasThis; var oldParameters = dupMethod.Parameters; dupMethod.Parameters = new ParameterList(oldParameters.Count + 1); dupMethod.Parameters.Add(oldThis); // make explicit for (int i = 0; i < oldParameters.Count; i++) { dupMethod.Parameters.Add(oldParameters[i]); } // now need to specialize transforming original parameters into first n method template parameters var targetTypeParameters = new TypeNodeList(originalParentTemplateParameters.Count); for (int i = 0; i < originalParentTemplateParameters.Count; i++) { targetTypeParameters.Add(dupMethod.TemplateParameters[i]); } var specializer = new Specializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); specializer.VisitMethod(dupMethod); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); bodySpecializer.VisitMethod(dupMethod); } } } else if (closureInstanceMethod != null) { var m = FindExistingClosureMethod(targetType, closureInstanceMethod); if (m == null) { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } } else { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } } #endregion Duplicate anonymous delegates that turn into static methods (and their caching fields) var duplicateContract = dup.VisitMethodContract(sourceContract); if (copyValidations) { duplicateContract.Validations = dup.VisitRequiresList(sourceContract.Validations); } foreach (Member mem in sourceType.Members) { if (mem == null) continue; Member newMember = (Member)dup.DuplicateFor[mem.UniqueKey]; if (newMember != null && mem != (Member)targetType && newMember.DeclaringType == targetType && !targetType.Members.Contains(newMember)) { TypeNode nestedType = mem as TypeNode; if (nestedType != null && nestedType.Template != null) { // don't add instantiations continue; } Method nestedMethod = mem as Method; if (nestedMethod != null && nestedMethod.Template != null) { // don't add instantiations continue; } // second conjunct is to make sure we don't recursively add a nested type to itself // e.g., ArrayList+IListWrapper extends ArrayList and so inherits contracts from it // so this method could be called with sourceMethod "ArrayList.M" and targetMethod "ArrayList+IListWrapper.M" // But need to make sure that there isn't already a type with the same name!!! TypeNode possibleClash = targetType.GetNestedType(newMember.Name); if (possibleClash != null) { newMember.Name = Identifier.For(newMember.Name.Name + "_1"); } // System.Console.WriteLine("found nested member that wasn't there before closure and contract duplication: {0}", newMember.FullName); dup.SafeAddMember(targetType, newMember, mem); //targetType.Members.Add(newMember); } } return duplicateContract; }