* generic.cs (DropGenericTypeArguments): New. Captures the common
[mono.git] / mcs / gmcs / generic.cs
index 57152c8e2dd05eac63a9ccb50fbd104b3dbcadca..e938019b20b78863e1daec5f84f8718d9579ede7 100644 (file)
@@ -223,7 +223,7 @@ namespace Mono.CSharp {
                                        if (errors != Report.Errors)
                                                return false;
 
-                                       Report.Error (246, loc, "Cannot find type '{0}'", obj);
+                                       Report.Error (246, loc, "Cannot find type '{0}'", ((Expression) obj).GetSignatureForError ());
                                        return false;
                                }
 
@@ -270,7 +270,7 @@ namespace Mono.CSharp {
 
                                        Report.Error (405, loc,
                                                      "Duplicate constraint `{0}' for type " +
-                                                     "parameter `{1}'.", iface_constraint.Type,
+                                                     "parameter `{1}'.", iface_constraint.GetSignatureForError (),
                                                      name);
                                        return false;
                                }
@@ -285,30 +285,15 @@ namespace Mono.CSharp {
 
                                        Report.Error (405, loc,
                                                      "Duplicate constraint `{0}' for type " +
-                                                     "parameter `{1}'.", expr.Type, name);
+                                                     "parameter `{1}'.", expr.GetSignatureForError (), name);
                                        return false;
                                }
 
                                list.Add (expr.Type);
                        }
 
-                       ArrayList new_list = new ArrayList ();
-                       foreach (Type iface in list) {
-                               if (new_list.Contains (iface))
-                                       continue;
-
-                               new_list.Add (iface);
-
-                               Type [] implementing = TypeManager.GetInterfaces (iface);
-
-                               foreach (Type imp in implementing) {
-                                       if (!new_list.Contains (imp))
-                                               new_list.Add (imp);
-                               }
-                       }
-
-                       iface_constraint_types = new Type [new_list.Count];
-                       new_list.CopyTo (iface_constraint_types, 0);
+                       iface_constraint_types = new Type [list.Count];
+                       list.CopyTo (iface_constraint_types, 0);
 
                        if (class_constraint != null) {
                                class_constraint_type = class_constraint.Type;
@@ -319,7 +304,7 @@ namespace Mono.CSharp {
                                        Report.Error (701, loc,
                                                      "`{0}' is not a valid bound.  Bounds " +
                                                      "must be interfaces or non sealed " +
-                                                     "classes", class_constraint_type);
+                                                     "classes", TypeManager.CSharpName (class_constraint_type));
                                        return false;
                                }
 
@@ -330,7 +315,7 @@ namespace Mono.CSharp {
                                    (class_constraint_type == TypeManager.object_type)) {
                                        Report.Error (702, loc,
                                                      "Bound cannot be special class `{0}'",
-                                                     class_constraint_type);
+                                                     TypeManager.CSharpName (class_constraint_type));
                                        return false;
                                }
                        }
@@ -446,7 +431,7 @@ namespace Mono.CSharp {
                        if (HasValueTypeConstraint && constraints.HasClassConstraint) {
                                Report.Error (455, loc, "Type parameter `{0}' inherits " +
                                              "conflicting constraints `{1}' and `{2}'",
-                                             name, constraints.ClassConstraint,
+                                             name, TypeManager.CSharpName (constraints.ClassConstraint),
                                              "System.ValueType");
                                return false;
                        }
@@ -462,7 +447,7 @@ namespace Mono.CSharp {
                                        Report.Error (455, loc,
                                                      "Type parameter `{0}' inherits " +
                                                      "conflicting constraints `{1}' and `{2}'",
-                                                     name, t1, t2);
+                                                     name, TypeManager.CSharpName (t1), TypeManager.CSharpName (t2));
                                        return false;
                                }
                        }
@@ -478,18 +463,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               /// <summary>
-               ///   Set the attributes on the GenericTypeParameterBuilder.
-               /// </summary>
-               /// <remarks>
-               ///   This is not done in Resolve() since Resolve() may be called before
-               ///   the GenericTypeParameterBuilder is created (partial generic classes).
-               /// </remarks>
-               public void Define (GenericTypeParameterBuilder type)
-               {
-                       type.SetGenericParameterAttributes (attrs);
-               }
-
                public override GenericParameterAttributes Attributes {
                        get { return attrs; }
                }
