manually synchronized with 56802
[mono.git] / mcs / gmcs / generic.cs
index b326cbdff75cfc8fba30eeea1e57bccd48d25989..09acdf3ea59c8a7ee650c88acc53dbd5532274a3 100644 (file)
@@ -217,7 +217,7 @@ namespace Mono.CSharp {
                                }
 
                                int errors = Report.Errors;
-                               FullNamedExpression fn = ((Expression) obj).ResolveAsTypeStep (ec);
+                               FullNamedExpression fn = ((Expression) obj).ResolveAsTypeStep (ec, false);
 
                                if (fn == null) {
                                        if (errors != Report.Errors)
@@ -235,7 +235,7 @@ namespace Mono.CSharp {
 
                                        expr = cexpr;
                                } else
-                                       expr = fn.ResolveAsTypeTerminal (ec);
+                                       expr = fn.ResolveAsTypeTerminal (ec, false);
 
                                if ((expr == null) || (expr.Type == null))
                                        return false;
@@ -1188,7 +1188,7 @@ namespace Mono.CSharp {
                        atypes = new Type [count];
 
                        for (int i = 0; i < count; i++){
-                               TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec);
+                               TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec, false);
                                if (te == null) {
                                        ok = false;
                                        continue;
@@ -1582,7 +1582,7 @@ namespace Mono.CSharp {
                                }
 
                                TypeExpr ct = new ConstructedType (ctype, new_args, loc);
-                               if (ct.ResolveAsTypeStep (ec) == null)
+                               if (ct.ResolveAsTypeStep (ec, false) == null)
                                        return false;
                                ctype = ct.Type;
                        } else if (ctype.IsGenericParameter) {
@@ -1599,6 +1599,8 @@ namespace Mono.CSharp {
 
                bool HasDefaultConstructor (EmitContext ec, Type atype)
                {
+                       atype = TypeManager.DropGenericTypeArguments (atype);
+
                        if (atype is TypeBuilder) {
                                if (atype.IsAbstract)
                                        return false;
@@ -1618,7 +1620,7 @@ namespace Mono.CSharp {
                        }
 
                        MethodGroupExpr mg = Expression.MemberLookup (
-                               ec, atype, ".ctor", MemberTypes.Constructor,
+                               ec.ContainerType, atype, ".ctor", MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance |
                                BindingFlags.DeclaredOnly, loc)
                                as MethodGroupExpr;
@@ -1786,7 +1788,7 @@ namespace Mono.CSharp {
                                if (!p.Resolve (ec))
                                        ok = false;
                        }
-                       if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec) == null))
+                       if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
                                ok = false;
 
                        return ok;
@@ -1846,7 +1848,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
+                       TypeExpr texpr = expr.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return null;
 
@@ -1899,7 +1901,7 @@ namespace Mono.CSharp {
                        args.Add (underlying);
 
                        ConstructedType ctype = new ConstructedType (TypeManager.generic_nullable_type, args, loc);
-                       return ctype.ResolveAsTypeTerminal (ec);
+                       return ctype.ResolveAsTypeTerminal (ec, false);
                }
        }
 
@@ -2059,6 +2061,23 @@ namespace Mono.CSharp {
                        return m;
                }
 
+               public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
+               {
+                       if (fi.DeclaringType.IsGenericTypeDefinition ||
+                           !fi.DeclaringType.IsGenericType)
+                               return fi;
+
+                       Type t = fi.DeclaringType.GetGenericTypeDefinition ();
+                       BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+                               BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+                       foreach (FieldInfo f in t.GetFields (bf))
+                               if (f.MetadataToken == fi.MetadataToken)
+                                       return f;
+
+                       return fi;
+               }
+
                //
                // Whether `array' is an array of T and `enumerator' is `IEnumerable<T>'.
                // For instance "string[]" -> "IEnumerable<string>".
@@ -2317,7 +2336,13 @@ namespace Mono.CSharp {
 
                static bool InferType (Type pt, Type at, Type[] infered)
                {
-                       if (pt.IsGenericParameter && (pt.DeclaringMethod != null)) {
+                       if (pt == at)
+                               return true;
+
+                       if (pt.IsGenericParameter) {
+                               if (pt.DeclaringMethod == null)
+                                       return false;
+
                                int pos = pt.GenericParameterPosition;
 
                                if (infered [pos] == null) {
@@ -2346,11 +2371,19 @@ namespace Mono.CSharp {
                        }
 
                        if (at.IsArray) {
-                               if (!pt.IsArray ||
-                                   (at.GetArrayRank () != pt.GetArrayRank ()))
-                                       return false;
+                               if (pt.IsArray) {
+                                       if (at.GetArrayRank () != pt.GetArrayRank ())
+                                               return false;
 
-                               return InferType (pt.GetElementType (), at.GetElementType (), infered);
+                                       return InferType (pt.GetElementType (), at.GetElementType (), infered);
+                               }
+
+                               if (!pt.IsGenericType ||
+                                   (pt.GetGenericTypeDefinition () != generic_ienumerable_type))
+                                   return false;
+
+                               Type[] args = GetTypeArguments (pt);
+                               return InferType (args [0], at.GetElementType (), infered);
                        }
 
                        if (pt.IsArray) {
@@ -2654,8 +2687,7 @@ namespace Mono.CSharp {
                                if (expr == null)
                                        return null;
 
-                               if (!(expr is IMemoryLocation))
-                                       temp = new LocalTemporary (ec, expr.Type);
+                               temp = new LocalTemporary (ec, expr.Type);
 
                                info = new NullableInfo (expr.Type);
                                type = info.UnderlyingType;
@@ -2675,6 +2707,11 @@ namespace Mono.CSharp {
                                ec.ig.EmitCall (OpCodes.Call, info.HasValue, null);
                        }
 
+                       public void Store (EmitContext ec)
+                       {
+                               create_temp (ec);
+                       }
+
                        void create_temp (EmitContext ec)
                        {
                                if ((temp != null) && !has_temp) {
@@ -2709,14 +2746,35 @@ namespace Mono.CSharp {
                        public void EmitAssign (EmitContext ec, Expression source,
                                                bool leave_copy, bool prepare_for_load)
                        {
-                               source.Emit (ec);
-                               ec.ig.Emit (OpCodes.Newobj, info.Constructor);
+                               InternalWrap wrap = new InternalWrap (source, info, loc);
+                               ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false);
+                       }
+
+                       protected class InternalWrap : Expression
+                       {
+                               public Expression expr;
+                               public NullableInfo info;
+
+                               public InternalWrap (Expression expr, NullableInfo info, Location loc)
+                               {
+                                       this.expr = expr;
+                                       this.info = info;
+                                       this.loc = loc;
+
+                                       type = info.Type;
+                                       eclass = ExprClass.Value;
+                               }
 
-                               if (leave_copy)
-                                       ec.ig.Emit (OpCodes.Dup);
+                               public override Expression DoResolve (EmitContext ec)
+                               {
+                                       return this;
+                               }
 
-                               Expression empty = new EmptyExpression (expr.Type);
-                               ((IAssignMethod) expr).EmitAssign (ec, empty, false, prepare_for_load);
+                               public override void Emit (EmitContext ec)
+                               {
+                                       expr.Emit (ec);
+                                       ec.ig.Emit (OpCodes.Newobj, info.Constructor);
+                               }
                        }
                }
 
@@ -2738,7 +2796,7 @@ namespace Mono.CSharp {
                                        return null;
 
                                TypeExpr target_type = new NullableType (expr.Type, loc);
-                               target_type = target_type.ResolveAsTypeTerminal (ec);
+                               target_type = target_type.ResolveAsTypeTerminal (ec, false);
                                if (target_type == null)
                                        return null;
 
@@ -2920,7 +2978,8 @@ namespace Mono.CSharp {
                {
                        public readonly Binary.Operator Oper;
 
-                       Expression left, right, underlying, null_value, bool_wrap;
+                       Expression left, right, original_left, original_right;
+                       Expression underlying, null_value, bool_wrap;
                        Unwrap left_unwrap, right_unwrap;
                        bool is_equality, is_comparision, is_boolean;
 
@@ -2928,8 +2987,8 @@ namespace Mono.CSharp {
                                                     Location loc)
                        {
                                this.Oper = op;
-                               this.left = left;
-                               this.right = right;
+                               this.left = original_left = left;
+                               this.right = original_right = right;
                                this.loc = loc;
                        }
 
@@ -2949,8 +3008,16 @@ namespace Mono.CSharp {
                                                return null;
                                }
 
-                               if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr) ||
-                                    (Oper == Binary.Operator.LogicalAnd) || (Oper == Binary.Operator.LogicalOr)) &&
+                               if ((Oper == Binary.Operator.LogicalAnd) ||
+                                   (Oper == Binary.Operator.LogicalOr)) {
+                                       Binary.Error_OperatorCannotBeApplied (
+                                               loc, Binary.OperName (Oper),
+                                               original_left.GetSignatureForError (),
+                                               original_right.GetSignatureForError ());
+                                       return null;
+                               }
+
+                               if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr)) &&
                                    ((left.Type == TypeManager.bool_type) && (right.Type == TypeManager.bool_type))) {
                                        Expression empty = new EmptyExpression (TypeManager.bool_type);
                                        bool_wrap = new Wrap (empty, loc).Resolve (ec);
@@ -3183,6 +3250,11 @@ namespace Mono.CSharp {
 
                        public override void Emit (EmitContext ec)
                        {
+                               if (left_unwrap != null)
+                                       left_unwrap.Store (ec);
+                               if (right_unwrap != null)
+                                       right_unwrap.Store (ec);
+
                                if (is_boolean) {
                                        EmitBoolean (ec);
                                        return;