2005-03-02 Martin Baulig <martin@ximian.com>
authorMartin Baulig <martin@novell.com>
Wed, 2 Mar 2005 16:30:29 +0000 (16:30 -0000)
committerMartin Baulig <martin@novell.com>
Wed, 2 Mar 2005 16:30:29 +0000 (16:30 -0000)
* decl.cs (DeclSpace.SetParameterInfo): Make this virtual.

* class.cs (ClassPart.SetParameterInfo): Override this.
(PartialContainer.SetParameterInfo): Override this.
(TypeContainer.CheckConstraints): New protected method.
(PartialContainer.CheckConstraints): Override this and check
whether the same contraints were specified in all parts of a
partial generic type definition.
(PartialContainer.UpdateConstraints): New public method.

* generic.cs (TypeParameter.UpdateConstraints): New public method.

svn path=/trunk/mcs/; revision=41365

mcs/gmcs/ChangeLog
mcs/gmcs/class.cs
mcs/gmcs/cs-parser.jay
mcs/gmcs/decl.cs
mcs/gmcs/generic.cs

index 9ba069116053ddbb9af6d222f48e477564bf45f5..6c243a15cea485fd45a89d9f4eab99c8bc9f9201 100644 (file)
@@ -1,3 +1,17 @@
+2005-03-02  Martin Baulig  <martin@ximian.com>
+
+       * decl.cs (DeclSpace.SetParameterInfo): Make this virtual.
+
+       * class.cs (ClassPart.SetParameterInfo): Override this.
+       (PartialContainer.SetParameterInfo): Override this.
+       (TypeContainer.CheckConstraints): New protected method.
+       (PartialContainer.CheckConstraints): Override this and check
+       whether the same contraints were specified in all parts of a
+       partial generic type definition.
+       (PartialContainer.UpdateConstraints): New public method.
+
+       * generic.cs (TypeParameter.UpdateConstraints): New public method.
+
 2005-03-02  Martin Baulig  <martin@ximian.com>
 
        Committing a patch from Carlos Alberto Cortez to fix #72887.
index dfd04c89770a5d9a8244da98b7225e2884bae5e8..c1add900dd8c2dbce7cba2276307f702e2407c6d 100644 (file)
@@ -1254,14 +1254,18 @@ namespace Mono.CSharp {
                                        CurrentTypeParameters [i - offset].DefineConstraints ();
 
                                current_type = new ConstructedType (Name, TypeParameters, Location);
-                       }
 
-                       if (IsGeneric) {
-                               foreach (TypeParameter type_param in TypeParameters)
+                               foreach (TypeParameter type_param in TypeParameters) {
                                        if (!type_param.DefineType (ec)) {
                                                error = true;
                                                return null;
                                        }
+                               }
+
+                               if (!CheckConstraints (ec)) {
+                                       error = true;
+                                       return null;
+                               }
                        }
 
                        if ((Kind == Kind.Struct) && TypeManager.value_type == null)
@@ -1377,6 +1381,11 @@ namespace Mono.CSharp {
                        return TypeBuilder;
                }
 
