Dynamic compound assignment breaks standard C# result conversion rules
authorMarek Safar <marek.safar@gmail.com>
Fri, 1 Oct 2010 13:20:39 +0000 (14:20 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 1 Oct 2010 13:23:59 +0000 (14:23 +0100)
mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/Binder.cs
mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpSetIndexBinder.cs
mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpSetMemberBinder.cs
mcs/mcs/assign.cs
mcs/mcs/dynamic.cs
mcs/tests/dtest-003.cs
mcs/tests/dtest-033.cs [new file with mode: 0644]
mcs/tests/ver-il-dmcs.xml

index b8ce85b4f4c932a5f656b9d2ab25aebb8eb7bd18..c8d56872c929c72109fa5f0525e302c9128d65a5 100644 (file)
@@ -80,12 +80,12 @@ namespace Microsoft.CSharp.RuntimeBinder
                
                public static CallSiteBinder SetIndex (CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
                {
-                       return new CSharpSetIndexBinder (context, argumentInfo);
+                       return new CSharpSetIndexBinder (flags, context, argumentInfo);
                }
                
                public static CallSiteBinder SetMember (CSharpBinderFlags flags, string name, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
                {
-                       return new CSharpSetMemberBinder (name, context, argumentInfo);
+                       return new CSharpSetMemberBinder (flags, name, context, argumentInfo);
                }
                
                public static CallSiteBinder UnaryOperation (CSharpBinderFlags flags, ExpressionType operation, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
index a02ef82becb9ba3c948351a63db1fda723b8f47a..2c72f1fa0b508e6d595e26ac28c3c68ce650a31c 100644 (file)
@@ -36,12 +36,14 @@ namespace Microsoft.CSharp.RuntimeBinder
 {
        class CSharpSetIndexBinder : SetIndexBinder
        {
+               readonly CSharpBinderFlags flags;
                IList<CSharpArgumentInfo> argumentInfo;
                Type callingContext;
 
-               public CSharpSetIndexBinder (Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
+               public CSharpSetIndexBinder (CSharpBinderFlags flags, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
                        : base (CSharpArgumentInfo.CreateCallInfo (argumentInfo, 2))
                {
+                       this.flags = flags;
                        this.callingContext = callingContext;
                        this.argumentInfo = argumentInfo.ToReadOnly ();
                }
@@ -61,7 +63,13 @@ namespace Microsoft.CSharp.RuntimeBinder
                        expr = new Compiler.ElementAccess (expr, args, Compiler.Location.Null);
 
                        var source = ctx.CreateCompilerExpression (argumentInfo [indexes.Length + 1], value);
-                       expr = new Compiler.SimpleAssign (expr, source);
+
+                       // Same conversion as in SetMemberBinder
+                       if ((flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0) {
+                               expr = new Compiler.RuntimeExplicitAssign (expr, source);
+                       } else {
+                               expr = new Compiler.SimpleAssign (expr, source);
+                       }
                        expr = new Compiler.Cast (new Compiler.TypeExpression (ctx.ImportType (ReturnType), Compiler.Location.Null), expr, Compiler.Location.Null);
 
                        var binder = new CSharpBinder (this, expr, errorSuggestion);
index 5add41be44699fb8bbe4e74e4e702eb5adf7c86d..52fb4dd0adafa7ba4065691e821463924008ea19 100644 (file)
@@ -36,12 +36,14 @@ namespace Microsoft.CSharp.RuntimeBinder
 {
        class CSharpSetMemberBinder : SetMemberBinder
        {
+               readonly CSharpBinderFlags flags;
                IList<CSharpArgumentInfo> argumentInfo;
                Type callingContext;
-               
-               public CSharpSetMemberBinder (string name, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
+
+               public CSharpSetMemberBinder (CSharpBinderFlags flags, string name, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
                        : base (name, false)
                {
+                       this.flags = flags;
                        this.callingContext = callingContext;
                        this.argumentInfo = argumentInfo.ToReadOnly ();
                }
@@ -54,7 +56,17 @@ namespace Microsoft.CSharp.RuntimeBinder
 
                        // Field assignment
                        expr = new Compiler.MemberAccess (expr, Name);
-                       expr = new Compiler.SimpleAssign (expr, source);
+
+                       // Compound assignment under dynamic context does not convert result
+                       // expression but when setting member type we need to do explicit
+                       // conversion to ensure type match between member type and dynamic
+                       // expression type
+                       if ((flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0) {
+                               expr = new Compiler.RuntimeExplicitAssign (expr, source);
+                       } else {
+                               expr = new Compiler.SimpleAssign (expr, source);
+                       }
+
                        expr = new Compiler.Cast (new Compiler.TypeExpression (ctx.ImportType (ReturnType), Compiler.Location.Null), expr, Compiler.Location.Null);
 
                        var binder = new CSharpBinder (this, expr, errorSuggestion);
index 049d9031c6f17bd489270af4ab1e054317f5b1d3..9967e31ea58a506b472b6088ec59fe2792b5d721 100644 (file)
@@ -399,7 +399,8 @@ namespace Mono.CSharp {
                }
        }
 
-       public class SimpleAssign : Assign {
+       public class SimpleAssign : Assign
+       {
                public SimpleAssign (Expression target, Expression source)
                        : this (target, source, target.Location)
                {
@@ -434,6 +435,23 @@ namespace Mono.CSharp {
                }
        }
 
+       public class RuntimeExplicitAssign : Assign
+       {
+               public RuntimeExplicitAssign (Expression target, Expression source)
+                       : base (target, source, target.Location)
+               {
+               }
+
+               protected override Expression ResolveConversions (ResolveContext ec)
+               {
+                       source = Convert.ExplicitConversion (ec, source, target.Type, loc);
+                       if (source != null)
+                               return this;
+
+                       return base.ResolveConversions (ec);
+               }
+       }
+
        //
        // Compiler generated assign
        //
@@ -637,30 +655,34 @@ namespace Mono.CSharp {
 
                        source = new Binary (op, left, right, true, loc);
 
-                       if (target is DynamicMemberBinder) {
-                               Arguments targs = ((DynamicMemberBinder) target).Arguments;
+                       if (target is DynamicMemberAssignable) {
+                               Arguments targs = ((DynamicMemberAssignable) target).Arguments;
                                source = source.Resolve (ec);
 
-                               Arguments args = new Arguments (2);
+                               Arguments args = new Arguments (targs.Count + 1);
                                args.AddRange (targs);
                                args.Add (new Argument (source));
-                               source = new DynamicMemberBinder (ma.Name, args, loc).ResolveLValue (ec, right);
-
-                               // Handles possible event addition/subtraction
-                               if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) {
-                                       args = new Arguments (2);
-                                       args.AddRange (targs);
-                                       args.Add (new Argument (right));
-                                       string method_prefix = op == Binary.Operator.Addition ?
-                                               Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;
-
-                                       var invoke = DynamicInvocation.CreateSpecialNameInvoke (
-                                               new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec);
-
-                                       args = new Arguments (1);
-                                       args.AddRange (targs);
-                                       source = new DynamicEventCompoundAssign (ma.Name, args,
-                                               (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec);
+                               if (target is DynamicMemberBinder) {
+                                       source = new DynamicMemberBinder (ma.Name, CSharpBinderFlags.ValueFromCompoundAssignment, args, loc).Resolve (ec);
+
+                                       // Handles possible event addition/subtraction
+                                       if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) {
+                                               args = new Arguments (2);
+                                               args.AddRange (targs);
+                                               args.Add (new Argument (right));
+                                               string method_prefix = op == Binary.Operator.Addition ?
+                                                       Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;
+
+                                               var invoke = DynamicInvocation.CreateSpecialNameInvoke (
+                                                       new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec);
+
+                                               args = new Arguments (1);
+                                               args.AddRange (targs);
+                                               source = new DynamicEventCompoundAssign (ma.Name, args,
+                                                       (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec);
+                                       }
+                               } else {
+                                       source = new DynamicIndexBinder (CSharpBinderFlags.ValueFromCompoundAssignment, args, loc).Resolve (ec);
                                }
 
                                return source;
@@ -671,6 +693,14 @@ namespace Mono.CSharp {
 
                protected override Expression ResolveConversions (ResolveContext ec)
                {
+                       //
+                       // LAMESPEC: Under dynamic context no target conversion is happening
+                       // This allows more natual dynamic behaviour but breaks compatibility
+                       // with static binding
+                       //
+                       if (target is RuntimeValueExpression)
+                               return this;
+
                        TypeSpec target_type = target.Type;
 
                        //
index 2977df9534d05cabc6f802e1e06087d224af5947..40c5742f2350852b90bbcf6ff0c884b662cdefe5 100644 (file)
@@ -561,14 +561,21 @@ namespace Mono.CSharp
                {
                }
 
+               public DynamicIndexBinder (CSharpBinderFlags flags, Arguments args, Location loc)
+                       : this (args, loc)
+               {
+                       base.flags = flags;
+               }
+
                protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet)
                {
                        Arguments binder_args = new Arguments (3);
 
-                       binder_args.Add (new Argument (new BinderFlags (0, this)));
+                       binder_args.Add (new Argument (new BinderFlags (flags, this)));
                        binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
                        binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));
 
+                       isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
                        return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args);
                }
        }
@@ -665,15 +672,22 @@ namespace Mono.CSharp
                        this.name = name;
                }
 
+               public DynamicMemberBinder (string name, CSharpBinderFlags flags, Arguments args, Location loc)
+                       : this (name, args, loc)
+               {
+                       base.flags = flags;
+               }
+
                protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet)
                {
                        Arguments binder_args = new Arguments (4);
 
-                       binder_args.Add (new Argument (new BinderFlags (0, this)));
+                       binder_args.Add (new Argument (new BinderFlags (flags, this)));
                        binder_args.Add (new Argument (new StringLiteral (name, loc)));
                        binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
                        binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));
 
+                       isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
                        return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args);
                }
        }
index 7f3f9de8bffccc73c81b5edd7bd3d84e963597e4..bcf0643b2eb0f1ab43d4a9df5a20edc870b33062 100644 (file)
@@ -66,9 +66,9 @@ class AssertDynamicObject : DynamicMetaObject
                if (mock.GetMemberOperation == null)
                        throw new ApplicationException ("Unexpected BindGetMember");
 
-               mock.GetMemberOperation (binder);
+               var r = mock.GetMemberOperation (binder);
 
-               return GetFakeMetaObject (new object ());
+               return GetFakeMetaObject (r);
        }
 
        public override DynamicMetaObject BindInvoke (InvokeBinder binder, DynamicMetaObject[] args)
@@ -140,7 +140,7 @@ class DynamicObjectMock : DynamicObject
        public Action<BinaryOperationBinder, object> BinaryOperation;
        public Func<ConvertBinder, object> ConvertOperation;
        public Action<GetIndexBinder, object[]> GetIndexOperation;
-       public Action<GetMemberBinder> GetMemberOperation;
+       public Func<GetMemberBinder, object> GetMemberOperation;
        public Action<InvokeBinder, object[]> InvokeOperation;
        public Action<InvokeMemberBinder, object[]> InvokeMemberOperation;
        public Action<SetIndexBinder, object[], object> SetIndexOperation;
@@ -738,7 +738,7 @@ class Tester : DynamicObjectMock
        {
                mock.ConvertOperation = (binder) => {
                        Assert (binder.Explicit, true, "Explicit");
-                       //                      Assert (binder.IsChecked, true, "IsChecked");
+//                     Assert (binder.IsChecked, true, "IsChecked");
                        Assert (binder.Type, typeof (byte), "Type");
                        return (byte) 2;
                };
@@ -767,7 +767,7 @@ class Tester : DynamicObjectMock
                };
 
                foreach (int v in d) {
-                       //                      Console.WriteLine (v);
+//                     Console.WriteLine (v);
                }
        }
 
@@ -826,6 +826,8 @@ class Tester : DynamicObjectMock
                        AssertArgument (binder, new[] {
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
                                "ArgumentInfo");
+
+                       return null;
                };
 
                var g = d.Foo;
@@ -860,7 +862,7 @@ class Tester : DynamicObjectMock
 
                d ();
        }
-       
+
        void Invoke_3 (dynamic d, DynamicObjectMock mock)
        {
                try {
@@ -926,10 +928,7 @@ class Tester : DynamicObjectMock
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
                                "ArgumentInfo");
 
-//                     Assert (binder.Flags, CSharpCallFlags.None, "Flags");
                        Assert (binder.IgnoreCase, false, "IgnoreCase");
-//                     Assert (binder.TypeArguments, new Type[0], "TypeArguments");
-
                        Assert ((IList<object>) args, new object[] { 'a' }, "args");
                };
 
@@ -945,10 +944,7 @@ class Tester : DynamicObjectMock
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)},
                                "ArgumentInfo");
 
-//                     Assert (binder.Flags, CSharpCallFlags.None, "Flags");
                        Assert (binder.IgnoreCase, false, "IgnoreCase");
-//                     Assert (binder.TypeArguments, new Type[0], "TypeArguments");
-
                        Assert ((IList<object>) args, new object[] { mock }, "args");
                };
 
@@ -964,10 +960,7 @@ class Tester : DynamicObjectMock
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
                                "ArgumentInfo");
 
-                       //                      Assert (binder.Flags, CSharpCallFlags.None, "Flags");
                        Assert (binder.IgnoreCase, false, "IgnoreCase");
-                       //                      Assert (binder.TypeArguments, new Type[0], "TypeArguments");
-
                        Assert ((IList<object>) args, new object[] { 9 }, "args");
                };
 
@@ -984,10 +977,7 @@ class Tester : DynamicObjectMock
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType, null)    },
                                "ArgumentInfo");
 
