static Type TypeParam_EffectiveBaseType (GenericConstraints gc) { ArrayList list = new ArrayList (); list.Add (gc.EffectiveBaseClass); foreach (Type t in gc.InterfaceConstraints) { if (!TypeManager.IsGenericParameter (t)) continue; GenericConstraints new_gc = TypeManager.GetTypeParameterConstraints (t); if (new_gc != null) list.Add (TypeParam_EffectiveBaseType (new_gc)); } return FindMostEncompassedType (list); }
public InflatedConstraints (GenericConstraints gc, Type[] dargs) { this.gc = gc; this.dargs = dargs; ArrayList list = new ArrayList (); if (gc.HasClassConstraint) list.Add (inflate (gc.ClassConstraint)); foreach (Type iface in gc.InterfaceConstraints) list.Add (inflate (iface)); bool has_class_constr = false; if (list.Count > 0) { Type first = (Type) list [0]; has_class_constr = !first.IsGenericParameter && !first.IsInterface; } if ((list.Count > 0) && has_class_constr) { class_constraint = (Type) list [0]; iface_constraints = new Type [list.Count - 1]; list.CopyTo (1, iface_constraints, 0, list.Count - 1); } else { iface_constraints = new Type [list.Count]; list.CopyTo (iface_constraints, 0); } if (HasValueTypeConstraint) base_type = TypeManager.value_type; else if (class_constraint != null) base_type = class_constraint; else base_type = TypeManager.object_type; }
public InflatedConstraints (GenericConstraints gc, Type declaring) : this (gc, TypeManager.GetTypeArguments (declaring)) { }
public void InflateConstraints (Type declaring) { if (constraints != null) gc = new InflatedConstraints (constraints, declaring); }
/// <summary> /// This is the fith and last method which is called during the resolving /// process. We're called after everything is fully resolved and actually /// register the constraints with SRE and the TypeManager. /// /// The `builder', `implementing' and `is_override' arguments are only /// applicable to method type parameters. /// </summary> public bool DefineType (IResolveContext ec, MethodBuilder builder, MethodInfo implementing, bool is_override) { if (!ResolveType (ec)) return false; if (implementing != null) { if (is_override && (constraints != null)) { Report.Error (460, Location, "`{0}': Cannot specify constraints for overrides or explicit interface implementation methods", TypeManager.CSharpSignature (builder)); return false; } MethodBase mb = TypeManager.DropGenericMethodArguments (implementing); int pos = type.GenericParameterPosition; Type mparam = mb.GetGenericArguments () [pos]; GenericConstraints temp_gc = ReflectionConstraints.GetConstraints (mparam); if (temp_gc != null) gc = new InflatedConstraints (temp_gc, implementing.DeclaringType); else if (constraints != null) gc = new InflatedConstraints (constraints, implementing.DeclaringType); bool ok = true; if (constraints != null) { if (temp_gc == null) ok = false; else if (!constraints.AreEqual (gc)) ok = false; } else { if (!is_override && (temp_gc != null)) ok = false; } if (!ok) { Report.SymbolRelatedToPreviousError (implementing); Report.Error ( 425, Location, "The constraints for type " + "parameter `{0}' of method `{1}' must match " + "the constraints for type parameter `{2}' " + "of interface method `{3}'. Consider using " + "an explicit interface implementation instead", Name, TypeManager.CSharpSignature (builder), TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb)); return false; } } else if (DeclSpace is CompilerGeneratedClass) { TypeParameter[] tparams = DeclSpace.TypeParameters; Type[] types = new Type [tparams.Length]; for (int i = 0; i < tparams.Length; i++) types [i] = tparams [i].Type; if (constraints != null) gc = new InflatedConstraints (constraints, types); } else { gc = (GenericConstraints) constraints; } if (gc == null) return true; if (gc.HasClassConstraint || gc.HasValueTypeConstraint) type.SetBaseTypeConstraint (gc.EffectiveBaseClass); type.SetInterfaceConstraints (gc.InterfaceConstraints); type.SetGenericParameterAttributes (gc.Attributes); TypeManager.RegisterBuilder (type, gc.InterfaceConstraints); return true; }
/// <summary> /// This is used when we're implementing a generic interface method. /// Each method type parameter in implementing method must have the same /// constraints than the corresponding type parameter in the interface /// method. To do that, we're called on each of the implementing method's /// type parameters. /// </summary> public bool AreEqual (GenericConstraints gc) { if (gc.Attributes != attrs) return false; if (HasClassConstraint != gc.HasClassConstraint) return false; if (HasClassConstraint && !TypeManager.IsEqual (gc.ClassConstraint, ClassConstraint)) return false; int gc_icount = gc.InterfaceConstraints != null ? gc.InterfaceConstraints.Length : 0; int icount = InterfaceConstraints != null ? InterfaceConstraints.Length : 0; if (gc_icount != icount) return false; for (int i = 0; i < gc.InterfaceConstraints.Length; ++i) { Type iface = gc.InterfaceConstraints [i]; if (iface.IsGenericType) iface = iface.GetGenericTypeDefinition (); bool ok = false; for (int ii = 0; i < InterfaceConstraints.Length; ++ii) { Type check = InterfaceConstraints [ii]; if (check.IsGenericType) check = check.GetGenericTypeDefinition (); if (TypeManager.IsEqual (iface, check)) { ok = true; break; } } if (!ok) return false; } return true; }