[svn] r7785: nemerle/trunk/ncc: testsuite/negative/where-constraints1.n typing/StaticTyVar.n typing/Subst....

nazgul svnadmin at nemerle.org
Wed Sep 5 12:22:05 CEST 2007


Log:
Fix checking of generic constraints - bugs 1048 and 1046. Patch by BOleg.

Author: nazgul
Date: Wed Sep  5 12:22:03 2007
New Revision: 7785

Modified:
   nemerle/trunk/ncc/testsuite/negative/where-constraints1.n
   nemerle/trunk/ncc/typing/StaticTyVar.n
   nemerle/trunk/ncc/typing/Subst.n
   nemerle/trunk/ncc/typing/TyVarEnv.n

Modified: nemerle/trunk/ncc/testsuite/negative/where-constraints1.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/where-constraints1.n	(original)
+++ nemerle/trunk/ncc/testsuite/negative/where-constraints1.n	Wed Sep  5 12:22:03 2007
@@ -1,2 +1,15 @@
 class A ['a] where 'a : System.IComparable ['a], System.IComparable ['a] { // E: constraint `System.IComparable.*' is already declared for 'a
 }
\ No newline at end of file
+
+namespace Bug1048 {
+using System;
+
+class RefTypeA {}
+class RefTypeB {}
+
+struct StructType {}
+
+class Test1[T1] where T1 : Object, Int32 {} // E: generic parameter cannot be constrained by multiple non-interfaces : int, System.Object
+class Test2[T1] where T1 : Object, StructType {} // E: generic parameter cannot be constrained by multiple non-interfaces : Bug1048.StructType, System.Object
+class Test3[T1] where T1 : RefTypeA, RefTypeB {} // E: generic parameter cannot be constrained by multiple non-interfaces : Bug1048.RefTypeB, Bug1048.RefTypeA
+}

Modified: nemerle/trunk/ncc/typing/StaticTyVar.n
==============================================================================
--- nemerle/trunk/ncc/typing/StaticTyVar.n	(original)
+++ nemerle/trunk/ncc/typing/StaticTyVar.n	Wed Sep  5 12:22:03 2007
@@ -77,6 +77,9 @@
       get {
         assert (constraints != null, $"for $this");
         match (constraints) {
+          | [] when (IsValueType)=>
+            assert (InternalType.ValueType != null);
+            InternalType.ValueType
           | [] =>
             assert (InternalType.Object != null);
             InternalType.Object
@@ -156,12 +159,32 @@
     
     internal SetConstraints (special : GenericParameterAttributes, subtype : list [MType]) : void
     {
-      when ((special & GenericParameterAttributes.NotNullableValueTypeConstraint) %&&
-            (special & ~GenericParameterAttributes.NotNullableValueTypeConstraint))
-        Message.Error ("`struct' generic constraint cannot be used together with `class' or `new ()'");
+      when ((special %&& GenericParameterAttributes.NotNullableValueTypeConstraint) &&
+              (special %&& GenericParameterAttributes.ReferenceTypeConstraint))
+        Message.Error ("`struct' generic constraint cannot be used together with `class'");
 
       this.special = special;
+
+      def check_class_constraints(lst)
+      {
+        mutable c=null;
+        lst.ForAll (fun(x) {
+          | x is MType.Class when (!x.tycon.IsInterface) => 
+              if(c==null) {
+                c = x;
+                true;
+              }
+              else {
+                Message.Error ($ "generic parameter cannot be constrained by multiple non-interfaces : $(c), $(x)");
+                false
+              }
+          | _ => true
+        });
+      }
+      if (check_class_constraints(subtype))
       Constraints = subtype;
+      else
+        Constraints = [];
     }
 
     public IsValueType : bool {
@@ -242,7 +265,6 @@
       }
     }
 
-
     /// Check if [tv] fullfills [this]'s constraints.
     public CheckConstraints (tv : TyVar, thing : object) : void
     {
@@ -261,11 +283,20 @@
         | _ => false
       }
       
+      def check_constraints (t, c) {
+        ! match(t)
+        {
+          | MType.TyVarRef (s) =>
+              s.Constraints.ForAll( ctr => { ctr.IsInterface || ! c (ctr) });
+          | _ => t.IsInterface || ! c (t);
+        }
+      }
+
       def t = tv.Fix ();
       
       when (SpecialConstraints %&& 
             GenericParameterAttributes.NotNullableValueTypeConstraint &&
-            t.CanBeNull)
+            check_constraints (t, c => { c.CanBeNull }))
         // cs453
         Message.Error ($ "the type `$t' must be a value type "
                          "in order to use it as type parameter "
@@ -273,7 +304,7 @@
 
       when (SpecialConstraints %&& 
             GenericParameterAttributes.ReferenceTypeConstraint &&
-            ! t.CanBeNull)
+            check_constraints (t, c => { !c.CanBeNull }))
         // cs452
         Message.Error ($ "the type `$t' must be a reference type "
                          "in order to use it as type parameter "

Modified: nemerle/trunk/ncc/typing/Subst.n
==============================================================================
--- nemerle/trunk/ncc/typing/Subst.n	(original)
+++ nemerle/trunk/ncc/typing/Subst.n	Wed Sep  5 12:22:03 2007
@@ -212,8 +212,9 @@
           });
 
         List.Iter2 (vars, vars', fun (v : StaticTyVar, tv : TyVar) {
-          when (!v.LowerBound.Equals (tv.Manager.InternalType.Object)) {
-            def ok = tv.Require (res.Apply (v.LowerBound));
+          def lb = v.LowerBound;
+          when (!lb.Equals (tv.Manager.InternalType.Object) && !lb.Equals (tv.Manager.InternalType.ValueType)) {
+            def ok = tv.Require (res.Apply (lb));
             Util.cassert (was_error || ok, $ "req fail, $tv $(res.Apply (v.LowerBound))");
           }
         });

Modified: nemerle/trunk/ncc/typing/TyVarEnv.n
==============================================================================
--- nemerle/trunk/ncc/typing/TyVarEnv.n	(original)
+++ nemerle/trunk/ncc/typing/TyVarEnv.n	Wed Sep  5 12:22:03 2007
@@ -421,7 +421,7 @@
             
             match (c.ty) {
               | <[ @class ]> => special |= GenericParameterAttributes.ReferenceTypeConstraint;
-              | <[ @struct ]> => special |= GenericParameterAttributes.NotNullableValueTypeConstraint;
+              | <[ @struct ]> => special |= (GenericParameterAttributes.NotNullableValueTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint);
               | <[ @new ]> => special |= GenericParameterAttributes.DefaultConstructorConstraint;
               | <[ @+ ]> => special |= GenericParameterAttributes.Covariant;
               | <[ @- ]> => special |= GenericParameterAttributes.Contravariant;
@@ -510,8 +510,6 @@
 
       if (cyclicConstraints.IsEmpty)
         foreach (tv : StaticTyVar in tyParams)
-          // FIXME: check Intersection invariants and flag error
-          // to the user, otherwise we'll get an ICE
           tv.SetConstraints (get (tv.id)); 
       else
         foreach (tv : StaticTyVar in tyParams)



More information about the svn mailing list