2004-11-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / gmcs / generic.cs
index 8d5c527c384c74d6016ec9691b94e6c969403cc6..0720906b141f82ce771ef12a67b85c39e3342eff 100644 (file)
@@ -195,7 +195,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, false, loc);
+                               TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, loc);
                                if (expr == null)
                                        return false;
 
@@ -372,8 +372,8 @@ namespace Mono.CSharp {
                                Type t2 = constraints.ClassConstraint;
                                TypeExpr e2 = constraints.class_constraint;
 
-                               if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
-                                   !Convert.ImplicitReferenceConversionExists (e2, t1)) {
+                               if (!Convert.ImplicitReferenceConversionExists (ec, e1, t2) &&
+                                   !Convert.ImplicitReferenceConversionExists (ec, e2, t1)) {
                                        Report.Error (455, loc,
                                                      "Type parameter `{0}' inherits " +
                                                      "conflicting constraints `{1}' and `{2}'",
@@ -445,7 +445,7 @@ namespace Mono.CSharp {
 
                        if (HasClassConstraint != gc.HasClassConstraint)
                                return false;
-                       if (HasClassConstraint && !gc.ClassConstraint.Equals (ClassConstraint))
+                       if (HasClassConstraint && !TypeManager.IsEqual (gc.ClassConstraint, ClassConstraint))
                                return false;
 
                        int gc_icount = gc.InterfaceConstraints != null ?
@@ -459,7 +459,7 @@ namespace Mono.CSharp {
                        foreach (Type iface in gc.InterfaceConstraints) {
                                bool ok = false;
                                foreach (Type check in InterfaceConstraints) {
-                                       if (iface.Equals (check)) {
+                                       if (TypeManager.IsEqual (iface, check)) {
                                                ok = true;
                                                break;
                                        }
@@ -533,10 +533,13 @@ namespace Mono.CSharp {
                                throw new InvalidOperationException ();
 
                        this.type = type;
-                       Type[] ifaces = null;
+                       TypeManager.AddTypeParameter (type, this);
+               }
+
+               public void DefineConstraints ()
+               {
                        if (constraints != null)
                                constraints.Define (type);
-                       TypeManager.AddTypeParameter (type, this);
                }
 
                public bool DefineType (EmitContext ec)
@@ -563,17 +566,22 @@ namespace Mono.CSharp {
 
                                int pos = type.GenericParameterPosition;
                                ParameterData pd = Invocation.GetParameterData (mb);
-                               gc = pd.GenericConstraints (pos);
+                               GenericConstraints temp_gc = pd.GenericConstraints (pos);
                                Type mparam = mb.GetGenericArguments () [pos];
 
+                               if (temp_gc != null)
+                                       gc = new InflatedConstraints (temp_gc, implementing.DeclaringType);
+                               else if (constraints != null)
+                                       gc = new InflatedConstraints (constraints, implementing.DeclaringType);
+
                                bool ok = true;
                                if (constraints != null) {
-                                       if (gc == null)
+                                       if (temp_gc == null)
                                                ok = false;
                                        else if (!constraints.CheckInterfaceMethod (ec, gc))
                                                ok = false;
                                } else {
-                                       if (!is_override && (gc != null))
+                                       if (!is_override && (temp_gc != null))
                                                ok = false;
                                }
 
@@ -655,7 +663,7 @@ namespace Mono.CSharp {
                        get { return Name; }
                }
 
-               IMemberContainer IMemberContainer.ParentContainer {
+               MemberCache IMemberContainer.ParentCache {
                        get { return null; }
                }
 
@@ -714,6 +722,82 @@ namespace Mono.CSharp {
                {
                        return "TypeParameter[" + name + "]";
                }
+
+               protected class InflatedConstraints : GenericConstraints
+               {
+                       GenericConstraints gc;
+                       Type base_type;
+                       Type class_constraint;
+                       Type[] iface_constraints;
+                       Type[] dargs;
+                       Type declaring;
+
+                       public InflatedConstraints (GenericConstraints gc, Type declaring)
+                       {
+                               this.gc = gc;
+                               this.declaring = declaring;
+
+                               dargs = TypeManager.GetTypeArguments (declaring);
+
+                               ArrayList list = new ArrayList ();
+                               if (gc.HasClassConstraint)
+                                       list.Add (inflate (gc.ClassConstraint));
+                               foreach (Type iface in gc.InterfaceConstraints)
+                                       list.Add (inflate (iface));
+
+                               bool has_class_constr = false;
+                               if (list.Count > 0) {
+                                       Type first = (Type) list [0];
+                                       has_class_constr = !first.IsInterface && !first.IsGenericParameter;
+                               }
+
+                               if ((list.Count > 0) && has_class_constr) {
+                                       class_constraint = (Type) list [0];
+                                       iface_constraints = new Type [list.Count - 1];
+                                       list.CopyTo (1, iface_constraints, 0, list.Count - 1);
+                               } else {
+                                       iface_constraints = new Type [list.Count];
+                                       list.CopyTo (iface_constraints, 0);
+                               }
+
+                               if (HasValueTypeConstraint)
+                                       base_type = TypeManager.value_type;
+                               else if (class_constraint != null)
+                                       base_type = class_constraint;
+                               else
+                                       base_type = TypeManager.object_type;
+                       }
+
+                       Type inflate (Type t)
+                       {
+                               if (t == null)
+                                       return null;
+                               if (t.IsGenericParameter)
+                                       return dargs [t.GenericParameterPosition];
+                               if (t.IsGenericInstance) {
+                                       t = t.GetGenericTypeDefinition ();
+                                       t = t.BindGenericParameters (dargs);
+                               }
+
+                               return t;
+                       }
+
+                       public override GenericParameterAttributes Attributes {
+                               get { return gc.Attributes; }
+                       }
+
+                       public override Type ClassConstraint {
+                               get { return class_constraint; }
+                       }
+
+                       public override Type EffectiveBaseClass {
+                               get { return base_type; }
+                       }
+
+                       public override Type[] InterfaceConstraints {
+                               get { return iface_constraints; }
+                       }
+               }
        }
 
        //
@@ -753,6 +837,11 @@ namespace Mono.CSharp {
                        get { return false; }
                }
 
+               public override bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return true;
+               }
+
                public void Error_CannotUseAsUnmanagedType (Location loc)
                {
                        Report.Error (-203, loc, "Can not use type parameter as unamanged type");
@@ -865,8 +954,7 @@ namespace Mono.CSharp {
                        atypes = new Type [count];
 
                        for (int i = 0; i < count; i++){
-                               TypeExpr te = ds.ResolveTypeExpr (
-                                       (Expression) args [i], false, Location);
+                               TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec);
                                if (te == null) {
                                        ok = false;
                                        continue;
@@ -989,7 +1077,7 @@ namespace Mono.CSharp {
                                        return false;
                        }
 
-                       return Convert.ImplicitStandardConversionExists (expr, ctype);
+                       return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
                }
 
                protected bool CheckConstraints (EmitContext ec, int index)
@@ -1088,8 +1176,10 @@ namespace Mono.CSharp {
 
                public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
-                       if (gt != null)
+                       if (type != null)
                                return this;
+                       if (gt != null)
+                               return DoResolveType (ec);
 
                        //
                        // First, resolve the generic type.
@@ -1107,7 +1197,7 @@ namespace Mono.CSharp {
                                new_args.Add (args);
 
                                args = new_args;
-                               return this;
+                               return DoResolveType (ec);
                        }
 
                        Type t;
@@ -1115,12 +1205,8 @@ namespace Mono.CSharp {
 
                        SimpleName sn = new SimpleName (name, loc);
                        TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
-                       if ((resolved == null) || (resolved.Type == null)) {
-                               Report.Error (246, loc,
-                                             "The type or namespace name `{0}<...>' "+
-                                             "could not be found", Basename);
+                       if (resolved == null)
                                return null;
-                       }
 
                        t = resolved.Type;
                        if (t == null) {
@@ -1139,16 +1225,11 @@ namespace Mono.CSharp {
                        }
 
                        gt = t.GetGenericTypeDefinition ();
-                       return this;
+                       return DoResolveType (ec);
                }
 
-               public override Type ResolveType (EmitContext ec)
+               TypeExpr DoResolveType (EmitContext ec)
                {
-                       if (type != null)
-                               return type;
-                       if (DoResolveAsTypeStep (ec) == null)
-                               return null;
-
                        //
                        // Resolve the arguments.
                        //
@@ -1176,7 +1257,7 @@ namespace Mono.CSharp {
                        // Now bind the parameters.
                        //
                        type = gt.BindGenericParameters (atypes);
-                       return type;
+                       return this;
                }
 
                public Expression GetSimpleName (EmitContext ec)
@@ -1264,7 +1345,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public bool Define (MethodBuilder mb)
+               public bool Define (MethodBuilder mb, Type return_type)
                {
                        if (!Define ())
                                return false;
@@ -1275,6 +1356,9 @@ namespace Mono.CSharp {
                        for (int i = 0; i < TypeParameters.Length; i++)
                                TypeParameters [i].Define (gen_params [i]);
 
+                       ec = new EmitContext (
+                               this, this, Location, null, return_type, ModFlags, false);
+
                        return true;
                }
 
@@ -1336,7 +1420,11 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       type = ec.DeclSpace.ResolveType (expr, false, loc);
+                       TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
+                       if (texpr == null)
+                               return null;
+
+                       type = texpr.ResolveType (ec);
                        if (type == null)
                                return null;