@@ -581,8 +554,8 @@ namespace Mono.CSharp {
                GenericTypeParameterBuilder type;
 
                public TypeParameter (TypeContainer parent, DeclSpace decl, string name,
-                                     Constraints constraints, Location loc)
-                       : base (parent, new MemberName (name, loc), null)
+                                     Constraints constraints, Attributes attrs, Location loc)
+                       : base (parent, new MemberName (name, loc), attrs)
                {
                        this.name = name;
                        this.decl = decl;
@@ -668,23 +641,6 @@ namespace Mono.CSharp {
 
                /// <summary>
                ///   This is the third method which is called during the resolving
-               ///   process.  We're called immediately after calling Resolve() on
-               ///   all of the current class'es type parameters.
-               ///
-               ///   All we do is setting the attributes on the GenericTypeParameterBuilder.
-               /// </summary>
-               /// <remarks>
-               ///   This is not done in Resolve() since Resolve() may be called before
-               ///   Define() for partial generic classes.
-               /// </remarks>
-               public void DefineConstraints ()
-               {
-                       if (constraints != null)
-                               constraints.Define (type);
-               }
-
-               /// <summary>
-               ///   This is the forth method which is called during the resolving
                ///   process.  We're called immediately after calling DefineConstraints()
                ///   on all of the current class'es type parameters.
                ///
@@ -706,7 +662,7 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///   This is the fith and last method which is called during the resolving
+               ///   This is the fourth 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.
                /// </summary>
@@ -744,9 +700,8 @@ namespace Mono.CSharp {
                                        mb = mb.GetGenericMethodDefinition ();
 
                                int pos = type.GenericParameterPosition;
-                               ParameterData pd = TypeManager.GetParameterData (mb);
-                               GenericConstraints temp_gc = pd.GenericConstraints (pos);
                                Type mparam = mb.GetGenericArguments () [pos];
+                               GenericConstraints temp_gc = ReflectionConstraints.GetConstraints (mparam);
 
                                if (temp_gc != null)
                                        gc = new InflatedConstraints (temp_gc, implementing.DeclaringType);
@@ -771,10 +726,10 @@ namespace Mono.CSharp {
                                                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 " +
+                                               "of interface method `{3}'. Consider using " +
                                                "an explicit interface implementation instead",
                                                Name, TypeManager.CSharpSignature (builder),
-                                               mparam, TypeManager.CSharpSignature (mb));
+                                               TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb));
                                        return false;
                                }
                        } else if (DeclSpace is Iterator) {
@@ -796,6 +751,7 @@ namespace Mono.CSharp {
                                type.SetBaseTypeConstraint (gc.ClassConstraint);
 
                        type.SetInterfaceConstraints (gc.InterfaceConstraints);
+                       type.SetGenericParameterAttributes (gc.Attributes);
                        TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
 
                        return true;
@@ -845,6 +801,12 @@ namespace Mono.CSharp {
                        return constraints.CheckInterfaceMethod (ec, new_constraints);
                }
 
+               public void EmitAttributes (EmitContext ec)
+               {
+                       if (OptAttributes != null)
+                               OptAttributes.Emit (ec, this);
+               }
+
                public override string DocCommentHeader {
                        get {
                                throw new InvalidOperationException (
@@ -863,17 +825,19 @@ namespace Mono.CSharp {
 
                public override void ApplyAttributeBuilder (Attribute a,
                                                            CustomAttributeBuilder cb)
-               { }
+               {
+                       type.SetCustomAttribute (cb);
+               }
 
                public override AttributeTargets AttributeTargets {
                        get {
-                               return (AttributeTargets) 0;
+                               return (AttributeTargets) AttributeTargets.GenericParameter;
                        }
                }
 
                public override string[] ValidAttributeTargets {
                        get {
-                               return new string [0];
+                               return new string [] { "type parameter" };
                        }
                }
 
@@ -919,7 +883,8 @@ namespace Mono.CSharp {
                                members.AddRange (list);
                        }
 
-                       foreach (Type t in gc.InterfaceConstraints) {
+                       Type[] ifaces = TypeManager.ExpandInterfaces (gc.InterfaceConstraints);
+                       foreach (Type t in ifaces) {
                                MemberList list = TypeManager.FindMembers (
                                        t, mt, bf, filter, criteria);
 
@@ -945,6 +910,21 @@ namespace Mono.CSharp {
                        return "TypeParameter[" + name + "]";
                }
 
+               public static string GetSignatureForError (TypeParameter[] tp)
+               {
+                       if (tp == null || tp.Length == 0)
+                               return "";
+
+                       StringBuilder sb = new StringBuilder ("<");
+                       for (int i = 0; i < tp.Length; ++i) {
+                               if (i > 0)
+                                       sb.Append (",");
+                               sb.Append (tp[i].GetSignatureForError ());
+                       }
+                       sb.Append ('>');
+                       return sb.ToString ();
+               }
+
                protected class InflatedConstraints : GenericConstraints
                {
                        GenericConstraints gc;
@@ -1125,13 +1105,18 @@ namespace Mono.CSharp {
                ///   parser creates a `MemberName' with `TypeArguments' for both cases and
                ///   in case of a generic type definition, we call GetDeclarations().
                /// </summary>
-               public string[] GetDeclarations ()
+               public TypeParameterName[] GetDeclarations ()
                {
-                       string[] ret = new string [args.Count];
+                       TypeParameterName[] ret = new TypeParameterName [args.Count];
                        for (int i = 0; i < args.Count; i++) {
+                               TypeParameterName name = args [i] as TypeParameterName;
+                               if (name != null) {
+                                       ret [i] = name;
+                                       continue;
+                               }
                                SimpleName sn = args [i] as SimpleName;
                                if (sn != null) {
-                                       ret [i] = sn.Name;
+                                       ret [i] = new TypeParameterName (sn.Name, null, sn.Location);
                                        continue;
                                }
 
@@ -1213,6 +1198,10 @@ namespace Mono.CSharp {
                                        Report.Error (306, Location, "The type `{0}' may not be used " +
                                                      "as a type argument.", TypeManager.CSharpName (te.Type));
                                        return false;
+                               } else if (te.Type == TypeManager.void_type) {
+                                       Report.Error (1547, Location,
+                                                     "Keyword `void' cannot be used in this context");
+                                       return false;
                                }
 
                                atypes [i] = te.Type;
@@ -1221,6 +1210,23 @@ namespace Mono.CSharp {
                }
        }
 
+       public class TypeParameterName : SimpleName
+       {
+               Attributes attributes;
+
+               public TypeParameterName (string name, Attributes attrs, Location loc)
+                       : base (name, loc)
+               {
+                       attributes = attrs;
+               }
+
+               public Attributes OptAttributes {
+                       get {
+                               return attributes;
+                       }
+               }
+       }
+
        /// <summary>
        ///   An instantiation of a generic type.
        /// </summary>  
@@ -1293,46 +1299,174 @@ namespace Mono.CSharp {
                        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 ();
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.CSharpName (gt);
+               }
+
+               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               {
+                       if (!ResolveConstructedType (ec))
+                               return null;
+
+                       return this;
+               }
+
+               /// <summary>
+               ///   Check the constraints; we're called from ResolveAsTypeTerminal()
+               ///   after fully resolving the constructed type.
+               /// </summary>
+               public bool CheckConstraints (EmitContext ec)
+               {
+                       return ConstraintChecker.CheckConstraints (ec, gt, gen_params, atypes, loc);
+               }
+
+               /// <summary>
+               ///   Resolve the constructed type, but don't check the constraints.
+               /// </summary>
+               public bool ResolveConstructedType (EmitContext ec)
+               {
+                       if (type != null)
+                               return true;
+                       // If we already know the fully resolved generic type.
+                       if (gt != null)
+                               return DoResolveType (ec);
+
+                       int num_args;
+                       Type t = name.Type;
+
+                       if (t == null) {
+                               Report.Error (246, loc, "Cannot find type `{0}'<...>", Name);
+                               return false;
+                       }
+
+                       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 false;
                        }
+
+                       gt = t.GetGenericTypeDefinition ();
+                       return DoResolveType (ec);
                }
 
-               protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
-                                               Type ctype)
+               bool DoResolveType (EmitContext ec)
                {
-                       if (TypeManager.HasGenericArguments (ctype)) {
-                               Type[] types = TypeManager.GetTypeArguments (ctype);
+                       //
+                       // Resolve the arguments.
+                       //
+                       if (args.Resolve (ec) == false)
+                               return false;
 
-                               TypeArguments new_args = new TypeArguments (loc);
+                       gen_params = gt.GetGenericArguments ();
+                       atypes = args.Arguments;
 
-                               for (int i = 0; i < types.Length; i++) {
-                                       Type t = types [i];
+                       if (atypes.Length != gen_params.Length) {
+                               Report.Error (305, loc,
+                                             "Using the generic type `{0}' " +
+                                             "requires {1} type arguments",
+                                             TypeManager.CSharpName (gt),
+                                             gen_params.Length.ToString ());
+                               return false;
+                       }
 
-                                       if (t.IsGenericParameter) {
-                                               int pos = t.GenericParameterPosition;
-                                               t = args.Arguments [pos];
-                                       }
-                                       new_args.Add (new TypeExpression (t, loc));
-                               }
+                       //
+                       // Now bind the parameters.
+                       //
+                       type = gt.MakeGenericType (atypes);
+                       return true;
+               }
 
-                               TypeExpr ct = new ConstructedType (ctype, new_args, loc);
-                               if (ct.ResolveAsTypeStep (ec) == null)
+               public Expression GetSimpleName (EmitContext ec)
+               {
+                       return this;
+               }
+
+               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 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 override int GetHashCode ()
+               {
+                       return base.GetHashCode ();
+               }
+
+               public override string Name {
+                       get {
+                               return full_name;
+                       }
+               }
+
+
+               public override string FullName {
+                       get {
+                               return full_name;
+                       }
+               }
+       }
+
+       public abstract class ConstraintChecker
+       {
+               protected readonly Type[] gen_params;
+               protected readonly Type[] atypes;
+               protected readonly Location loc;
+
+               protected ConstraintChecker (Type[] gen_params, Type[] atypes, Location loc)
+               {
+                       this.gen_params = gen_params;
+                       this.atypes = atypes;
+                       this.loc = loc;
+               }
+
+               /// <summary>
+               ///   Check the constraints; we're called from ResolveAsTypeTerminal()
+               ///   after fully resolving the constructed type.
+               /// </summary>
+               public bool CheckConstraints (EmitContext ec)
+               {
+                       for (int i = 0; i < gen_params.Length; i++) {
+                               if (!CheckConstraints (ec, i))
                                        return false;
-                               ctype = ct.Type;
                        }
 
-                       return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
+                       return true;
                }
 
                protected bool CheckConstraints (EmitContext ec, int index)
@@ -1371,14 +1505,18 @@ namespace Mono.CSharp {
                                              "a reference type in order to use it " +
                                              "as type parameter `{1}' in the " +
                                              "generic type or method `{2}'.",
-                                             atype, ptype, DeclarationName);
+                                             TypeManager.CSharpName (atype),
+                                             TypeManager.CSharpName (ptype),
+                                             GetSignatureForError ());
                                return false;
                        } else if (gc.HasValueTypeConstraint && !is_struct) {
                                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);
+                                             TypeManager.CSharpName (atype),
+                                             TypeManager.CSharpName (ptype),
+                                             GetSignatureForError ());
                                return false;
                        }
 
@@ -1387,11 +1525,7 @@ namespace Mono.CSharp {
                        //
                        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);
+                                       Error_TypeMustBeConvertible (atype, gc.ClassConstraint, ptype);
                                        return false;
                                }
                        }
@@ -1407,11 +1541,7 @@ namespace Mono.CSharp {
                                        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);
+                                       Error_TypeMustBeConvertible (atype, itype, ptype);
                                        return false;
                                }
                        }
@@ -1429,13 +1559,45 @@ namespace Mono.CSharp {
                        if (HasDefaultConstructor (ec, atype))
                                return true;
 
+                       Report_SymbolRelatedToPreviousError ();
+                       Report.SymbolRelatedToPreviousError (atype);
                        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);
+                                     "method `{2}'",
+                                     TypeManager.CSharpName (atype),
+                                     TypeManager.CSharpName (ptype),
+                                     GetSignatureForError ());
                        return false;
                }
 