-//                     Assert (binder.Flags, CSharpCallFlags.None, "Flags");
                        Assert (binder.IgnoreCase, false, "IgnoreCase");
-//                     Assert (binder.TypeArguments, new Type[0], "TypeArguments");
-
                        Assert ((IList<object>) args, new object[] { 0 }, "args");
                };
 
@@ -1009,10 +999,8 @@ class Tester : DynamicObjectMock
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null),
                        }, "ArgumentInfo");
-                       //                      Assert (binder.Flags, CSharpCallFlags.SimpleNameCall, "Flags");
-                       Assert (binder.IgnoreCase, false, "IgnoreCase");
-                       //                      Assert (binder.TypeArguments, Type.EmptyTypes, "TypeArguments");
 
+                       Assert (binder.IgnoreCase, false, "IgnoreCase");
                        Assert ((IList<object>) args, new object[] { d, null }, "args");
                };
 
@@ -1026,10 +1014,8 @@ class Tester : DynamicObjectMock
                        AssertArgument (binder, new[] {
                                CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
                        }, "ArgumentInfo");
-//                     Assert (binder.Flags, CSharpCallFlags.None, "Flags");
-                       Assert (binder.IgnoreCase, false, "IgnoreCase");
-//                     Assert (binder.TypeArguments, new Type[] { typeof (object) }, "TypeArguments");
 
