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);
646 public override bool Define ()
651 protected override void VerifyObsoleteAttribute ()
654 public override void ApplyAttributeBuilder (Attribute a,
655 CustomAttributeBuilder cb)
658 public override AttributeTargets AttributeTargets {
660 return (AttributeTargets) 0;
664 public override string[] ValidAttributeTargets {
666 return new string [0];
674 string IMemberContainer.Name {
678 MemberCache IMemberContainer.ParentCache {
682 bool IMemberContainer.IsInterface {
686 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
688 return FindMembers (mt, bf, null, null);
691 MemberCache IMemberContainer.MemberCache {
695 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
696 MemberFilter filter, object criteria)
698 if (constraints == null)
699 return MemberList.Empty;
701 ArrayList members = new ArrayList ();
703 GenericConstraints gc = (GenericConstraints) constraints;
705 if (gc.HasClassConstraint) {
706 MemberList list = TypeManager.FindMembers (
707 gc.ClassConstraint, mt, bf, filter, criteria);
709 members.AddRange (list);
712 foreach (Type t in gc.InterfaceConstraints) {
713 MemberList list = TypeManager.FindMembers (
714 t, mt, bf, filter, criteria);
716 members.AddRange (list);
719 return new MemberList (members);
722 public bool IsSubclassOf (Type t)
727 if (constraints != null)
728 return constraints.IsSubclassOf (t);
733 public override string ToString ()
735 return "TypeParameter[" + name + "]";
738 protected class InflatedConstraints : GenericConstraints
740 GenericConstraints gc;
742 Type class_constraint;
743 Type[] iface_constraints;
747 public InflatedConstraints (GenericConstraints gc, Type declaring)
750 this.declaring = declaring;
752 dargs = TypeManager.GetTypeArguments (declaring);
754 ArrayList list = new ArrayList ();
755 if (gc.HasClassConstraint)
756 list.Add (inflate (gc.ClassConstraint));
757 foreach (Type iface in gc.InterfaceConstraints)
758 list.Add (inflate (iface));
760 bool has_class_constr = false;
761 if (list.Count > 0) {
762 Type first = (Type) list [0];
763 has_class_constr = !first.IsInterface && !first.IsGenericParameter;
766 if ((list.Count > 0) && has_class_constr) {
767 class_constraint = (Type) list [0];
768 iface_constraints = new Type [list.Count - 1];
769 list.CopyTo (1, iface_constraints, 0, list.Count - 1);
771 iface_constraints = new Type [list.Count];
772 list.CopyTo (iface_constraints, 0);
775 if (HasValueTypeConstraint)
776 base_type = TypeManager.value_type;
777 else if (class_constraint != null)
778 base_type = class_constraint;
780 base_type = TypeManager.object_type;
783 Type inflate (Type t)
787 if (t.IsGenericParameter)
788 return dargs [t.GenericParameterPosition];
789 if (t.IsGenericInstance) {
790 t = t.GetGenericTypeDefinition ();
791 t = t.BindGenericParameters (dargs);
797 public override GenericParameterAttributes Attributes {
798 get { return gc.Attributes; }
801 public override Type ClassConstraint {
802 get { return class_constraint; }
805 public override Type EffectiveBaseClass {
806 get { return base_type; }
809 public override Type[] InterfaceConstraints {
810 get { return iface_constraints; }
816 // This type represents a generic type parameter reference.
818 // These expressions are born in a fully resolved state.
820 public class TypeParameterExpr : TypeExpr {
821 TypeParameter type_parameter;
823 public override string Name {
825 return type_parameter.Name;
829 public TypeParameter TypeParameter {
831 return type_parameter;
835 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
837 this.type_parameter = type_parameter;
841 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
843 type = type_parameter.Type;
848 public override bool IsInterface {
849 get { return false; }
852 public override bool CheckAccessLevel (DeclSpace ds)
857 public void Error_CannotUseAsUnmanagedType (Location loc)
859 Report.Error (-203, loc, "Can not use type parameter as unamanged type");
863 public class TypeArguments {
864 public readonly Location Location;
871 public TypeArguments (Location loc)
873 args = new ArrayList ();
877 public TypeArguments (int dimension, Location loc)
879 this.dimension = dimension;
883 public void Add (Expression type)
886 throw new InvalidOperationException ();
891 public void Add (TypeArguments new_args)
894 throw new InvalidOperationException ();
896 args.AddRange (new_args.args);
899 public string[] GetDeclarations ()
901 string[] ret = new string [args.Count];
902 for (int i = 0; i < args.Count; i++) {
903 SimpleName sn = args [i] as SimpleName;
909 Report.Error (81, Location, "Type parameter declaration " +
910 "must be an identifier not a type");
916 public Type[] Arguments {
922 public bool HasTypeArguments {
924 return has_type_args;
937 public bool IsUnbound {
939 return dimension > 0;
943 public override string ToString ()
945 StringBuilder s = new StringBuilder ();
948 for (int i = 0; i < count; i++){
950 // FIXME: Use TypeManager.CSharpname once we have the type
953 s.Append (args [i].ToString ());
957 return s.ToString ();
960 public bool Resolve (EmitContext ec)
962 DeclSpace ds = ec.DeclSpace;
963 int count = args.Count;
966 atypes = new Type [count];
968 for (int i = 0; i < count; i++){
969 TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec);
974 if (te is TypeParameterExpr)
975 has_type_args = true;
977 atypes [i] = te.Type;
983 public class ConstructedType : TypeExpr {
984 string name, full_name;
986 Type[] gen_params, atypes;
989 public ConstructedType (string name, TypeArguments args, Location l)
992 this.name = MemberName.MakeName (name, args.Count);
995 eclass = ExprClass.Type;
996 full_name = name + "<" + args.ToString () + ">";
999 public ConstructedType (string name, TypeParameter[] type_params, Location l)
1000 : this (type_params, l)
1005 full_name = name + "<" + args.ToString () + ">";
1008 protected ConstructedType (TypeArguments args, Location l)
1013 eclass = ExprClass.Type;
1016 protected ConstructedType (TypeParameter[] type_params, Location l)
1020 args = new TypeArguments (l);
1021 foreach (TypeParameter type_param in type_params)
1022 args.Add (new TypeParameterExpr (type_param, l));
1024 eclass = ExprClass.Type;
1027 public ConstructedType (Type t, TypeParameter[] type_params, Location l)
1028 : this (type_params, l)
1030 gt = t.GetGenericTypeDefinition ();
1032 this.name = gt.FullName;
1033 full_name = gt.FullName + "<" + args.ToString () + ">";
1036 public ConstructedType (Type t, TypeArguments args, Location l)
1039 gt = t.GetGenericTypeDefinition ();
1041 this.name = gt.FullName;
1042 full_name = gt.FullName + "<" + args.ToString () + ">";
1045 public TypeArguments TypeArguments {
1046 get { return args; }
1049 protected string DeclarationName {
1051 StringBuilder sb = new StringBuilder ();
1052 sb.Append (gt.FullName);
1054 for (int i = 0; i < gen_params.Length; i++) {
1057 sb.Append (gen_params [i]);
1060 return sb.ToString ();
1064 protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
1067 if (TypeManager.HasGenericArguments (ctype)) {
1068 Type[] types = TypeManager.GetTypeArguments (ctype);
1070 TypeArguments new_args = new TypeArguments (loc);
1072 for (int i = 0; i < types.Length; i++) {
1075 if (t.IsGenericParameter) {
1076 int pos = t.GenericParameterPosition;
1077 t = args.Arguments [pos];
1079 new_args.Add (new TypeExpression (t, loc));
1082 TypeExpr ct = new ConstructedType (ctype, new_args, loc);
1083 if (ct.ResolveAsTypeTerminal (ec) == null)
1088 return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
1091 protected bool CheckConstraints (EmitContext ec, int index)
1093 Type atype = atypes [index];
1094 Type ptype = gen_params [index];
1099 Expression aexpr = new EmptyExpression (atype);
1101 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype);
1106 // First, check the `class' and `struct' constraints.
1108 if (gc.HasReferenceTypeConstraint && !atype.IsClass) {
1109 Report.Error (452, loc, "The type `{0}' must be " +
1110 "a reference type in order to use it " +
1111 "as type parameter `{1}' in the " +
1112 "generic type or method `{2}'.",
1113 atype, ptype, DeclarationName);
1115 } else if (gc.HasValueTypeConstraint && !atype.IsValueType) {
1116 Report.Error (453, loc, "The type `{0}' must be " +
1117 "a value type in order to use it " +
1118 "as type parameter `{1}' in the " +
1119 "generic type or method `{2}'.",
1120 atype, ptype, DeclarationName);
1125 // The class constraint comes next.
1127 if (gc.HasClassConstraint) {
1128 if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) {
1129 Report.Error (309, loc, "The type `{0}' must be " +
1130 "convertible to `{1}' in order to " +
1131 "use it as parameter `{2}' in the " +
1132 "generic type or method `{3}'",
1133 atype, gc.ClassConstraint, ptype, DeclarationName);
1139 // Now, check the interface constraints.
1141 foreach (Type it in gc.InterfaceConstraints) {
1143 if (it.IsGenericParameter)
1144 itype = atypes [it.GenericParameterPosition];
1148 if (!CheckConstraint (ec, ptype, aexpr, itype)) {
1149 Report.Error (309, loc, "The type `{0}' must be " +
1150 "convertible to `{1}' in order to " +
1151 "use it as parameter `{2}' in the " +
1152 "generic type or method `{3}'",
1153 atype, itype, ptype, DeclarationName);
1159 // Finally, check the constructor constraint.
1162 if (!gc.HasConstructorConstraint)
1165 if (TypeManager.IsBuiltinType (atype))
1168 MethodGroupExpr mg = Expression.MemberLookup (
1169 ec, atype, ".ctor", MemberTypes.Constructor,
1170 BindingFlags.Public | BindingFlags.Instance |
1171 BindingFlags.DeclaredOnly, loc)
1174 if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
1175 Report.Error (310, loc, "The type `{0}' must have a public " +
1176 "parameterless constructor in order to use it " +
1177 "as parameter `{1}' in the generic type or " +
1178 "method `{2}'", atype, ptype, DeclarationName);
1185 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
1187 if (!ResolveConstructedType (ec))
1193 public bool CheckConstraints (EmitContext ec)
1195 for (int i = 0; i < gen_params.Length; i++) {
1196 if (!CheckConstraints (ec, i))
1203 public override TypeExpr ResolveAsTypeTerminal (EmitContext ec)
1205 if (base.ResolveAsTypeTerminal (ec) == null)
1208 if (!CheckConstraints (ec))
1214 public bool ResolveConstructedType (EmitContext ec)
1219 return DoResolveType (ec);
1222 // First, resolve the generic type.
1225 Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
1226 if (nested != null) {
1227 gt = nested.GetGenericTypeDefinition ();
1229 TypeArguments new_args = new TypeArguments (loc);
1231 foreach (TypeParameter param in ds.TypeParameters)
1232 new_args.Add (new TypeParameterExpr (param, loc));
1234 new_args.Add (args);
1237 return DoResolveType (ec);
1243 SimpleName sn = new SimpleName (name, loc);
1244 TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
1245 if (resolved == null)
1250 Report.Error (246, loc, "Cannot find type `{0}'<...>",
1255 num_args = TypeManager.GetNumberOfTypeArguments (t);
1256 if (num_args == 0) {
1257 Report.Error (308, loc,
1258 "The non-generic type `{0}' cannot " +
1259 "be used with type arguments.",
1260 TypeManager.CSharpName (t));
1264 gt = t.GetGenericTypeDefinition ();
1265 return DoResolveType (ec);
1268 bool DoResolveType (EmitContext ec)
1271 // Resolve the arguments.
1273 if (args.Resolve (ec) == false)
1276 gen_params = gt.GetGenericArguments ();
1277 atypes = args.Arguments;
1279 if (atypes.Length != gen_params.Length) {
1280 Report.Error (305, loc,
1281 "Using the generic type `{0}' " +
1282 "requires {1} type arguments",
1283 TypeManager.GetFullName (gt),
1289 // Now bind the parameters.
1291 type = gt.BindGenericParameters (atypes);
1295 public Expression GetSimpleName (EmitContext ec)
1297 return new SimpleName (Basename, args, loc);
1300 public override bool CheckAccessLevel (DeclSpace ds)
1302 return ds.CheckAccessLevel (gt);
1305 public override bool AsAccessible (DeclSpace ds, int flags)
1307 return ds.AsAccessible (gt, flags);
1310 public override bool IsClass {
1311 get { return gt.IsClass; }
1314 public override bool IsValueType {
1315 get { return gt.IsValueType; }
1318 public override bool IsInterface {
1319 get { return gt.IsInterface; }
1322 public override bool IsSealed {
1323 get { return gt.IsSealed; }
1326 public override bool IsAttribute {
1327 get { return false; }
1330 public override bool Equals (object obj)
1332 ConstructedType cobj = obj as ConstructedType;
1336 if ((type == null) || (cobj.type == null))
1339 return type == cobj.type;
1342 public string Basename {
1344 int pos = name.LastIndexOf ('`');
1346 return name.Substring (0, pos);
1352 public override string Name {
1359 public class GenericMethod : DeclSpace
1361 public GenericMethod (NamespaceEntry ns, TypeContainer parent,
1362 MemberName name, Location l)
1363 : base (ns, parent, name, null, l)
1366 public override TypeBuilder DefineType ()
1368 throw new Exception ();
1371 public override bool Define ()
1373 for (int i = 0; i < TypeParameters.Length; i++)
1374 if (!TypeParameters [i].Resolve (Parent))
1380 public bool Define (MethodBuilder mb, Type return_type)
1385 GenericTypeParameterBuilder[] gen_params;
1386 string[] names = MemberName.TypeArguments.GetDeclarations ();
1387 gen_params = mb.DefineGenericParameters (names);
1388 for (int i = 0; i < TypeParameters.Length; i++)
1389 TypeParameters [i].Define (gen_params [i]);
1391 ec = new EmitContext (
1392 this, this, Location, null, return_type, ModFlags, false);
1397 public bool DefineType (EmitContext ec, MethodBuilder mb,
1398 MethodInfo implementing, bool is_override)
1400 for (int i = 0; i < TypeParameters.Length; i++)
1401 if (!TypeParameters [i].DefineType (
1402 ec, mb, implementing, is_override))
1408 public override bool DefineMembers (TypeContainer parent)
1413 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1414 MemberFilter filter, object criteria)
1416 throw new Exception ();
1419 public override MemberCache MemberCache {
1421 throw new Exception ();
1425 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
1430 protected override void VerifyObsoleteAttribute()
1435 public override AttributeTargets AttributeTargets {
1437 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1442 public class DefaultValueExpression : Expression
1445 LocalTemporary temp_storage;
1447 public DefaultValueExpression (Expression expr, Location loc)
1453 public override Expression DoResolve (EmitContext ec)
1455 TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
1460 if (type.IsGenericParameter || TypeManager.IsValueType (type))
1461 temp_storage = new LocalTemporary (ec, type);
1463 eclass = ExprClass.Variable;
1467 public override void Emit (EmitContext ec)
1469 if (temp_storage != null) {
1470 temp_storage.AddressOf (ec, AddressOp.LoadStore);
1471 ec.ig.Emit (OpCodes.Initobj, type);
1472 temp_storage.Emit (ec);
1474 ec.ig.Emit (OpCodes.Ldnull);