2 // generic.cs: Support classes for generics
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2003 Ximian, Inc.
10 using System.Reflection;
11 using System.Reflection.Emit;
12 using System.Globalization;
13 using System.Collections;
16 namespace Mono.CSharp {
18 public abstract class GenericConstraints {
19 public abstract GenericParameterAttributes Attributes {
23 public bool HasConstructorConstraint {
24 get { return (Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0; }
27 public bool HasReferenceTypeConstraint {
28 get { return (Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0; }
31 public bool HasValueTypeConstraint {
32 get { return (Attributes & GenericParameterAttributes.ValueTypeConstraint) != 0; }
35 public virtual bool HasClassConstraint {
36 get { return ClassConstraint != null; }
39 public abstract Type ClassConstraint {
43 public abstract Type[] InterfaceConstraints {
47 public abstract Type EffectiveBaseClass {
52 // Returns whether the type parameter is "known to be a reference type".
54 public virtual bool IsReferenceType {
56 if (HasReferenceTypeConstraint)
58 if (HasValueTypeConstraint)
61 if (ClassConstraint != null) {
62 if (ClassConstraint.IsValueType)
65 if (ClassConstraint != TypeManager.object_type)
69 foreach (Type t in InterfaceConstraints) {
70 if (!t.IsGenericParameter)
73 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
74 if ((gc != null) && gc.IsReferenceType)
83 // Returns whether the type parameter is "known to be a value type".
85 public virtual bool IsValueType {
87 if (HasValueTypeConstraint)
89 if (HasReferenceTypeConstraint)
92 if (ClassConstraint != null) {
93 if (!ClassConstraint.IsValueType)
96 if (ClassConstraint != TypeManager.value_type)
100 foreach (Type t in InterfaceConstraints) {
101 if (!t.IsGenericParameter)
104 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
105 if ((gc != null) && gc.IsValueType)
114 public enum SpecialConstraint
122 // Tracks the constraints for a type parameter
124 public class Constraints : GenericConstraints {
126 ArrayList constraints;
130 // name is the identifier, constraints is an arraylist of
131 // Expressions (with types) or `true' for the constructor constraint.
133 public Constraints (string name, ArrayList constraints,
137 this.constraints = constraints;
141 public string TypeParameter {
147 GenericParameterAttributes attrs;
148 TypeExpr class_constraint;
149 ArrayList iface_constraints;
150 ArrayList type_param_constraints;
151 int num_constraints, first_constraint;
152 Type class_constraint_type;
153 Type[] iface_constraint_types;
154 Type effective_base_type;
156 public bool Resolve (EmitContext ec)
158 DeclSpace ds = ec.DeclSpace;
160 iface_constraints = new ArrayList ();
161 type_param_constraints = new ArrayList ();
163 foreach (object obj in constraints) {
164 if (HasConstructorConstraint) {
165 Report.Error (401, loc,
166 "The new() constraint must be last.");
170 if (obj is SpecialConstraint) {
171 SpecialConstraint sc = (SpecialConstraint) obj;
173 if (sc == SpecialConstraint.Constructor) {
174 if (!HasValueTypeConstraint) {
175 attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
180 451, loc, "The new () constraint " +
181 "cannot be used with the `struct' " +
186 if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) {
187 Report.Error (449, loc,
188 "The `class' or `struct' " +
189 "constraint must be first");
193 if (sc == SpecialConstraint.ReferenceType)
194 attrs |= GenericParameterAttributes.ReferenceTypeConstraint;
196 attrs |= GenericParameterAttributes.ValueTypeConstraint;
201 if (obj is ConstructedType) {
202 ConstructedType cexpr = (ConstructedType) obj;
203 if (!cexpr.ResolveConstructedType (ec))
207 expr = ((Expression) obj).ResolveAsTypeTerminal (ec);
212 TypeParameterExpr texpr = expr as TypeParameterExpr;
214 type_param_constraints.Add (expr);
215 else if (expr.IsInterface)
216 iface_constraints.Add (expr);
217 else if (class_constraint != null) {
218 Report.Error (406, loc,
219 "`{0}': the class constraint for `{1}' " +
220 "must come before any other constraints.",
223 } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
224 Report.Error (450, loc, "`{0}': cannot specify both " +
225 "a constraint class and the `class' " +
226 "or `struct' constraint.", expr.Name);
229 class_constraint = expr;
237 bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
239 seen.Add (tparam, true);
241 Constraints constraints = tparam.Constraints;
242 if (constraints == null)
245 if (constraints.HasValueTypeConstraint) {
246 Report.Error (456, loc, "Type parameter `{0}' has " +
247 "the `struct' constraint, so it cannot " +
248 "be used as a constraint for `{1}'",
253 if (constraints.type_param_constraints == null)
256 foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
257 if (seen.Contains (expr.TypeParameter)) {
258 Report.Error (454, loc, "Circular constraint " +
259 "dependency involving `{0}' and `{1}'",
260 tparam.Name, expr.Name);
264 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
271 public bool ResolveTypes (EmitContext ec)
273 foreach (object obj in constraints) {
274 ConstructedType cexpr = obj as ConstructedType;
278 if (!cexpr.CheckConstraints (ec))
282 foreach (TypeParameterExpr expr in type_param_constraints) {
283 Hashtable seen = new Hashtable ();
284 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
288 ArrayList list = new ArrayList ();
290 foreach (TypeExpr iface_constraint in iface_constraints) {
291 foreach (Type type in list) {
292 if (!type.Equals (iface_constraint.Type))
295 Report.Error (405, loc,
296 "Duplicate constraint `{0}' for type " +
297 "parameter `{1}'.", iface_constraint.Type,
302 list.Add (iface_constraint.Type);
305 foreach (TypeParameterExpr expr in type_param_constraints) {
306 foreach (Type type in list) {
307 if (!type.Equals (expr.Type))
310 Report.Error (405, loc,
311 "Duplicate constraint `{0}' for type " +
312 "parameter `{1}'.", expr.Type, name);
316 list.Add (expr.Type);
319 iface_constraint_types = new Type [list.Count];
320 list.CopyTo (iface_constraint_types, 0);
322 if (class_constraint != null) {
323 class_constraint_type = class_constraint.Type;
324 if (class_constraint_type == null)
327 if (class_constraint_type.IsSealed) {
328 Report.Error (701, loc,
329 "`{0}' is not a valid bound. Bounds " +
330 "must be interfaces or non sealed " +
331 "classes", class_constraint_type);
335 if ((class_constraint_type == TypeManager.array_type) ||
336 (class_constraint_type == TypeManager.delegate_type) ||
337 (class_constraint_type == TypeManager.enum_type) ||
338 (class_constraint_type == TypeManager.value_type) ||
339 (class_constraint_type == TypeManager.object_type)) {
340 Report.Error (702, loc,
341 "Bound cannot be special class `{0}'",
342 class_constraint_type);
347 if (class_constraint_type != null)
348 effective_base_type = class_constraint_type;
349 else if (HasValueTypeConstraint)
350 effective_base_type = TypeManager.value_type;
352 effective_base_type = TypeManager.object_type;
357 public bool CheckDependencies (EmitContext ec)
359 foreach (TypeParameterExpr expr in type_param_constraints) {
360 if (!CheckDependencies (expr.TypeParameter, ec))
367 bool CheckDependencies (TypeParameter tparam, EmitContext ec)
369 Constraints constraints = tparam.Constraints;
370 if (constraints == null)
373 if (HasValueTypeConstraint && constraints.HasClassConstraint) {
374 Report.Error (455, loc, "Type parameter `{0}' inherits " +
375 "conflicting constraints `{1}' and `{2}'",
376 name, constraints.ClassConstraint,
381 if (HasClassConstraint && constraints.HasClassConstraint) {
382 Type t1 = ClassConstraint;
383 TypeExpr e1 = class_constraint;
384 Type t2 = constraints.ClassConstraint;
385 TypeExpr e2 = constraints.class_constraint;
387 if (!Convert.ImplicitReferenceConversionExists (ec, e1, t2) &&
388 !Convert.ImplicitReferenceConversionExists (ec, e2, t1)) {
389 Report.Error (455, loc,
390 "Type parameter `{0}' inherits " +
391 "conflicting constraints `{1}' and `{2}'",
397 if (constraints.type_param_constraints == null)
400 foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
401 if (!CheckDependencies (expr.TypeParameter, ec))
408 public void Define (GenericTypeParameterBuilder type)
410 type.SetGenericParameterAttributes (attrs);
413 public override GenericParameterAttributes Attributes {
414 get { return attrs; }
417 public override bool HasClassConstraint {
418 get { return class_constraint != null; }
421 public override Type ClassConstraint {
422 get { return class_constraint_type; }
425 public override Type[] InterfaceConstraints {
426 get { return iface_constraint_types; }
429 public override Type EffectiveBaseClass {
430 get { return effective_base_type; }
433 internal bool IsSubclassOf (Type t)
435 if ((class_constraint_type != null) &&
436 class_constraint_type.IsSubclassOf (t))
439 if (iface_constraint_types == null)
442 foreach (Type iface in iface_constraint_types) {
443 if (TypeManager.IsSubclassOf (iface, t))
450 public bool CheckInterfaceMethod (EmitContext ec, GenericConstraints gc)
452 if (!ResolveTypes (ec))
455 if (gc.Attributes != attrs)
458 if (HasClassConstraint != gc.HasClassConstraint)
460 if (HasClassConstraint && !TypeManager.IsEqual (gc.ClassConstraint, ClassConstraint))
463 int gc_icount = gc.InterfaceConstraints != null ?
464 gc.InterfaceConstraints.Length : 0;
465 int icount = InterfaceConstraints != null ?
466 InterfaceConstraints.Length : 0;
468 if (gc_icount != icount)
471 foreach (Type iface in gc.InterfaceConstraints) {
473 foreach (Type check in InterfaceConstraints) {
474 if (TypeManager.IsEqual (iface, check)) {
489 // This type represents a generic type parameter
491 public class TypeParameter : MemberCore, IMemberContainer {
493 GenericConstraints gc;
494 Constraints constraints;
496 GenericTypeParameterBuilder type;
498 public TypeParameter (TypeContainer parent, string name,
499 Constraints constraints, Location loc)
500 : base (parent, new MemberName (name), null, loc)
503 this.constraints = constraints;
507 public GenericConstraints GenericConstraints {
509 return gc != null ? gc : constraints;
513 public Constraints Constraints {
519 public bool HasConstructorConstraint {
521 if (constraints != null)
522 return constraints.HasConstructorConstraint;
534 public bool Resolve (DeclSpace ds)
536 if (constraints != null)
537 return constraints.Resolve (ds.EmitContext);
542 public void Define (GenericTypeParameterBuilder type)
544 if (this.type != null)
545 throw new InvalidOperationException ();
548 TypeManager.AddTypeParameter (type, this);
551 public void DefineConstraints ()
553 if (constraints != null)
554 constraints.Define (type);
557 public bool DefineType (EmitContext ec)
559 return DefineType (ec, null, null, false);
562 public bool DefineType (EmitContext ec, MethodBuilder builder,
563 MethodInfo implementing, bool is_override)
565 if (implementing != null) {
566 if (is_override && (constraints != null)) {
568 460, loc, "Constraints for override and " +
569 "explicit interface implementation methods " +
570 "are inherited from the base method so they " +
571 "cannot be specified directly");
575 MethodBase mb = implementing;
576 if (mb.Mono_IsInflatedMethod)
577 mb = mb.GetGenericMethodDefinition ();
579 int pos = type.GenericParameterPosition;
580 ParameterData pd = Invocation.GetParameterData (mb);
581 GenericConstraints temp_gc = pd.GenericConstraints (pos);
582 Type mparam = mb.GetGenericArguments () [pos];
585 gc = new InflatedConstraints (temp_gc, implementing.DeclaringType);
586 else if (constraints != null)
587 gc = new InflatedConstraints (constraints, implementing.DeclaringType);
590 if (constraints != null) {
593 else if (!constraints.CheckInterfaceMethod (ec, gc))
596 if (!is_override && (temp_gc != null))
601 Report.SymbolRelatedToPreviousError (implementing);
604 425, loc, "The constraints for type " +
605 "parameter `{0}' of method `{1}' must match " +
606 "the constraints for type parameter `{2}' " +
607 "of interface method `{3}'. Consider using " +
608 "an explicit interface implementation instead",
609 Name, TypeManager.CSharpSignature (builder),
610 mparam, TypeManager.CSharpSignature (mb));
614 if (constraints != null) {
615 if (!constraints.ResolveTypes (ec))
619 gc = (GenericConstraints) constraints;
625 if (gc.HasClassConstraint)
626 type.SetBaseTypeConstraint (gc.ClassConstraint);
628 type.SetInterfaceConstraints (gc.InterfaceConstraints);
629 TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
634 public bool CheckDependencies (EmitContext ec)
636 if (constraints != null)
637 return constraints.CheckDependencies (ec);
642 public override string DocCommentHeader {
644 throw new InvalidOperationException (
645 "Unexpected attempt to get doc comment from " + this.GetType () + ".");
653 public override bool Define ()
658 protected override void VerifyObsoleteAttribute ()
661 public override void ApplyAttributeBuilder (Attribute a,
662 CustomAttributeBuilder cb)
665 public override AttributeTargets AttributeTargets {
667 return (AttributeTargets) 0;
671 public override string[] ValidAttributeTargets {
673 return new string [0];
681 string IMemberContainer.Name {
685 MemberCache IMemberContainer.ParentCache {
689 bool IMemberContainer.IsInterface {
693 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
695 return FindMembers (mt, bf, null, null);
698 MemberCache IMemberContainer.MemberCache {
702 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
703 MemberFilter filter, object criteria)
705 if (constraints == null)
706 return MemberList.Empty;
708 ArrayList members = new ArrayList ();
710 GenericConstraints gc = (GenericConstraints) constraints;
712 if (gc.HasClassConstraint) {
713 MemberList list = TypeManager.FindMembers (
714 gc.ClassConstraint, mt, bf, filter, criteria);
716 members.AddRange (list);
719 foreach (Type t in gc.InterfaceConstraints) {
720 MemberList list = TypeManager.FindMembers (
721 t, mt, bf, filter, criteria);
723 members.AddRange (list);
726 return new MemberList (members);
729 public bool IsSubclassOf (Type t)
734 if (constraints != null)
735 return constraints.IsSubclassOf (t);
740 public override string ToString ()
742 return "TypeParameter[" + name + "]";
745 protected class InflatedConstraints : GenericConstraints
747 GenericConstraints gc;
749 Type class_constraint;
750 Type[] iface_constraints;
754 public InflatedConstraints (GenericConstraints gc, Type declaring)
757 this.declaring = declaring;
759 dargs = TypeManager.GetTypeArguments (declaring);
761 ArrayList list = new ArrayList ();
762 if (gc.HasClassConstraint)
763 list.Add (inflate (gc.ClassConstraint));
764 foreach (Type iface in gc.InterfaceConstraints)
765 list.Add (inflate (iface));
767 bool has_class_constr = false;
768 if (list.Count > 0) {
769 Type first = (Type) list [0];
770 has_class_constr = !first.IsInterface && !first.IsGenericParameter;
773 if ((list.Count > 0) && has_class_constr) {
774 class_constraint = (Type) list [0];
775 iface_constraints = new Type [list.Count - 1];
776 list.CopyTo (1, iface_constraints, 0, list.Count - 1);
778 iface_constraints = new Type [list.Count];
779 list.CopyTo (iface_constraints, 0);
782 if (HasValueTypeConstraint)
783 base_type = TypeManager.value_type;
784 else if (class_constraint != null)
785 base_type = class_constraint;
787 base_type = TypeManager.object_type;
790 Type inflate (Type t)
794 if (t.IsGenericParameter)
795 return dargs [t.GenericParameterPosition];
796 if (t.IsGenericInstance) {
797 t = t.GetGenericTypeDefinition ();
798 t = t.BindGenericParameters (dargs);
804 public override GenericParameterAttributes Attributes {
805 get { return gc.Attributes; }
808 public override Type ClassConstraint {
809 get { return class_constraint; }
812 public override Type EffectiveBaseClass {
813 get { return base_type; }
816 public override Type[] InterfaceConstraints {
817 get { return iface_constraints; }
823 // This type represents a generic type parameter reference.
825 // These expressions are born in a fully resolved state.
827 public class TypeParameterExpr : TypeExpr {
828 TypeParameter type_parameter;
830 public override string Name {
832 return type_parameter.Name;
836 public TypeParameter TypeParameter {
838 return type_parameter;
842 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
844 this.type_parameter = type_parameter;
848 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
850 type = type_parameter.Type;
855 public override bool IsInterface {
856 get { return false; }
859 public override bool CheckAccessLevel (DeclSpace ds)
864 public void Error_CannotUseAsUnmanagedType (Location loc)
866 Report.Error (-203, loc, "Can not use type parameter as unamanged type");
870 public class TypeArguments {
871 public readonly Location Location;
878 public TypeArguments (Location loc)
880 args = new ArrayList ();
884 public TypeArguments (int dimension, Location loc)
886 this.dimension = dimension;
890 public void Add (Expression type)
893 throw new InvalidOperationException ();
898 public void Add (TypeArguments new_args)
901 throw new InvalidOperationException ();
903 args.AddRange (new_args.args);
906 public string[] GetDeclarations ()
908 string[] ret = new string [args.Count];
909 for (int i = 0; i < args.Count; i++) {
910 SimpleName sn = args [i] as SimpleName;
916 Report.Error (81, Location, "Type parameter declaration " +
917 "must be an identifier not a type");
923 public Type[] Arguments {
929 public bool HasTypeArguments {
931 return has_type_args;
944 public bool IsUnbound {
946 return dimension > 0;
950 public override string ToString ()
952 StringBuilder s = new StringBuilder ();
955 for (int i = 0; i < count; i++){
957 // FIXME: Use TypeManager.CSharpname once we have the type
960 s.Append (args [i].ToString ());
964 return s.ToString ();
967 public bool Resolve (EmitContext ec)
969 DeclSpace ds = ec.DeclSpace;
970 int count = args.Count;
973 atypes = new Type [count];
975 for (int i = 0; i < count; i++){
976 TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec);
981 if (te is TypeParameterExpr)
982 has_type_args = true;
984 atypes [i] = te.Type;
990 public class ConstructedType : TypeExpr {
991 string name, full_name;
993 Type[] gen_params, atypes;
996 public ConstructedType (string name, TypeArguments args, Location l)
999 this.name = MemberName.MakeName (name, args.Count);
1002 eclass = ExprClass.Type;
1003 full_name = name + "<" + args.ToString () + ">";
1006 public ConstructedType (string name, TypeParameter[] type_params, Location l)
1007 : this (type_params, l)
1012 full_name = name + "<" + args.ToString () + ">";
1015 protected ConstructedType (TypeArguments args, Location l)
1020 eclass = ExprClass.Type;
1023 protected ConstructedType (TypeParameter[] type_params, Location l)
1027 args = new TypeArguments (l);
1028 foreach (TypeParameter type_param in type_params)
1029 args.Add (new TypeParameterExpr (type_param, l));
1031 eclass = ExprClass.Type;
1034 public ConstructedType (Type t, TypeParameter[] type_params, Location l)
1035 : this (type_params, l)
1037 gt = t.GetGenericTypeDefinition ();
1039 this.name = gt.FullName;
1040 full_name = gt.FullName + "<" + args.ToString () + ">";
1043 public ConstructedType (Type t, TypeArguments args, Location l)
1046 gt = t.GetGenericTypeDefinition ();
1048 this.name = gt.FullName;
1049 full_name = gt.FullName + "<" + args.ToString () + ">";
1052 public TypeArguments TypeArguments {
1053 get { return args; }
1056 protected string DeclarationName {
1058 StringBuilder sb = new StringBuilder ();
1059 sb.Append (gt.FullName);
1061 for (int i = 0; i < gen_params.Length; i++) {
1064 sb.Append (gen_params [i]);
1067 return sb.ToString ();
1071 protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
1074 if (TypeManager.HasGenericArguments (ctype)) {
1075 Type[] types = TypeManager.GetTypeArguments (ctype);
1077 TypeArguments new_args = new TypeArguments (loc);
1079 for (int i = 0; i < types.Length; i++) {
1082 if (t.IsGenericParameter) {
1083 int pos = t.GenericParameterPosition;
1084 t = args.Arguments [pos];
1086 new_args.Add (new TypeExpression (t, loc));
1089 TypeExpr ct = new ConstructedType (ctype, new_args, loc);
1090 if (ct.ResolveAsTypeTerminal (ec) == null)
1095 return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
1098 protected bool CheckConstraints (EmitContext ec, int index)
1100 Type atype = atypes [index];
1101 Type ptype = gen_params [index];
1106 Expression aexpr = new EmptyExpression (atype);
1108 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype);
1113 // First, check the `class' and `struct' constraints.
1115 if (gc.HasReferenceTypeConstraint && !atype.IsClass) {
1116 Report.Error (452, loc, "The type `{0}' must be " +
1117 "a reference type in order to use it " +
1118 "as type parameter `{1}' in the " +
1119 "generic type or method `{2}'.",
1120 atype, ptype, DeclarationName);
1122 } else if (gc.HasValueTypeConstraint && !atype.IsValueType) {
1123 Report.Error (453, loc, "The type `{0}' must be " +
1124 "a value type in order to use it " +
1125 "as type parameter `{1}' in the " +
1126 "generic type or method `{2}'.",
1127 atype, ptype, DeclarationName);
1132 // The class constraint comes next.
1134 if (gc.HasClassConstraint) {
1135 if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) {
1136 Report.Error (309, loc, "The type `{0}' must be " +
1137 "convertible to `{1}' in order to " +
1138 "use it as parameter `{2}' in the " +
1139 "generic type or method `{3}'",
1140 atype, gc.ClassConstraint, ptype, DeclarationName);
1146 // Now, check the interface constraints.
1148 foreach (Type it in gc.InterfaceConstraints) {
1150 if (it.IsGenericParameter)
1151 itype = atypes [it.GenericParameterPosition];
1155 if (!CheckConstraint (ec, ptype, aexpr, itype)) {
1156 Report.Error (309, loc, "The type `{0}' must be " +
1157 "convertible to `{1}' in order to " +
1158 "use it as parameter `{2}' in the " +
1159 "generic type or method `{3}'",
1160 atype, itype, ptype, DeclarationName);
1166 // Finally, check the constructor constraint.
1169 if (!gc.HasConstructorConstraint)
1172 if (TypeManager.IsBuiltinType (atype))
1175 MethodGroupExpr mg = Expression.MemberLookup (
1176 ec, atype, ".ctor", MemberTypes.Constructor,
1177 BindingFlags.Public | BindingFlags.Instance |
1178 BindingFlags.DeclaredOnly, loc)
1181 if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
1182 Report.Error (310, loc, "The type `{0}' must have a public " +
1183 "parameterless constructor in order to use it " +
1184 "as parameter `{1}' in the generic type or " +
1185 "method `{2}'", atype, ptype, DeclarationName);
1192 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
1194 if (!ResolveConstructedType (ec))
1200 public bool CheckConstraints (EmitContext ec)
1202 for (int i = 0; i < gen_params.Length; i++) {
1203 if (!CheckConstraints (ec, i))
1210 public override TypeExpr ResolveAsTypeTerminal (EmitContext ec)
1212 if (base.ResolveAsTypeTerminal (ec) == null)
1215 if (!CheckConstraints (ec))
1221 public bool ResolveConstructedType (EmitContext ec)
1226 return DoResolveType (ec);
1229 // First, resolve the generic type.
1232 Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
1233 if (nested != null) {
1234 gt = nested.GetGenericTypeDefinition ();
1236 TypeArguments new_args = new TypeArguments (loc);
1238 foreach (TypeParameter param in ds.TypeParameters)
1239 new_args.Add (new TypeParameterExpr (param, loc));
1241 new_args.Add (args);
1244 return DoResolveType (ec);
1250 SimpleName sn = new SimpleName (name, loc);
1251 TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
1252 if (resolved == null)
1257 Report.Error (246, loc, "Cannot find type `{0}'<...>",
1262 num_args = TypeManager.GetNumberOfTypeArguments (t);
1263 if (num_args == 0) {
1264 Report.Error (308, loc,
1265 "The non-generic type `{0}' cannot " +
1266 "be used with type arguments.",
1267 TypeManager.CSharpName (t));
1271 gt = t.GetGenericTypeDefinition ();
1272 return DoResolveType (ec);
1275 bool DoResolveType (EmitContext ec)
1278 // Resolve the arguments.
1280 if (args.Resolve (ec) == false)
1283 gen_params = gt.GetGenericArguments ();
1284 atypes = args.Arguments;
1286 if (atypes.Length != gen_params.Length) {
1287 Report.Error (305, loc,
1288 "Using the generic type `{0}' " +
1289 "requires {1} type arguments",
1290 TypeManager.GetFullName (gt),
1296 // Now bind the parameters.
1298 type = gt.BindGenericParameters (atypes);
1302 public Expression GetSimpleName (EmitContext ec)
1304 return new SimpleName (Basename, args, loc);
1307 public override bool CheckAccessLevel (DeclSpace ds)
1309 return ds.CheckAccessLevel (gt);
1312 public override bool AsAccessible (DeclSpace ds, int flags)
1314 return ds.AsAccessible (gt, flags);
1317 public override bool IsClass {
1318 get { return gt.IsClass; }
1321 public override bool IsValueType {
1322 get { return gt.IsValueType; }
1325 public override bool IsInterface {
1326 get { return gt.IsInterface; }
1329 public override bool IsSealed {
1330 get { return gt.IsSealed; }
1333 public override bool IsAttribute {
1334 get { return false; }
1337 public override bool Equals (object obj)
1339 ConstructedType cobj = obj as ConstructedType;
1343 if ((type == null) || (cobj.type == null))
1346 return type == cobj.type;
1349 public string Basename {
1351 int pos = name.LastIndexOf ('`');
1353 return name.Substring (0, pos);
1359 public override string Name {
1366 public class GenericMethod : DeclSpace
1368 public GenericMethod (NamespaceEntry ns, TypeContainer parent,
1369 MemberName name, Location l)
1370 : base (ns, parent, name, null, l)
1373 public override TypeBuilder DefineType ()
1375 throw new Exception ();
1378 public override bool Define ()
1380 for (int i = 0; i < TypeParameters.Length; i++)
1381 if (!TypeParameters [i].Resolve (Parent))
1387 public bool Define (MethodBuilder mb, Type return_type)
1392 GenericTypeParameterBuilder[] gen_params;
1393 string[] names = MemberName.TypeArguments.GetDeclarations ();
1394 gen_params = mb.DefineGenericParameters (names);
1395 for (int i = 0; i < TypeParameters.Length; i++)
1396 TypeParameters [i].Define (gen_params [i]);
1398 ec = new EmitContext (
1399 this, this, Location, null, return_type, ModFlags, false);
1404 public bool DefineType (EmitContext ec, MethodBuilder mb,
1405 MethodInfo implementing, bool is_override)
1407 for (int i = 0; i < TypeParameters.Length; i++)
1408 if (!TypeParameters [i].DefineType (
1409 ec, mb, implementing, is_override))
1415 public override bool DefineMembers (TypeContainer parent)
1420 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1421 MemberFilter filter, object criteria)
1423 throw new Exception ();
1426 public override MemberCache MemberCache {
1428 throw new Exception ();
1432 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
1437 protected override void VerifyObsoleteAttribute()
1442 public override AttributeTargets AttributeTargets {
1444 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1448 public override string DocCommentHeader {
1449 get { return "M:"; }
1453 public class DefaultValueExpression : Expression
1456 LocalTemporary temp_storage;
1458 public DefaultValueExpression (Expression expr, Location loc)
1464 public override Expression DoResolve (EmitContext ec)
1466 TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
1471 if (type.IsGenericParameter || TypeManager.IsValueType (type))
1472 temp_storage = new LocalTemporary (ec, type);
1474 eclass = ExprClass.Variable;
1478 public override void Emit (EmitContext ec)
1480 if (temp_storage != null) {
1481 temp_storage.AddressOf (ec, AddressOp.LoadStore);
1482 ec.ig.Emit (OpCodes.Initobj, type);
1483 temp_storage.Emit (ec);
1485 ec.ig.Emit (OpCodes.Ldnull);