+               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 = atypes [pos];
+                                       }
+                                       new_args.Add (new TypeExpression (t, loc));
+                               }
+
+                               TypeExpr ct = new ConstructedType (ctype, new_args, loc);
+                               if (ct.ResolveAsTypeStep (ec) == null)
+                                       return false;
+                               ctype = ct.Type;
+                       }
+
+                       return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
+               }
+
                bool HasDefaultConstructor (EmitContext ec, Type atype)
                {
                        if (atype is TypeBuilder) {
@@ -1449,8 +1611,7 @@ namespace Mono.CSharp {
                                        if ((c.Parameters.FixedParameters != null) &&
                                            (c.Parameters.FixedParameters.Length != 0))
                                                continue;
-                                       if (c.Parameters.HasArglist ||
-                                           (c.Parameters.ArrayParameter != null))
+                                       if (c.Parameters.HasArglist || c.Parameters.HasParams)
                                                continue;
 
                                        return true;
@@ -1474,145 +1635,80 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
-               {
-                       if (!ResolveConstructedType (ec))
-                               return null;
-
-                       return this;
-               }
+               protected abstract string GetSignatureForError ();
+               protected abstract void Report_SymbolRelatedToPreviousError ();
 
-               /// <summary>
-               ///   Check the constraints; we're called from ResolveAsTypeTerminal()
-               ///   after fully resolving the constructed type.
-               /// </summary>
-               public bool CheckConstraints (EmitContext ec)
+               void Error_TypeMustBeConvertible (Type atype, Type gc, Type ptype)
                {
-                       for (int i = 0; i < gen_params.Length; i++) {
-                               if (!CheckConstraints (ec, i))
-                                       return false;
-                       }
-
-                       return true;
+                       Report_SymbolRelatedToPreviousError ();
+                       Report.SymbolRelatedToPreviousError (atype);
+                       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}'",
+                                     TypeManager.CSharpName (atype), TypeManager.CSharpName (gc),
+                                     TypeManager.CSharpName (ptype), GetSignatureForError ());
                }
 
-               /// <summary>
-               ///   Resolve the constructed type, but don't check the constraints.
-               /// </summary>
-               public bool ResolveConstructedType (EmitContext ec)
+               public static bool CheckConstraints (EmitContext ec, MethodBase definition,
+                                                    MethodBase instantiated, Location loc)
                {
-                       if (type != null)
-                               return true;
-                       // If we already know the fully resolved generic type.
-                       if (gt != null)
-                               return DoResolveType (ec);
-
-                       int num_args;
-                       Type t = name.Type;
+                       MethodConstraintChecker checker = new MethodConstraintChecker (
+                               definition, definition.GetGenericArguments (),
+                               instantiated.GetGenericArguments (), loc);
 
-                       if (t == null) {
-                               Report.Error (246, loc, "Cannot find type `{0}'<...>", Name);
-                               return false;
-                       }
-
-                       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 false;
-                       }
-
-                       gt = t.GetGenericTypeDefinition ();
-                       return DoResolveType (ec);
+                       return checker.CheckConstraints (ec);
                }
 
