Comment.
[mono.git] / mcs / mcs / generic.cs
index e45400f703f1f9818ae41a75eb08063c4ed96be8..11a913a4f6d0362f46cfce7fe0415e7b3411d4e7 100644 (file)
@@ -401,7 +401,12 @@ namespace Mono.CSharp {
                        if (constraints != null)
                                return spec.HasSameConstraintsDefinition (tp.Type);
 
-                       constraints = new_constraints;
+                       // Copy constraint from resolved part to partial container
+                       spec.SpecialConstraint = tp.spec.SpecialConstraint;
+                       spec.InterfacesDefined = tp.spec.InterfacesDefined;
+                       spec.TypeArguments = tp.spec.TypeArguments;
+                       spec.BaseType = tp.spec.BaseType;
+                       
                        return true;
                }
 
@@ -943,9 +948,9 @@ namespace Mono.CSharp {
                        var tps = (TypeParameterSpec) MemberwiseClone ();
                        tps.BaseType = inflator.Inflate (BaseType);
                        if (ifaces != null) {
-                               tps.ifaces = new TypeSpec[ifaces.Count];
+                               tps.ifaces = new List<TypeSpec> (ifaces.Count);
                                for (int i = 0; i < ifaces.Count; ++i)
-                                       tps.ifaces[i] = inflator.Inflate (ifaces[i]);
+                                       tps.ifaces.Add (inflator.Inflate (ifaces[i]));
                        }
                        if (targs != null) {
                                tps.targs = new TypeSpec[targs.Length];
@@ -971,6 +976,25 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsConvertibleToInterface (TypeSpec iface)
+               {
+                       if (Interfaces != null) {
+                               foreach (var t in Interfaces) {
+                                       if (t == iface)
+                                               return true;
+                               }
+                       }
+
+                       if (TypeArguments != null) {
+                               foreach (var t in TypeArguments) {
+                                       if (((TypeParameterSpec) t).IsConvertibleToInterface (iface))
+                                               return true;
+                               }
+                       }
+
+                       return false;
+               }
+
                public override TypeSpec Mutate (TypeParameterMutator mutator)
                {
                        return mutator.Mutate (this);
@@ -1066,7 +1090,7 @@ namespace Mono.CSharp {
                        }
 
                        // Inflate generic type
-                       if (ts.IsGeneric)
+                       if (ts.Arity > 0)
                                return InflateTypeParameters (ts);
 
                        return ts;
@@ -1078,7 +1102,7 @@ namespace Mono.CSharp {
                                if (tparams [i] == tp)
                                        return targs[i];
 
-                       // CECIL: This can happen when inflating nested types
+                       // This can happen when inflating nested types
                        // without type arguments specified
                        return tp;
                }
@@ -1976,14 +2000,21 @@ namespace Mono.CSharp {
                        for (int i = 0; i < names.Length; i++) {
                                string type_argument_name = names[i].Name;
                                int idx = parameters.GetParameterIndexByName (type_argument_name);
+
                                if (idx >= 0) {
-                                       Block b = m.Block;
+                                       var b = m.Block;
                                        if (b == null)
-                                               b = new Block (null);
+                                               b = new ToplevelBlock (Compiler, Location);
 
-                                       b.Error_AlreadyDeclaredTypeParameter (Report, parameters [i].Location,
+                                       b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
                                                type_argument_name, "method parameter");
                                }
+
+                               if (m.Block != null) {
+                                       var ikv = m.Block.GetKnownVariable (type_argument_name);
+                                       if (ikv != null)
+                                               ikv.Block.Error_AlreadyDeclaredTypeParameter (ikv.Location, type_argument_name, "local variable");
+                               }
                                
                                snames[i] = type_argument_name;
                        }
@@ -2598,26 +2629,31 @@ namespace Mono.CSharp {
                }
                
                //
-               // Uses inferred types to inflate delegate type argument
+               // Uses inferred or partially infered types to inflate delegate type argument. Returns
+               // null when type parameter was not yet inferres
                //
                public TypeSpec InflateGenericArgument (TypeSpec parameter)
                {
                        var tp = parameter as TypeParameterSpec;
                        if (tp != null) {
                                //
-                               // Inflate method generic argument (MVAR) only
+                               // Type inference work on generic arguments (MVAR) only
                                //
                                if (!tp.IsMethodOwned)
                                        return parameter;
 
-                               return fixed_types [tp.DeclaredPosition];
+                               return fixed_types [tp.DeclaredPosition] ?? parameter;
                        }
 
                        var gt = parameter as InflatedTypeSpec;
                        if (gt != null) {
                                var inflated_targs = new TypeSpec [gt.TypeArguments.Length];
                                for (int ii = 0; ii < inflated_targs.Length; ++ii) {
-                                       inflated_targs[ii] = InflateGenericArgument (gt.TypeArguments [ii]);
+                                       var inflated = InflateGenericArgument (gt.TypeArguments [ii]);
+                                       if (inflated == null)
+                                               return null;
+
+                                       inflated_targs[ii] = inflated;
                                }
 
                                return gt.GetDefinition ().MakeGenericType (inflated_targs);
@@ -2822,25 +2858,39 @@ namespace Mono.CSharp {
                        // then a lower-bound inference is made from U for Tb.
                        //
                        if (e is MethodGroupExpr) {
-                               // TODO: Or expression tree
-                               if (!TypeManager.IsDelegateType (t))
-                                       return 0;
+                               if (!TypeManager.IsDelegateType (t)) {
+                                       if (TypeManager.expression_type == null || t.MemberDefinition != TypeManager.expression_type.MemberDefinition)
+                                               return 0;
+
+                                       t = TypeManager.GetTypeArguments (t)[0];
+                               }
 
                                var invoke = Delegate.GetInvokeMethod (ec.Compiler, t);
                                TypeSpec rtype = invoke.ReturnType;
 
-                               if (!TypeManager.IsGenericType (rtype))
+                               if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype))
                                        return 0;
 
+                               // LAMESPEC: Standard does not specify that all methodgroup arguments
+                               // has to be fixed but it does not specify how to do recursive type inference
+                               // either. We choose the simple option and infer return type only
+                               // if all delegate generic arguments are fixed.
+                               TypeSpec[] param_types = new TypeSpec [invoke.Parameters.Count];
+                               for (int i = 0; i < param_types.Length; ++i) {
+                                       var inflated = InflateGenericArgument (invoke.Parameters.Types[i]);
+                                       if (inflated == null)
+                                               return 0;
+
+                                       param_types[i] = inflated;
+                               }
+
                                MethodGroupExpr mg = (MethodGroupExpr) e;
-                               Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, e.Location);
+                               Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, param_types, e.Location);
                                mg = mg.OverloadResolve (ec, ref args, true, e.Location);
                                if (mg == null)
                                        return 0;
 
-                               // TODO: What should happen when return type is of generic type ?
-                               throw new NotImplementedException ();
-//                             return LowerBoundInference (null, rtype) + 1;
+                               return LowerBoundInference (mg.BestCandidate.ReturnType, rtype) + 1;
                        }
 
                        //