Merge pull request #2040 from esdrubal/monoman
[mono.git] / mcs / mcs / generic.cs
index 57afe77b004f424864eaba0104e9e04d1e99a764..e63e999dc79dd325b8e42d7a1ab839be35de00fd 100644 (file)
@@ -106,7 +106,7 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
-               public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec)
+               public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments)
                {
                        throw new NotImplementedException ();
                }
@@ -195,9 +195,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (obsoleteCheck) {
-                                       ObsoleteAttribute obsolete_attr = t.GetAttributeObsolete ();
-                                       if (obsolete_attr != null)
-                                               AttributeTester.Report_ObsoleteMessage (obsolete_attr, t.GetSignatureForError (), c.Location, context.Module.Compiler.Report);
+                                       t.CheckObsoleteness (context, c.Location);
                                }
 
                                ConstraintChecker.Check (context, t, c.Location);
@@ -651,10 +649,10 @@ namespace Mono.CSharp {
                                var meta_constraints = new List<MetaType> (spec.TypeArguments.Length);
                                foreach (var c in spec.TypeArguments) {
                                        //
-                                       // Inflated type parameters can collide with special constraint types, don't
+                                       // Inflated type parameters can collide with base type constraint, don't
                                        // emit any such type parameter.
                                        //
-                                       if (c.BuiltinType == BuiltinTypeSpec.Type.Object || c.BuiltinType == BuiltinTypeSpec.Type.ValueType)
+                                       if (c.IsClass && spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object)
                                                continue;
 
                                        meta_constraints.Add (c.GetMetaInfo ());
@@ -1052,7 +1050,8 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               types [i] = ((TypeParameterSpec)t).GetEffectiveBase ();
+                               var tps = t as TypeParameterSpec;
+                               types [i] = tps != null ? tps.GetEffectiveBase () : t;
                        }
 
                        if (HasTypeConstraint)
@@ -1061,8 +1060,11 @@ namespace Mono.CSharp {
                        return effective_base = Convert.FindMostEncompassedType (types);
                }
 
-               public override string GetSignatureForDocumentation ()
+               public override string GetSignatureForDocumentation (bool explicitName)
                {
+                       if (explicitName)
+                               return Name;
+
                        var prefix = IsMethodOwned ? "``" : "`";
                        return prefix + DeclaredPosition;
                }
@@ -1110,14 +1112,20 @@ namespace Mono.CSharp {
                        //
                        bool found;
                        if (!TypeSpecComparer.Override.IsEqual (BaseType, other.BaseType)) {
-                               if (other.targs == null)
-                                       return false;
-
                                found = false;
-                               foreach (var otarg in other.targs) {
-                                       if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) {
-                                               found = true;
-                                               break;
+                               if (other.targs != null) {
+                                       foreach (var otarg in other.targs) {
+                                               if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) {
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                               } else if (targs != null) {
+                                       foreach (var targ in targs) {
+                                               if (TypeSpecComparer.Override.IsEqual (targ, other.BaseType)) {
+                                                       found = true;
+                                                       break;
+                                               }
                                        }
                                }
 
@@ -1146,7 +1154,7 @@ namespace Mono.CSharp {
 
                                        if (other.targs != null) {
                                                foreach (var otarg in other.targs) {
-                                                       if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) {
+                                                       if (TypeSpecComparer.Override.IsEqual (iface, otarg)) {
                                                                found = true;
                                                                break;
                                                        }
@@ -1160,18 +1168,25 @@ namespace Mono.CSharp {
 
                        // Check interfaces implementation <- definition
                        if (other.InterfacesDefined != null) {
-                               if (InterfacesDefined == null)
-                                       return false;
-
                                //
                                // Iterate over inflated interfaces
                                //
                                foreach (var oiface in other.Interfaces) {
                                        found = false;
-                                       foreach (var iface in Interfaces) {
-                                               if (TypeSpecComparer.Override.IsEqual (iface, oiface)) {
-                                                       found = true;
-                                                       break;
+
+                                       if (InterfacesDefined != null) {
+                                               foreach (var iface in Interfaces) {
+                                                       if (TypeSpecComparer.Override.IsEqual (iface, oiface)) {
+                                                               found = true;
+                                                               break;
+                                                       }
+                                               }
+                                       } else if (targs != null) {
+                                               foreach (var targ in targs) {
+                                                       if (TypeSpecComparer.Override.IsEqual (targ, oiface)) {
+                                                               found = true;
+                                                               break;
+                                                       }
                                                }
                                        }
 
@@ -1182,18 +1197,30 @@ namespace Mono.CSharp {
 
                        // Check type parameters implementation -> definition
                        if (targs != null) {
-                               if (other.targs == null)
-                                       return false;
-
                                foreach (var targ in targs) {
                                        found = false;
-                                       foreach (var otarg in other.targs) {
-                                               if (TypeSpecComparer.Override.IsEqual (targ, otarg)) {
-                                                       found = true;
-                                                       break;
+
+                                       if (other.targs != null) {
+                                               foreach (var otarg in other.targs) {
+                                                       if (TypeSpecComparer.Override.IsEqual (targ, otarg)) {
+                                                               found = true;
+                                                               break;
+                                                       }
                                                }
                                        }
 
+                                       if (other.InterfacesDefined != null && !found) {
+                                               foreach (var iface in other.Interfaces) {
+                                                       if (TypeSpecComparer.Override.IsEqual (iface, targ)) {
+                                                               found = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       if (!found)
+                                               found = TypeSpecComparer.Override.IsEqual (targ, other.BaseType);
+
                                        if (!found)
                                                return false;
                                }
@@ -1307,12 +1334,26 @@ namespace Mono.CSharp {
                {
                        cache = new MemberCache ();
 
+                       if (targs != null) {
+                               foreach (var ta in targs) {
+                                       var tps = ta as TypeParameterSpec;
+                                       var b_type = tps == null ? ta : tps.GetEffectiveBase ();
+
+                                       //
+                                       // Find the most specific type when base type was inflated from base constraints
+                                       //
+                                       if (b_type != null && !b_type.IsStructOrEnum && TypeSpec.IsBaseClass (b_type, BaseType, false))
+                                               BaseType = b_type;
+                               }
+                       }
+
                        //
                        // For a type parameter the membercache is the union of the sets of members of the types
                        // specified as a primary constraint or secondary constraint
                        //
-                       if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType)
+                       if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) {
                                cache.AddBaseType (BaseType);
+                       }
 
                        if (InterfacesDefined != null) {
                                foreach (var iface_type in InterfacesDefined) {
@@ -1320,19 +1361,13 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       //
+                       // Import interfaces after base type to match behavior from ordinary classes
+                       //
                        if (targs != null) {
                                foreach (var ta in targs) {
                                        var tps = ta as TypeParameterSpec;
-                                       IList<TypeSpec> ifaces;
-                                       if (tps != null) {
-                                               var b_type = tps.GetEffectiveBase ();
-                                               if (b_type != null && b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType)
-                                                       cache.AddBaseType (b_type);
-
-                                               ifaces = tps.InterfacesDefined;
-                                       } else {
-                                               ifaces = ta.Interfaces;
-                                       }
+                                       var ifaces = tps == null ? ta.Interfaces : tps.InterfacesDefined;
 
                                        if (ifaces != null) {
                                                foreach (var iface_type in ifaces) {
@@ -1478,6 +1513,9 @@ namespace Mono.CSharp {
                                        if (ac != null)
                                                return ArrayContainer.MakeType (context.Module, et, ac.Rank);
 
+                                       if (ec is PointerContainer)
+                                               return PointerContainer.MakeType (context.Module, et);
+
                                        throw new NotImplementedException ();
                                }
 
@@ -1902,6 +1940,14 @@ namespace Mono.CSharp {
                        return definition.GetMetaInfo ().MakeGenericType (all.ToArray ());
                }
 
+               public override void CheckObsoleteness (IMemberContext mc, Location loc)
+               {
+                       base.CheckObsoleteness (mc, loc);
+
+                       foreach (var ta in TypeArguments)
+                               ta.CheckObsoleteness (mc, loc);
+               }
+
                public override ObsoleteAttribute GetAttributeObsolete ()
                {
                        return open_type.GetAttributeObsolete ();
@@ -2176,7 +2222,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Resolve the type arguments.
                /// </summary>
-               public virtual bool Resolve (IMemberContext ec)
+               public virtual bool Resolve (IMemberContext ec, bool allowUnbound)
                {
                        if (atypes != null)
                            return true;
@@ -2229,9 +2275,12 @@ namespace Mono.CSharp {
 
        public class UnboundTypeArguments : TypeArguments
        {
-               public UnboundTypeArguments (int arity)
+               Location loc;
+
+               public UnboundTypeArguments (int arity, Location loc)
                        : base (new FullNamedExpression[arity])
                {
+                       this.loc = loc;
                }
 
                public override bool IsEmpty {
@@ -2240,8 +2289,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override bool Resolve (IMemberContext ec)
+               public override bool Resolve (IMemberContext mc, bool allowUnbound)
                {
+                       if (!allowUnbound) {
+                               mc.Module.Compiler.Report.Error (7003, loc, "Unbound generic name is not valid in this context");
+                       }
+
                        // Nothing to be resolved
                        return true;
                }
@@ -2422,12 +2475,12 @@ namespace Mono.CSharp {
                        return type.GetSignatureForError ();
                }
 
-               public override TypeSpec ResolveAsType (IMemberContext mc)
+               public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
                {
                        if (eclass != ExprClass.Unresolved)
                                return type;
 
-                       if (!args.Resolve (mc))
+                       if (!args.Resolve (mc, allowUnboundTypeArguments))
                                return null;
 
                        TypeSpec[] atypes = args.Arguments;
@@ -2545,6 +2598,9 @@ namespace Mono.CSharp {
                //
                public bool CheckAll (MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc)
                {
+                       if (targs == null)
+                               return true;
+
                        for (int i = 0; i < tparams.Length; i++) {
                                var targ = targs[i];
                                if (!CheckConstraint (context, targ, tparams [i], loc))
@@ -2754,7 +2810,7 @@ namespace Mono.CSharp {
                //
                // Tracks successful rate of type inference
                //
-               int score = int.MaxValue;
+               int score;
                readonly Arguments arguments;
                readonly int arg_count;
 
@@ -2827,12 +2883,12 @@ namespace Mono.CSharp {
                                AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
                                if (am != null) {
                                        if (am.ExplicitTypeInference (tic, method_parameter))
-                                               --score; 
+                                               ++score; 
                                        continue;
                                }
 
                                if (a.IsByRef) {
-                                       score -= tic.ExactInference (a.Type, method_parameter);
+                                       score += tic.ExactInference (a.Type, method_parameter);
                                        continue;
                                }
 
@@ -2840,14 +2896,14 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (TypeSpec.IsValueType (method_parameter)) {
-                                       score -= tic.LowerBoundInference (a.Type, method_parameter);
+                                       score += tic.LowerBoundInference (a.Type, method_parameter);
                                        continue;
                                }
 
                                //
                                // Otherwise an output type inference is made
                                //
-                               score -= tic.OutputTypeInference (ec, a.Expr, method_parameter);
+                               score += tic.OutputTypeInference (ec, a.Expr, method_parameter);
                        }
 
                        //
@@ -2897,7 +2953,7 @@ namespace Mono.CSharp {
                                        if (arguments[i] == null)
                                                continue;
 
-                                       score -= tic.OutputTypeInference (ec, arguments[i].Expr, t_i);
+                                       score += tic.OutputTypeInference (ec, arguments[i].Expr, t_i);
                                }
                        }
 
@@ -3004,7 +3060,7 @@ namespace Mono.CSharp {
                        // Some types cannot be used as type arguments
                        //
                        if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
-                               bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod)
+                               bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType)
                                return;
 
                        var a = bounds [index];
@@ -3030,8 +3086,8 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (TypeManager.IsGenericType (t))
-                                       return AllTypesAreFixed (TypeManager.GetTypeArguments (t));
+                               if (t.IsGeneric && !AllTypesAreFixed (t.TypeArguments))
+                                       return false;
                        }
                        
                        return true;
@@ -3199,7 +3255,7 @@ namespace Mono.CSharp {
                                                        continue;
 
                                                if (!applicable[cii])
-                                                       break;
+                                                       continue;
 
                                                //
                                                // For each exact bound U of Xi all types Uj which are not identical
@@ -3216,7 +3272,7 @@ namespace Mono.CSharp {
                                                        continue;
 
                                                if (!applicable[cii])
-                                                       break;
+                                                       continue;
 
                                                //
                                                // For each lower bound U of Xi all types Uj to which there is not an implicit conversion
@@ -3235,7 +3291,7 @@ namespace Mono.CSharp {
                                                        continue;
 
                                                if (!applicable[cii])
-                                                       break;
+                                                       continue;
 
                                                //
                                                // For each upper bound U of Xi all types Uj from which there is not an implicit conversion