-               bool DoResolveType (EmitContext ec)
+               public static bool CheckConstraints (EmitContext ec, Type gt, Type[] gen_params,
+                                                    Type[] atypes, Location loc)
                {
-                       //
-                       // Resolve the arguments.
-                       //
-                       if (args.Resolve (ec) == false)
-                               return false;
+                       TypeConstraintChecker checker = new TypeConstraintChecker (
+                               gt, gen_params, atypes, loc);
 
-                       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 false;
-                       }
-
-                       //
-                       // Now bind the parameters.
-                       //
-                       type = gt.MakeGenericType (atypes);
-                       return true;
-               }
-
-               public Expression GetSimpleName (EmitContext ec)
-               {
-                       return this;
+                       return checker.CheckConstraints (ec);
                }
 
-               public override bool CheckAccessLevel (DeclSpace ds)
-               {
-                       return ds.CheckAccessLevel (gt);
-               }
-
-               public override bool AsAccessible (DeclSpace ds, int flags)
+               protected class MethodConstraintChecker : ConstraintChecker
                {
-                       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; }
-               }
+                       MethodBase definition;
 
-               public override bool Equals (object obj)
-               {
-                       ConstructedType cobj = obj as ConstructedType;
-                       if (cobj == null)
-                               return false;
+                       public MethodConstraintChecker (MethodBase definition, Type[] gen_params,
+                                                       Type[] atypes, Location loc)
+                               : base (gen_params, atypes, loc)
+                       {
+                               this.definition = definition;
+                       }
 
-                       if ((type == null) || (cobj.type == null))
-                               return false;
+                       protected override string GetSignatureForError ()
+                       {
+                               return TypeManager.CSharpSignature (definition);
+                       }
 
-                       return type == cobj.type;
+                       protected override void Report_SymbolRelatedToPreviousError ()
+                       {
+                               Report.SymbolRelatedToPreviousError (definition);
+                       }
                }
 
