From f5e9161078142c136f66cdf3ff12ad7557fa5d9f Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Wed, 2 Mar 2005 16:30:29 +0000 Subject: [PATCH] 2005-03-02 Martin Baulig * 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 | 14 +++++ mcs/gmcs/class.cs | 118 +++++++++++++++++++++++++++++++++++++++-- mcs/gmcs/cs-parser.jay | 6 ++- mcs/gmcs/decl.cs | 2 +- mcs/gmcs/generic.cs | 32 +++++++++++ 5 files changed, 166 insertions(+), 6 deletions(-) diff --git a/mcs/gmcs/ChangeLog b/mcs/gmcs/ChangeLog index 9ba06911605..6c243a15cea 100644 --- a/mcs/gmcs/ChangeLog +++ b/mcs/gmcs/ChangeLog @@ -1,3 +1,17 @@ +2005-03-02 Martin Baulig + + * 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 Committing a patch from Carlos Alberto Cortez to fix #72887. diff --git a/mcs/gmcs/class.cs b/mcs/gmcs/class.cs index dfd04c89770..c1add900dd8 100644 --- a/mcs/gmcs/class.cs +++ b/mcs/gmcs/class.cs @@ -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; diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay index 06de45d524a..6716d185c79 100644 --- a/mcs/gmcs/cs-parser.jay +++ b/mcs/gmcs/cs-parser.jay @@ -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) diff --git a/mcs/gmcs/decl.cs b/mcs/gmcs/decl.cs index fccf04b5bc9..659b541db8c 100644 --- a/mcs/gmcs/decl.cs +++ b/mcs/gmcs/decl.cs @@ -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) { diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs index 512975246e8..331d295aa60 100644 --- a/mcs/gmcs/generic.cs +++ b/mcs/gmcs/generic.cs @@ -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 ( -- 2.25.1