+                       Assert (binder.IgnoreCase, false, "IgnoreCase");
                        Assert ((IList<object>) args, new object[0], "args");
                };
 
@@ -1107,6 +1093,40 @@ class Tester : DynamicObjectMock
                d.Foo = d_const;
        }
 
+       void SetMember_2 (dynamic d, DynamicObjectMock mock)
+       {
+               mock.GetMemberOperation = (binder) => {
+                       Assert (binder.Name, "Foo", "Name");
+                       Assert (binder.IgnoreCase, false, "IgnoreCase");
+                       AssertArgument (binder, new[] {
+                               CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
+                               "ArgumentInfo");
+
+                       return mock;
+               };
+
+               mock.BinaryOperation = (binder, arg) => {
+                       Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
+                       AssertArgument (binder, new[] {
+                           CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
+                           CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
+                               "ArgumentInfo");
+
+                       Assert (arg, null, "arg");
+               };
+
+               mock.SetMemberOperation = (binder, value) => {
+                       Assert (binder.Name, "Foo", "Name");
+                       Assert (binder.IgnoreCase, false, "IgnoreCase");
+                       AssertArgument (binder, new[] {
+                               CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
+                               CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
+                       }, "ArgumentInfo");
+               };
+
+               d.Foo *= null;
+       }
+
        void UnaryPlus_1 (dynamic d, DynamicObjectMock mock)
        {
                mock.UnaryOperation = (binder) => {
diff --git a/mcs/tests/dtest-033.cs b/mcs/tests/dtest-033.cs
new file mode 100644 (file)
index 0000000..8a0f13b
--- /dev/null
@@ -0,0 +1,34 @@
+using System;
+
+public class Test
+{
+       byte Prop {
+               get { return 4; }
+               set { }
+       }
+
+       byte this [int arg] {
+               get { return 2; }
+               set { }
+       }
+
+       public static int Main ()
+       {
+               dynamic v = 'a';
+               dynamic a = new Test ();
+
+               string s = "-sdfas";
+               
+               // dynamic compound assignment with different result type
+               v += s;
+
+               if (v != "a-sdfas")
+                       return 1;
+
+               byte b = 4;
+               a.Prop *= b;
+               a[4] ^= b;
+
+               return 0;
+       }
+}
\ No newline at end of file
index 28c64c25a7e473b4df45d0ae268fa91c8f616c3d..e8524105f43116a847da45f1ba118bbcc5ea2492 100644 (file)
@@ -95,7 +95,7 @@
         <size>96</size>
       </method>
       <method name="System.Dynamic.DynamicMetaObject BindGetMember(System.Dynamic.GetMemberBinder)">
-        <size>56</size>
+        <size>53</size>
       </method>
       <method name="System.Dynamic.DynamicMetaObject BindInvoke(System.Dynamic.InvokeBinder, System.Dynamic.DynamicMetaObject[])">
         <size>96</size>
       <method name="Void &lt;GetIndex_2&gt;m__2B(System.Dynamic.GetIndexBinder, System.Object[])">
         <size>111</size>
       </method>
-      <method name="Void &lt;GetMember_1&gt;m__2D(System.Dynamic.GetMemberBinder)">
-        <size>66</size>
-      </method>
       <method name="Void &lt;Invoke_1&gt;m__2E(System.Dynamic.InvokeBinder, System.Object[])">
         <size>101</size>
       </method>
       <method name="Void &lt;SetMember_1&gt;m__3D(System.Dynamic.SetMemberBinder, System.Object)">
         <size>101</size>
       </method>
-      <method name="System.Object &lt;UnaryPlus_1&gt;m__3E(System.Dynamic.UnaryOperationBinder)">
+    </type>
+    <type name="Tester+&lt;InvokeMember_2&gt;c__AnonStorey3">
+      <method name="Void &lt;&gt;m__35(System.Dynamic.InvokeMemberBinder, System.Object[])">
+        <size>109</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;InvokeMember_6&gt;c__AnonStorey4">
+      <method name="Void &lt;&gt;m__38(System.Dynamic.InvokeMemberBinder, System.Object[])">
+        <size>119</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;SetIndex_3&gt;c__AnonStorey5">
+      <method name="Void &lt;&gt;m__3C(System.Dynamic.SetIndexBinder, System.Object[], System.Object)">
+        <size>119</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;InvokeMember_3&gt;c__DynamicSite30+Container0">
+      <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Object, Int32 ByRef)">
+        <size>0</size>
+      </method>
+      <method name="Void .ctor(Object, IntPtr)">
+        <size>0</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;InvokeMember_4&gt;c__DynamicSite31+Container0">
+      <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Object, Int32 ByRef)">
+        <size>0</size>
+      </method>
+      <method name="Void .ctor(Object, IntPtr)">
+        <size>0</size>
+      </method>
+    </type>
+    <type name="Tester">
+      <method name="Void SetMember_2(System.Object, DynamicObjectMock)">
+        <size>372</size>
+      </method>
+      <method name="System.Object &lt;GetMember_1&gt;m__2D(System.Dynamic.GetMemberBinder)">
+        <size>67</size>
+      </method>
+      <method name="Void &lt;SetMember_2&gt;m__3F(System.Dynamic.BinaryOperationBinder, System.Object)">
+        <size>68</size>
+      </method>
+      <method name="Void &lt;SetMember_2&gt;m__40(System.Dynamic.SetMemberBinder, System.Object)">
+        <size>76</size>
+      </method>
+      <method name="System.Object &lt;UnaryPlus_1&gt;m__41(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryMinus_1&gt;m__3F(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryMinus_1&gt;m__42(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryNot_1&gt;m__40(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryNot_1&gt;m__43(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryOnesComplement_1&gt;m__41(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryOnesComplement_1&gt;m__44(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryDecrement_1&gt;m__42(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryDecrement_1&gt;m__45(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryDecrement_2&gt;m__43(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryDecrement_2&gt;m__46(System.Dynamic.UnaryOperationBinder)">
         <size>51</size>
       </method>
-      <method name="System.Object &lt;UnaryIncrement_1&gt;m__44(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIncrement_1&gt;m__47(System.Dynamic.UnaryOperationBinder)">
         <size>47</size>
       </method>
-      <method name="System.Object &lt;UnaryIncrement_2&gt;m__45(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIncrement_2&gt;m__48(System.Dynamic.UnaryOperationBinder)">
         <size>51</size>
       </method>
-      <method name="System.Object &lt;UnaryIsFalse_1&gt;m__46(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIsFalse_1&gt;m__49(System.Dynamic.UnaryOperationBinder)">
         <size>52</size>
       </method>
-      <method name="Void &lt;UnaryIsFalse_1&gt;m__47(System.Dynamic.BinaryOperationBinder, System.Object)">
+      <method name="Void &lt;UnaryIsFalse_1&gt;m__4A(System.Dynamic.BinaryOperationBinder, System.Object)">
         <size>68</size>
       </method>
-      <method name="System.Object &lt;UnaryIsFalse_2&gt;m__48(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIsFalse_2&gt;m__4B(System.Dynamic.UnaryOperationBinder)">
         <size>52</size>
       </method>
-      <method name="Void &lt;UnaryIsFalse_2&gt;m__49(System.Dynamic.BinaryOperationBinder, System.Object)">
+      <method name="Void &lt;UnaryIsFalse_2&gt;m__4C(System.Dynamic.BinaryOperationBinder, System.Object)">
         <size>68</size>
       </method>
-      <method name="System.Object &lt;UnaryIsFalse_3&gt;m__4A(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIsFalse_3&gt;m__4D(System.Dynamic.UnaryOperationBinder)">
         <size>52</size>
       </method>
-      <method name="Void &lt;UnaryIsFalse_3&gt;m__4B(System.Dynamic.BinaryOperationBinder, System.Object)">
+      <method name="Void &lt;UnaryIsFalse_3&gt;m__4E(System.Dynamic.BinaryOperationBinder, System.Object)">
         <size>67</size>
       </method>
-      <method name="System.Object &lt;UnaryIsTrue_1&gt;m__4C(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIsTrue_1&gt;m__4F(System.Dynamic.UnaryOperationBinder)">
         <size>52</size>
       </method>
-      <method name="System.Object &lt;UnaryIsTrue_2&gt;m__4D(System.Dynamic.UnaryOperationBinder)">
+      <method name="System.Object &lt;UnaryIsTrue_2&gt;m__50(System.Dynamic.UnaryOperationBinder)">
         <size>52</size>
       </method>
-      <method name="Void &lt;UnaryIsTrue_2&gt;m__4E(System.Dynamic.BinaryOperationBinder, System.Object)">
+      <method name="Void &lt;UnaryIsTrue_2&gt;m__51(System.Dynamic.BinaryOperationBinder, System.Object)">
         <size>68</size>
       </method>
-      <method name="Boolean &lt;Main&gt;m__4F(System.Reflection.MethodInfo)">
+      <method name="Boolean &lt;Main&gt;m__52(System.Reflection.MethodInfo)">
         <size>12</size>
       </method>
-      <method name="System.String &lt;Main&gt;m__50(System.Reflection.MethodInfo)">
+      <method name="System.String &lt;Main&gt;m__53(System.Reflection.MethodInfo)">
         <size>7</size>
       </method>
-      <method name="Boolean &lt;Main&gt;m__51(System.Reflection.MethodInfo)">
+      <method name="Boolean &lt;Main&gt;m__54(System.Reflection.MethodInfo)">
         <size>7</size>
       </method>
-      <method name="Boolean &lt;Main&gt;m__52(Boolean)">
+      <method name="Boolean &lt;Main&gt;m__55(Boolean)">
         <size>5</size>
       </method>
     </type>
-    <type name="Tester+&lt;InvokeMember_2&gt;c__AnonStorey3">
-      <method name="Void &lt;&gt;m__35(System.Dynamic.InvokeMemberBinder, System.Object[])">
-        <size>109</size>
-      </method>
-    </type>
-    <type name="Tester+&lt;InvokeMember_6&gt;c__AnonStorey4">
-      <method name="Void &lt;&gt;m__38(System.Dynamic.InvokeMemberBinder, System.Object[])">
-        <size>119</size>
-      </method>
-    </type>
-    <type name="Tester+&lt;SetIndex_3&gt;c__AnonStorey5">
-      <method name="Void &lt;&gt;m__3C(System.Dynamic.SetIndexBinder, System.Object[], System.Object)">
-        <size>119</size>
-      </method>
-    </type>
-    <type name="Tester+&lt;InvokeMember_3&gt;c__DynamicSite30+Container0">
-      <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Object, Int32 ByRef)">
-        <size>0</size>
-      </method>
-      <method name="Void .ctor(Object, IntPtr)">
-        <size>0</size>
-      </method>
-    </type>
-    <type name="Tester+&lt;InvokeMember_4&gt;c__DynamicSite31+Container0">
-      <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Object, Int32 ByRef)">
-        <size>0</size>
+    <type name="Tester+&lt;SetMember_2&gt;c__AnonStorey6">
+      <method name="System.Object &lt;&gt;m__3E(System.Dynamic.GetMemberBinder)">
+        <size>72</size>
       </method>
-      <method name="Void .ctor(Object, IntPtr)">
-        <size>0</size>
+      <method name="Void .ctor()">
+        <size>7</size>
       </method>
     </type>
   </test>
         <size>231</size>
       </method>
       <method name="Void IsEvent()">
-        <size>2697</size>
+        <size>2673</size>
       </method>
       <method name="Void MemberGetTest()">
         <size>810</size>
         <size>36</size>
       </method>
       <method name="Void MemberSetTest()">
-        <size>2970</size>
+        <size>2964</size>
       </method>
       <method name="Void MemberSetError_Null()">
         <size>36</size>
       </method>
     </type>
   </test>
+  <test name="dtest-033.cs">
+    <type name="Test">
+      <method name="Byte get_Prop()">
+        <size>2</size>
+      </method>
+      <method name="Void set_Prop(Byte)">
+        <size>1</size>
+      </method>
+      <method name="Byte get_Item(Int32)">
+        <size>2</size>
+      </method>
+      <method name="Void set_Item(Int32, Byte)">
+        <size>1</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>804</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="dtest-collectioninit-01.cs">
     <type name="Test">
       <method name="Int32 Main()">