-               public override int GetHashCode ()
+               protected class TypeConstraintChecker : ConstraintChecker
                {
-                       return base.GetHashCode ();
-               }
+                       Type gt;
 
-               public override string Name {
-                       get {
-                               return full_name;
+                       public TypeConstraintChecker (Type gt, Type[] gen_params, Type[] atypes,
+                                                     Location loc)
+                               : base (gen_params, atypes, loc)
+                       {
+                               this.gt = gt;
                        }
-               }
 
+                       protected override string GetSignatureForError ()
+                       {
+                               return TypeManager.CSharpName (gt);
+                       }
 
-               public override string FullName {
-                       get {
-                               return full_name;
+                       protected override void Report_SymbolRelatedToPreviousError ()
+                       {
+                               Report.SymbolRelatedToPreviousError (gt);
                        }
                }
        }
@@ -1622,9 +1718,16 @@ namespace Mono.CSharp {
        /// </summary>
        public class GenericMethod : DeclSpace
        {
-               public GenericMethod (NamespaceEntry ns, TypeContainer parent, MemberName name)
+               Expression return_type;
+               Parameters parameters;
+
+               public GenericMethod (NamespaceEntry ns, TypeContainer parent, MemberName name,
+                                     Expression return_type, Parameters parameters)
                        : base (ns, parent, name, null)
-               { }
+               {
+                       this.return_type = return_type;
+                       this.parameters = parameters;
+               }
 
                public override TypeBuilder DefineType ()
                {
@@ -1649,8 +1752,11 @@ namespace Mono.CSharp {
                public bool Define (MethodBuilder mb)
                {
                        GenericTypeParameterBuilder[] gen_params;
-                       string[] names = MemberName.TypeArguments.GetDeclarations ();
-                       gen_params = mb.DefineGenericParameters (names);
+                       TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
+                       string[] snames = new string [names.Length];
+                       for (int i = 0; i < names.Length; i++)
+                               snames [i] = names [i].Name;
+                       gen_params = mb.DefineGenericParameters (snames);
                        for (int i = 0; i < TypeParameters.Length; i++)
                                TypeParameters [i].Define (gen_params [i]);
 
@@ -1676,7 +1782,24 @@ namespace Mono.CSharp {
                                            ec, mb, implementing, is_override))
                                        return false;
 
-                       return true;
+                       bool ok = true;
+                       foreach (Parameter p in parameters.FixedParameters){
+                               if (!p.Resolve (ec))
+                                       ok = false;
+                       }
+                       if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec) == null))
+                               ok = false;
+
+                       return ok;
+               }
+
+               public void EmitAttributes (EmitContext ec)
+               {
+                       for (int i = 0; i < TypeParameters.Length; i++)
+                               TypeParameters [i].EmitAttributes (ec);
+
+                       if (OptAttributes != null)
+                               OptAttributes.Emit (ec, this);
                }
 
                public override bool DefineMembers (TypeContainer parent)
@@ -1698,7 +1821,7 @@ namespace Mono.CSharp {
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
                {
-                       // FIXME
+                       base.ApplyAttributeBuilder (a, cb);
                }
 
                public override AttributeTargets AttributeTargets {
@@ -1786,7 +1909,6 @@ namespace Mono.CSharp {
                //
                // A list of core types that the compiler requires or uses
                //
-               static public Type new_constraint_attr_type;
                static public Type activator_type;
                static public Type generic_ienumerator_type;
                static public Type generic_ienumerable_type;
@@ -1815,8 +1937,6 @@ namespace Mono.CSharp {
                static void InitGenericCoreTypes ()
                {
                        activator_type = CoreLookupType ("System", "Activator");
-                       new_constraint_attr_type = CoreLookupType (
-                               "System.Runtime.CompilerServices", "NewConstraintAttribute");
 
                        generic_ienumerator_type = CoreLookupType (
                                "System.Collections.Generic", "IEnumerator", 1);
@@ -1847,9 +1967,7 @@ namespace Mono.CSharp {
 
                public static TypeContainer LookupGenericTypeContainer (Type t)
                {
-                       while (t.IsGenericInstance)
-                               t = t.GetGenericTypeDefinition ();
-
+                       t = DropGenericTypeArguments (t);
                        return LookupTypeContainer (t);
                }
 
@@ -1867,7 +1985,7 @@ namespace Mono.CSharp {
                        if (tparam != null)
                                return tparam.GenericConstraints;
 
-                       return new ReflectionConstraints (t);
+                       return ReflectionConstraints.GetConstraints (t);
                }
 
                public static bool IsGeneric (Type t)
@@ -1913,6 +2031,16 @@ namespace Mono.CSharp {
                                return t.GetGenericArguments ();
                }
 
+               public static Type DropGenericTypeArguments (Type t)
+               {
+                       if (!t.IsGenericType)
+                               return t;
+                       // Micro-optimization: a generic typebuilder is always a generic type definition
+                       if (t is TypeBuilder)
+                               return t;
+                       return t.GetGenericTypeDefinition ();
+               }
+
                //
                // Whether `array' is an array of T and `enumerator' is `IEnumerable<T>'.
                // For instance "string[]" -> "IEnumerable<string>".
@@ -2140,14 +2268,12 @@ namespace Mono.CSharp {
                        int tcount = GetNumberOfTypeArguments (type);
                        int pcount = GetNumberOfTypeArguments (parent);
 
-                       if (type.IsGenericInstance)
-                               type = type.GetGenericTypeDefinition ();
-                       if (parent.IsGenericInstance)
-                               parent = parent.GetGenericTypeDefinition ();
-
                        if (tcount != pcount)
                                return false;
 
+                       type = DropGenericTypeArguments (type);
+                       parent = DropGenericTypeArguments (parent);
+
                        return type.Equals (parent);
                }
 
@@ -2462,11 +2588,7 @@ namespace Mono.CSharp {
 
                public static bool IsNullableType (Type t)
                {
-                       if (!t.IsGenericInstance)
-                               return false;
-
-                       Type gt = t.GetGenericTypeDefinition ();
-                       return gt == generic_nullable_type;
+                       return generic_nullable_type == DropGenericTypeArguments (t);
                }
        }
 
@@ -2485,8 +2607,8 @@ namespace Mono.CSharp {
                                Type = type;
                                UnderlyingType = TypeManager.GetTypeArguments (type) [0];
 
-                               PropertyInfo has_value_pi = type.GetProperty ("HasValue");
-                               PropertyInfo value_pi = type.GetProperty ("Value");
+                               PropertyInfo has_value_pi = TypeManager.GetProperty (type, "HasValue");
+                               PropertyInfo value_pi = TypeManager.GetProperty (type, "Value");
 
                                HasValue = has_value_pi.GetGetMethod (false);
                                Value = value_pi.GetGetMethod (false);