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