// // generic.cs: Support classes for generics // // Author: // Miguel de Icaza (miguel@ximian.com) // // (C) 2003 Ximian, Inc. // using System; using System.Reflection; using System.Reflection.Emit; using System.Globalization; using System.Collections; using System.Text; namespace Mono.CSharp { public abstract class GenericConstraints { public abstract GenericParameterAttributes Attributes { get; } public bool HasConstructorConstraint { get { return (Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0; } } public bool HasReferenceTypeConstraint { get { return (Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0; } } public bool HasValueTypeConstraint { get { return (Attributes & GenericParameterAttributes.ValueTypeConstraint) != 0; } } public virtual bool HasClassConstraint { get { return ClassConstraint != null; } } public abstract Type ClassConstraint { get; } public abstract Type[] InterfaceConstraints { get; } public abstract Type EffectiveBaseClass { get; } // // Returns whether the type parameter is "known to be a reference type". // public virtual bool IsReferenceType { get { if (HasReferenceTypeConstraint) return true; if (HasValueTypeConstraint) return false; if (ClassConstraint != null) { if (ClassConstraint.IsValueType) return false; if (ClassConstraint != TypeManager.object_type) return true; } foreach (Type t in InterfaceConstraints) { if (!t.IsGenericParameter) continue; GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t); if ((gc != null) && gc.IsReferenceType) return true; } return false; } } // // Returns whether the type parameter is "known to be a value type". // public virtual bool IsValueType { get { if (HasValueTypeConstraint) return true; if (HasReferenceTypeConstraint) return false; if (ClassConstraint != null) { if (!ClassConstraint.IsValueType) return false; if (ClassConstraint != TypeManager.value_type) return true; } foreach (Type t in InterfaceConstraints) { if (!t.IsGenericParameter) continue; GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t); if ((gc != null) && gc.IsValueType) return true; } return false; } } } public enum SpecialConstraint { Constructor, ReferenceType, ValueType } // // Tracks the constraints for a type parameter // public class Constraints : GenericConstraints { string name; ArrayList constraints; Location loc; // // name is the identifier, constraints is an arraylist of // Expressions (with types) or `true' for the constructor constraint. // public Constraints (string name, ArrayList constraints, Location loc) { this.name = name; this.constraints = constraints; this.loc = loc; } public string TypeParameter { get { return name; } } GenericParameterAttributes attrs; TypeExpr class_constraint; ArrayList iface_constraints; ArrayList type_param_constraints; int num_constraints, first_constraint; Type class_constraint_type; Type[] iface_constraint_types; Type effective_base_type; public bool Resolve (DeclSpace ds) { iface_constraints = new ArrayList (); type_param_constraints = new ArrayList (); foreach (object obj in constraints) { if (HasConstructorConstraint) { Report.Error (401, loc, "The new() constraint must be last."); return false; } if (obj is SpecialConstraint) { SpecialConstraint sc = (SpecialConstraint) obj; if (sc == SpecialConstraint.Constructor) { if (!HasValueTypeConstraint) { attrs |= GenericParameterAttributes.DefaultConstructorConstraint; continue; } Report.Error ( 451, loc, "The new () constraint " + "cannot be used with the `struct' " + "constraint."); return false; } if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) { Report.Error (449, loc, "The `class' or `struct' " + "constraint must be first"); return false; } if (sc == SpecialConstraint.ReferenceType) attrs |= GenericParameterAttributes.ReferenceTypeConstraint; else attrs |= GenericParameterAttributes.ValueTypeConstraint; continue; } TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, false, loc); if (expr == null) return false; TypeParameterExpr texpr = expr as TypeParameterExpr; if (texpr != null) type_param_constraints.Add (expr); else if (expr.IsInterface) iface_constraints.Add (expr); else if (class_constraint != null) { Report.Error (406, loc, "`{0}': the class constraint for `{1}' " + "must come before any other constraints.", expr.Name, name); return false; } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) { Report.Error (450, loc, "`{0}': cannot specify both " + "a constraint class and the `class' " + "or `struct' constraint.", expr.Name); return false; } else class_constraint = expr; num_constraints++; } return true; } bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen) { seen.Add (tparam, true); Constraints constraints = tparam.Constraints; if (constraints == null) return true; if (constraints.HasValueTypeConstraint) { Report.Error (456, loc, "Type parameter `{0}' has " + "the `struct' constraint, so it cannot " + "be used as a constraint for `{1}'", tparam.Name, name); return false; } if (constraints.type_param_constraints == null) return true; foreach (TypeParameterExpr expr in constraints.type_param_constraints) { if (seen.Contains (expr.TypeParameter)) { Report.Error (454, loc, "Circular constraint " + "dependency involving `{0}' and `{1}'", tparam.Name, expr.Name); return false; } if (!CheckTypeParameterConstraints (expr.TypeParameter, seen)) return false; } return true; } public bool ResolveTypes (EmitContext ec) { foreach (TypeParameterExpr expr in type_param_constraints) { Hashtable seen = new Hashtable (); if (!CheckTypeParameterConstraints (expr.TypeParameter, seen)) return false; } ArrayList list = new ArrayList (); foreach (TypeExpr iface_constraint in iface_constraints) { Type resolved = iface_constraint.ResolveType (ec); if (resolved == null) return false; foreach (Type type in list) { if (!type.Equals (resolved)) continue; Report.Error (405, loc, "Duplicate constraint `{0}' for type " + "parameter `{1}'.", resolved, name); return false; } list.Add (resolved); } foreach (TypeParameterExpr expr in type_param_constraints) { Type resolved = expr.ResolveType (ec); if (resolved == null) return false; foreach (Type type in list) { if (!type.Equals (resolved)) continue; Report.Error (405, loc, "Duplicate constraint `{0}' for type " + "parameter `{1}'.", resolved, name); return false; } list.Add (resolved); } iface_constraint_types = new Type [list.Count]; list.CopyTo (iface_constraint_types, 0); if (class_constraint != null) { class_constraint_type = class_constraint.ResolveType (ec); if (class_constraint_type == null) return false; if (class_constraint_type.IsSealed) { Report.Error (701, loc, "`{0}' is not a valid bound. Bounds " + "must be interfaces or non sealed " + "classes", class_constraint_type); return false; } if ((class_constraint_type == TypeManager.array_type) || (class_constraint_type == TypeManager.delegate_type) || (class_constraint_type == TypeManager.enum_type) || (class_constraint_type == TypeManager.value_type) || (class_constraint_type == TypeManager.object_type)) { Report.Error (702, loc, "Bound cannot be special class `{0}'", class_constraint_type); return false; } } if (class_constraint_type != null) effective_base_type = class_constraint_type; else if (HasValueTypeConstraint) effective_base_type = TypeManager.value_type; else effective_base_type = TypeManager.object_type; return true; } public bool CheckDependencies (EmitContext ec) { foreach (TypeParameterExpr expr in type_param_constraints) { if (!CheckDependencies (expr.TypeParameter, ec)) return false; } return true; } bool CheckDependencies (TypeParameter tparam, EmitContext ec) { Constraints constraints = tparam.Constraints; if (constraints == null) return true; if (HasValueTypeConstraint && constraints.HasClassConstraint) { Report.Error (455, loc, "Type parameter `{0}' inherits " + "conflicting constraints `{1}' and `{2}'", name, constraints.ClassConstraint, "System.ValueType"); return false; } if (HasClassConstraint && constraints.HasClassConstraint) { Type t1 = ClassConstraint; TypeExpr e1 = class_constraint; Type t2 = constraints.ClassConstraint; TypeExpr e2 = constraints.class_constraint; if (!Convert.ImplicitReferenceConversionExists (e1, t2) && !Convert.ImplicitReferenceConversionExists (e2, t1)) { Report.Error (455, loc, "Type parameter `{0}' inherits " + "conflicting constraints `{1}' and `{2}'", name, t1, t2); return false; } } if (constraints.type_param_constraints == null) return true; foreach (TypeParameterExpr expr in constraints.type_param_constraints) { if (!CheckDependencies (expr.TypeParameter, ec)) return false; } return true; } public void Define (GenericTypeParameterBuilder type) { type.SetGenericParameterAttributes (attrs); } public override GenericParameterAttributes Attributes { get { return attrs; } } public override bool HasClassConstraint { get { return class_constraint != null; } } public override Type ClassConstraint { get { return class_constraint_type; } } public override Type[] InterfaceConstraints { get { return iface_constraint_types; } } public override Type EffectiveBaseClass { get { return effective_base_type; } } internal bool IsSubclassOf (Type t) { if ((class_constraint_type != null) && class_constraint_type.IsSubclassOf (t)) return true; if (iface_constraint_types == null) return false; foreach (Type iface in iface_constraint_types) { if (TypeManager.IsSubclassOf (iface, t)) return true; } return false; } public bool CheckInterfaceMethod (EmitContext ec, GenericConstraints gc) { if (!ResolveTypes (ec)) return false; if (gc.Attributes != attrs) return false; if (HasClassConstraint != gc.HasClassConstraint) return false; if (HasClassConstraint && !gc.ClassConstraint.Equals (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; foreach (Type iface in gc.InterfaceConstraints) { bool ok = false; foreach (Type check in InterfaceConstraints) { if (iface.IsGenericParameter && check.IsGenericParameter) { ok = true; break; } else if (iface.Equals (check)) { ok = true; break; } } if (!ok) return false; } return true; } } // // This type represents a generic type parameter // public class TypeParameter : MemberCore, IMemberContainer { string name; GenericConstraints gc; Constraints constraints; Location loc; GenericTypeParameterBuilder type; public TypeParameter (TypeContainer parent, string name, Constraints constraints, Location loc) : base (parent, new MemberName (name), null, loc) { this.name = name; this.constraints = constraints; this.loc = loc; } public GenericConstraints GenericConstraints { get { return gc != null ? gc : constraints; } } public Constraints Constraints { get { return constraints; } } public bool HasConstructorConstraint { get { if (constraints != null) return constraints.HasConstructorConstraint; return false; } } public Type Type { get { return type; } } public bool Resolve (DeclSpace ds) { if (constraints != null) return constraints.Resolve (ds); return true; } public void Define (GenericTypeParameterBuilder type) { if (this.type != null) throw new InvalidOperationException (); this.type = type; Type[] ifaces = null; if (constraints != null) constraints.Define (type); TypeManager.AddTypeParameter (type, this); } public bool DefineType (EmitContext ec) { return DefineType (ec, null, null, false); } public bool DefineType (EmitContext ec, MethodBuilder builder, MethodInfo implementing, bool is_override) { if (implementing != null) { if (is_override && (constraints != null)) { Report.Error ( 460, loc, "Constraints for override and " + "explicit interface implementation methods " + "are inherited from the base method so they " + "cannot be specified directly"); return false; } MethodBase mb = implementing; if (mb.Mono_IsInflatedMethod) mb = mb.GetGenericMethodDefinition (); int pos = type.GenericParameterPosition; ParameterData pd = Invocation.GetParameterData (mb); gc = pd.GenericConstraints (pos); Type mparam = mb.GetGenericArguments () [pos]; bool ok = true; if (constraints != null) { if (gc == null) ok = false; else if (!constraints.CheckInterfaceMethod (ec, gc)) ok = false; } else { if (!is_override && (gc != null)) ok = false; } if (!ok) { Report.SymbolRelatedToPreviousError (implementing); Report.Error ( 425, loc, "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), mparam, TypeManager.CSharpSignature (mb)); return false; } } else { if (constraints != null) { if (!constraints.ResolveTypes (ec)) return false; } gc = (GenericConstraints) constraints; } if (gc == null) return true; if (gc.HasClassConstraint) type.SetBaseTypeConstraint (gc.ClassConstraint); type.SetInterfaceConstraints (gc.InterfaceConstraints); TypeManager.RegisterBuilder (type, gc.InterfaceConstraints); return true; } public bool CheckDependencies (EmitContext ec) { if (constraints != null) return constraints.CheckDependencies (ec); return true; } // // MemberContainer // public override bool Define () { return true; } protected override void VerifyObsoleteAttribute () { } public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) { } public override AttributeTargets AttributeTargets { get { return (AttributeTargets) 0; } } public override string[] ValidAttributeTargets { get { return new string [0]; } } // // IMemberContainer // string IMemberContainer.Name { get { return Name; } } IMemberContainer IMemberContainer.ParentContainer { get { return null; } } bool IMemberContainer.IsInterface { get { return true; } } MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf) { return FindMembers (mt, bf, null, null); } MemberCache IMemberContainer.MemberCache { get { return null; } } public MemberList FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria) { if (constraints == null) return MemberList.Empty; ArrayList members = new ArrayList (); GenericConstraints gc = (GenericConstraints) constraints; if (gc.HasClassConstraint) { MemberList list = TypeManager.FindMembers ( gc.ClassConstraint, mt, bf, filter, criteria); members.AddRange (list); } foreach (Type t in gc.InterfaceConstraints) { MemberList list = TypeManager.FindMembers ( t, mt, bf, filter, criteria); members.AddRange (list); } return new MemberList (members); } public bool IsSubclassOf (Type t) { if (type.Equals (t)) return true; if (constraints != null) return constraints.IsSubclassOf (t); return false; } public override string ToString () { return "TypeParameter[" + name + "]"; } } // // This type represents a generic type parameter reference. // // These expressions are born in a fully resolved state. // public class TypeParameterExpr : TypeExpr { TypeParameter type_parameter; public override string Name { get { return type_parameter.Name; } } public TypeParameter TypeParameter { get { return type_parameter; } } public TypeParameterExpr (TypeParameter type_parameter, Location loc) { this.type_parameter = type_parameter; this.loc = loc; } public override TypeExpr DoResolveAsTypeStep (EmitContext ec) { type = type_parameter.Type; return this; } public override bool IsInterface { get { return false; } } public void Error_CannotUseAsUnmanagedType (Location loc) { Report.Error (-203, loc, "Can not use type parameter as unamanged type"); } } public class TypeArguments { public readonly Location Location; ArrayList args; Type[] atypes; int dimension; bool has_type_args; bool created; public TypeArguments (Location loc) { args = new ArrayList (); this.Location = loc; } public TypeArguments (int dimension, Location loc) { this.dimension = dimension; this.Location = loc; } public void Add (Expression type) { if (created) throw new InvalidOperationException (); args.Add (type); } public void Add (TypeArguments new_args) { if (created) throw new InvalidOperationException (); args.AddRange (new_args.args); } public string[] GetDeclarations () { string[] ret = new string [args.Count]; for (int i = 0; i < args.Count; i++) { SimpleName sn = args [i] as SimpleName; if (sn != null) { ret [i] = sn.Name; continue; } Report.Error (81, Location, "Type parameter declaration " + "must be an identifier not a type"); return null; } return ret; } public Type[] Arguments { get { return atypes; } } public bool HasTypeArguments { get { return has_type_args; } } public int Count { get { if (dimension > 0) return dimension; else return args.Count; } } public bool IsUnbound { get { return dimension > 0; } } public override string ToString () { StringBuilder s = new StringBuilder (); int count = Count; for (int i = 0; i < count; i++){ // // FIXME: Use TypeManager.CSharpname once we have the type // if (args != null) s.Append (args [i].ToString ()); if (i+1 < count) s.Append (","); } return s.ToString (); } public bool Resolve (EmitContext ec) { DeclSpace ds = ec.DeclSpace; int count = args.Count; bool ok = true; atypes = new Type [count]; for (int i = 0; i < count; i++){ TypeExpr te = ds.ResolveTypeExpr ( (Expression) args [i], false, Location); if (te == null) { ok = false; continue; } if (te is TypeParameterExpr) has_type_args = true; atypes [i] = te.ResolveType (ec); if (atypes [i] == null) { Report.Error (246, Location, "Cannot find type `{0}'", te.Name); ok = false; } } return ok; } } public class ConstructedType : TypeExpr { string name, full_name; TypeArguments args; Type[] gen_params, atypes; Type gt; public ConstructedType (string name, TypeArguments args, Location l) { loc = l; this.name = MemberName.MakeName (name, args.Count); this.args = args; eclass = ExprClass.Type; full_name = name + "<" + args.ToString () + ">"; } public ConstructedType (string name, TypeParameter[] type_params, Location l) : this (type_params, l) { loc = l; this.name = name; full_name = name + "<" + args.ToString () + ">"; } protected ConstructedType (TypeArguments args, Location l) { loc = l; this.args = args; eclass = ExprClass.Type; } protected ConstructedType (TypeParameter[] type_params, Location l) { loc = l; args = new TypeArguments (l); foreach (TypeParameter type_param in type_params) args.Add (new TypeParameterExpr (type_param, l)); eclass = ExprClass.Type; } public ConstructedType (Type t, TypeParameter[] type_params, Location l) : this (type_params, l) { gt = t.GetGenericTypeDefinition (); this.name = gt.FullName; full_name = gt.FullName + "<" + args.ToString () + ">"; } public ConstructedType (Type t, TypeArguments args, Location l) : this (args, l) { gt = t.GetGenericTypeDefinition (); this.name = gt.FullName; full_name = gt.FullName + "<" + args.ToString () + ">"; } public TypeArguments TypeArguments { get { return args; } } protected string DeclarationName { get { StringBuilder sb = new StringBuilder (); sb.Append (gt.FullName); sb.Append ("<"); for (int i = 0; i < gen_params.Length; i++) { if (i > 0) sb.Append (","); sb.Append (gen_params [i]); } sb.Append (">"); return sb.ToString (); } } protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr, Type ctype) { if (TypeManager.HasGenericArguments (ctype)) { Type[] types = TypeManager.GetTypeArguments (ctype); TypeArguments new_args = new TypeArguments (loc); for (int i = 0; i < types.Length; i++) { Type t = types [i]; if (t.IsGenericParameter) { int pos = t.GenericParameterPosition; t = args.Arguments [pos]; } new_args.Add (new TypeExpression (t, loc)); } ctype = new ConstructedType (ctype, new_args, loc).ResolveType (ec); if (ctype == null) return false; } return Convert.ImplicitStandardConversionExists (expr, ctype); } protected bool CheckConstraints (EmitContext ec, int index) { Type atype = atypes [index]; Type ptype = gen_params [index]; if (atype == ptype) return true; Expression aexpr = new EmptyExpression (atype); GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype); if (gc == null) return true; // // First, check the `class' and `struct' constraints. // if (gc.HasReferenceTypeConstraint && !atype.IsClass) { Report.Error (452, loc, "The type `{0}' must be " + "a reference type in order to use it " + "as type parameter `{1}' in the " + "generic type or method `{2}'.", atype, ptype, DeclarationName); return false; } else if (gc.HasValueTypeConstraint && !atype.IsValueType) { Report.Error (453, loc, "The type `{0}' must be " + "a value type in order to use it " + "as type parameter `{1}' in the " + "generic type or method `{2}'.", atype, ptype, DeclarationName); return false; } // // The class constraint comes next. // if (gc.HasClassConstraint) { if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) { Report.Error (309, loc, "The type `{0}' must be " + "convertible to `{1}' in order to " + "use it as parameter `{2}' in the " + "generic type or method `{3}'", atype, gc.ClassConstraint, ptype, DeclarationName); return false; } } // // Now, check the interface constraints. // foreach (Type it in gc.InterfaceConstraints) { Type itype; if (it.IsGenericParameter) itype = atypes [it.GenericParameterPosition]; else itype = it; if (!CheckConstraint (ec, ptype, aexpr, itype)) { Report.Error (309, loc, "The type `{0}' must be " + "convertible to `{1}' in order to " + "use it as parameter `{2}' in the " + "generic type or method `{3}'", atype, itype, ptype, DeclarationName); return false; } } // // Finally, check the constructor constraint. // if (!gc.HasConstructorConstraint) return true; if (TypeManager.IsBuiltinType (atype)) return true; MethodGroupExpr mg = Expression.MemberLookup ( ec, atype, ".ctor", MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, loc) as MethodGroupExpr; if (atype.IsAbstract || (mg == null) || !mg.IsInstance) { Report.Error (310, loc, "The type `{0}' must have a public " + "parameterless constructor in order to use it " + "as parameter `{1}' in the generic type or " + "method `{2}'", atype, ptype, DeclarationName); return false; } return true; } public override TypeExpr DoResolveAsTypeStep (EmitContext ec) { if (gt != null) return this; // // First, resolve the generic type. // DeclSpace ds; Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds); if (nested != null) { gt = nested.GetGenericTypeDefinition (); TypeArguments new_args = new TypeArguments (loc); if (ds.IsGeneric) { foreach (TypeParameter param in ds.TypeParameters) new_args.Add (new TypeParameterExpr (param, loc)); } new_args.Add (args); args = new_args; return this; } Type t; int num_args; SimpleName sn = new SimpleName (name, loc); TypeExpr resolved = sn.ResolveAsTypeTerminal (ec); if ((resolved == null) || (resolved.Type == null)) { Report.Error (246, loc, "The type or namespace name `{0}<...>' "+ "could not be found", Basename); return null; } t = resolved.Type; if (t == null) { Report.Error (246, loc, "Cannot find type `{0}'<...>", Basename); return null; } num_args = TypeManager.GetNumberOfTypeArguments (t); if (num_args == 0) { Report.Error (308, loc, "The non-generic type `{0}' cannot " + "be used with type arguments.", TypeManager.CSharpName (t)); return null; } gt = t.GetGenericTypeDefinition (); return this; } public override Type ResolveType (EmitContext ec) { if (type != null) return type; if (DoResolveAsTypeStep (ec) == null) return null; // // Resolve the arguments. // if (args.Resolve (ec) == false) return null; gen_params = gt.GetGenericArguments (); atypes = args.Arguments; if (atypes.Length != gen_params.Length) { Report.Error (305, loc, "Using the generic type `{0}' " + "requires {1} type arguments", TypeManager.GetFullName (gt), gen_params.Length); return null; } for (int i = 0; i < gen_params.Length; i++) { if (!CheckConstraints (ec, i)) return null; } // // Now bind the parameters. // type = gt.BindGenericParameters (atypes); return type; } public Expression GetSimpleName (EmitContext ec) { return new SimpleName (Basename, args, loc); } public override bool CheckAccessLevel (DeclSpace ds) { return ds.CheckAccessLevel (gt); } public override bool AsAccessible (DeclSpace ds, int flags) { return ds.AsAccessible (gt, flags); } public override bool IsClass { get { return gt.IsClass; } } public override bool IsValueType { get { return gt.IsValueType; } } public override bool IsInterface { get { return gt.IsInterface; } } public override bool IsSealed { get { return gt.IsSealed; } } public override bool IsAttribute { get { return false; } } public override bool Equals (object obj) { ConstructedType cobj = obj as ConstructedType; if (cobj == null) return false; if ((type == null) || (cobj.type == null)) return false; return type == cobj.type; } public string Basename { get { int pos = name.LastIndexOf ('`'); if (pos >= 0) return name.Substring (0, pos); else return name; } } public override string Name { get { return full_name; } } } public class GenericMethod : DeclSpace { public GenericMethod (NamespaceEntry ns, TypeContainer parent, MemberName name, Location l) : base (ns, parent, name, null, l) { } public override TypeBuilder DefineType () { throw new Exception (); } public override bool Define () { for (int i = 0; i < TypeParameters.Length; i++) if (!TypeParameters [i].Resolve (Parent)) return false; return true; } public bool Define (MethodBuilder mb) { if (!Define ()) return false; GenericTypeParameterBuilder[] gen_params; string[] names = MemberName.TypeArguments.GetDeclarations (); gen_params = mb.DefineGenericParameters (names); for (int i = 0; i < TypeParameters.Length; i++) TypeParameters [i].Define (gen_params [i]); return true; } public bool DefineType (EmitContext ec, MethodBuilder mb, MethodInfo implementing, bool is_override) { for (int i = 0; i < TypeParameters.Length; i++) if (!TypeParameters [i].DefineType ( ec, mb, implementing, is_override)) return false; return true; } public override bool DefineMembers (TypeContainer parent) { return true; } public override MemberList FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria) { throw new Exception (); } public override MemberCache MemberCache { get { throw new Exception (); } } public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) { // FIXME } protected override void VerifyObsoleteAttribute() { // FIXME } public override AttributeTargets AttributeTargets { get { return AttributeTargets.Method | AttributeTargets.ReturnValue; } } } public class DefaultValueExpression : Expression { Expression expr; LocalTemporary temp_storage; public DefaultValueExpression (Expression expr, Location loc) { this.expr = expr; this.loc = loc; } public override Expression DoResolve (EmitContext ec) { type = ec.DeclSpace.ResolveType (expr, false, loc); if (type == null) return null; if (type.IsGenericParameter || TypeManager.IsValueType (type)) temp_storage = new LocalTemporary (ec, type); eclass = ExprClass.Variable; return this; } public override void Emit (EmitContext ec) { if (temp_storage != null) { temp_storage.AddressOf (ec, AddressOp.LoadStore); ec.ig.Emit (OpCodes.Initobj, type); temp_storage.Emit (ec); } else ec.ig.Emit (OpCodes.Ldnull); } } }