+               protected virtual bool CheckConstraints (EmitContext ec)
+               {
+                       return true;
+               }
+
                protected virtual bool DefineNestedTypes ()
                {
                        if (Interfaces != null) {
@@ -2629,6 +2638,30 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               if (pc.IsGeneric) {
+                                       if (pc.CountTypeParameters != member_name.CountTypeArguments) {
+                                               Report.Error (
+                                                       264, loc, "Partial declarations of `{0}' " +
+                                                       "must have the same type parameter names in " +
+                                                       "the same order", member_name.GetTypeName ());
+                                               return null;
+                                       }
+
+                                       string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
+                                       string[] names = member_name.TypeArguments.GetDeclarations ();
+
+                                       for (int i = 0; i < pc.CountTypeParameters; i++) {
+                                               if (pc_names [i] == names [i])
+                                                       continue;
+
+                                               Report.Error (
+                                                       264, loc, "Partial declarations of `{0}' " +
+                                                       "must have the same type parameter names in " +
+                                                       "the same order", member_name.GetTypeName ());
+                                               return null;
+                                       }
+                               }
+
                                return pc;
                        }
 
@@ -2636,6 +2669,8 @@ namespace Mono.CSharp {
                        RootContext.Tree.RecordDecl (full_name, pc);
                        parent.AddType (pc);
                        pc.Register ();
+                       // This is needed to define our type parameters; we define the constraints later.
+                       pc.SetParameterInfo (null);
                        return pc;
                }
 
@@ -2706,6 +2741,78 @@ namespace Mono.CSharp {
                        return PendingImplementation.GetPendingImplementations (this);
                }
 
+               ArrayList constraints_lists;
+
+               public void UpdateConstraints (ArrayList constraints_list)
+               {
+                       //
+                       // This is called for each ClassPart in a partial generic type declaration.
+                       //
+                       // If no constraints were specified for the part, just return.
+                       // Otherwise, if we're called with constraints for the first time, they become
+                       // the type's constraint.  If we're called with constraints again, we just
+                       // store them somewhere so we can later check whether there are no conflicts.
+                       //
+                       if (constraints_list == null)
+                               return;
+
+                       if (constraints_lists != null) {
+                               constraints_lists.Add (constraints_list);
+                               return;
+                       }
+
+                       DoUpdateConstraints (null, constraints_list, false);
+
+                       constraints_lists = new ArrayList ();
+               }
+
+               protected bool DoUpdateConstraints (EmitContext ec, ArrayList constraints_list, bool check)
+               {
+                       for (int i = 0; i < TypeParameters.Length; i++) {
+                               string name = TypeParameters [i].Name;
+
+                               Constraints constraints = null;
+                               if (constraints_list != null) {
+                                       foreach (Constraints constraint in constraints_list) {
+                                               if (constraint.TypeParameter == name) {
+                                                       constraints = constraint;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               if (!TypeParameters [i].UpdateConstraints (ec, constraints, check)) {
+                                       Report.Error (265, Location, "Partial declarations of `{0}' have " +
+                                                     "inconsistent constraints for type parameter `{1}'.",
+                                                     MemberName.GetTypeName (), name);
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               protected override bool CheckConstraints (EmitContext ec)
+               {
+                       if (constraints_lists == null)
+                               return true;
+
+                       //
+                       // If constraints were specified in more than one part of a
+                       // partial generic type definition, they must be identical.
+                       //
+                       // Note that we must resolve them and then compute the fully
+                       // resolved types since different parts may have different
+                       // `using' aliases.  See gen-129.cs for an example.
+
+                       foreach (ArrayList constraints_list in constraints_lists) {
+                               if (!DoUpdateConstraints (ec, constraints_list, true))
+                                       return false;
+                       }
+
+                       return true;
+               }
+
                public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
                                          Location l)
                {
@@ -2758,6 +2865,11 @@ namespace Mono.CSharp {
                                interface_type, full, name, loc);
                }
 
+               public override void SetParameterInfo (ArrayList constraints_list)
+               {
+                       PartialContainer.UpdateConstraints (constraints_list);
+               }
+
                public override MemberCache BaseCache {
                        get {
                                return PartialContainer.BaseCache;
index 06de45d524a0180030ae55d6d892c27e519b88b7..6716d185c792968d9edae0542e89170b0b7da657 100644 (file)
@@ -5030,13 +5030,14 @@ public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList def
 
 public void parse ()
 {
-       try {
+       // try {
                if (yacc_verbose_flag > 1)
                        yyparse (lexer, new yydebug.yyDebugSimple ());
                else
                        yyparse (lexer);
                Tokenizer tokenizer = lexer as Tokenizer;
-               tokenizer.cleanup ();           
+               tokenizer.cleanup ();
+#if FIXME
        } catch (Exception e){
                //
                // Removed for production use, use parser verbose to get the output.
@@ -5046,6 +5047,7 @@ public void parse ()
                if (yacc_verbose_flag > 0)
                        Console.WriteLine (e);
        }
+#endif
 }
 
 void CheckToken (int error, int yyToken, string msg)
index fccf04b5bc97e4e401187d055aa1e4c2ef566ac2..659b541db8c68fe252a32074191f36f33b9ec4d2 100644 (file)
@@ -1413,7 +1413,7 @@ namespace Mono.CSharp {
                        return type_param_list;
                }
 
-               public void SetParameterInfo (ArrayList constraints_list)
+               public virtual void SetParameterInfo (ArrayList constraints_list)
                {
                        if (!is_generic) {
                                if (constraints_list != null) {
index 512975246e8944751b251015350e1b6da9ce4326..331d295aa6078aab96ce8b969b9d7c9dc7761a64 100644 (file)
@@ -655,6 +655,38 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public bool UpdateConstraints (EmitContext ec, Constraints new_constraints, bool check)
+               {
+                       //
+                       // We're used in partial generic type definitions.
+                       // If `check' is false, we just encountered the first ClassPart which has
+                       // constraints - they become our "real" constraints.
+                       // Otherwise we're called after the type parameters have already been defined
+                       // and check whether the constraints are the same in all parts.
+                       //
+                       if (!check) {
+                               if (type != null)
+                                       throw new InvalidOperationException ();
+                               constraints = new_constraints;
+                               return true;
+                       }
+
+                       if (type == null)
+                               throw new InvalidOperationException ();
+
+                       if (constraints == null)
+                               return new_constraints == null;
+                       else if (new_constraints == null)
+                               return false;
+
+                       if (!new_constraints.Resolve (ec))
+                               return false;
+                       if (!new_constraints.ResolveTypes (ec))
+                               return false;
+
+                       return constraints.CheckInterfaceMethod (ec, new_constraints);
+               }
+
                public override string DocCommentHeader {
                        get {
                                throw new InvalidOperationException (