Esempio n. 1
0
        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;
        }
Esempio n. 2
0
        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));
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 5
0
    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;
    }
Esempio n. 6
0
    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;
    }
Esempio n. 7
0
        /// <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())));
        }
Esempio n. 8
0
    /// <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&lt;T&gt;() 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);
    }
Esempio n. 9
0
        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;
            }
        }
Esempio n. 10
0
        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;
            }
        }
Esempio n. 11
0
        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())));
        }
Esempio n. 12
0
    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;
    }