public virtual void CheckForCircularLayout(Struct s1, Struct s2, Field offendingField) { if (s1 == null || s2 == null) return; MemberList members = this.GetTypeView(s1).Members; // need to check all members, right? for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++) { Field f = members[i] as Field; if (f == null) continue; if (f.Type == s1 && s1.Template == s2 && s1.IsNotFullySpecialized) { for (int j = 0, m = s1.TemplateArguments == null ? 0 : s1.TemplateArguments.Count; j < m; j++) { TypeNode s1arg = s1.TemplateArguments[j]; if (s1arg != null && s1arg.Template == s2) { //Recursive generic struct this.HandleError(offendingField.Name, Error.ValueTypeLayoutCycle, this.GetMemberSignature(offendingField), this.GetTypeName(s1)); break; } } } if (f.IsStatic || f.IsLiteral) continue; if (s2.IsStructurallyEquivalentTo(f.Type)) { // Our primitives tend to hold their state in a field of their own type. For instance // the Boolean struct has a field 'bool m_value' which of course is a Boolean struct if (s2.IsPrimitiveNumeric || s2 == SystemTypes.Boolean || s2 == SystemTypes.Char) continue; this.HandleError(offendingField.Name, Error.ValueTypeLayoutCycle, this.GetMemberSignature(offendingField), this.GetTypeName(s1)); } } }