Skip to content

Commit

Permalink
Fix calling await on base expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-safar committed Apr 13, 2012
1 parent f97e03f commit 989100d
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
15 changes: 11 additions & 4 deletions mcs/mcs/ecore.cs
Expand Up @@ -2772,8 +2772,14 @@ protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec meth
}
}

// TODO: For now we do it for any hoisted call even if it's needed for
// hoisted stories only but that requires a new expression wrapper
//
// When base access is used inside anonymous method/iterator/etc we need to
// get back to the context of original type. We do it by emiting proxy
// method in original class and rewriting base call to this compiler
// generated method call which does the actual base invocation. This may
// introduce redundant storey but with `this' only but it's tricky to avoid
// at this stage as we don't know what expressions follow base
//
if (rc.CurrentAnonymousMethod != null) {
if (targs == null && method.IsGeneric) {
targs = method.TypeArguments;
Expand All @@ -2787,8 +2793,9 @@ protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec meth

// Ideally this should apply to any proxy rewrite but in the case of unary mutators on
// get/set member expressions second call would fail to proxy because left expression
// would be of 'this' and not 'base'
if (rc.CurrentType.IsStruct)
// would be of 'this' and not 'base' because we share InstanceExpression for get/set
// FIXME: The async check is another hack but will probably fail with mutators
if (rc.CurrentType.IsStruct || rc.CurrentAnonymousMethod.Storey is AsyncTaskStorey)
InstanceExpression = new This (loc).Resolve (rc);
}

Expand Down
52 changes: 52 additions & 0 deletions mcs/tests/test-async-33.cs
@@ -0,0 +1,52 @@
using System;
using System.Threading;
using System.Threading.Tasks;

class A
{
public virtual Task<int> Foo (int value)
{
return Task.FromResult (value);
}

public virtual Task<int> Prop { get; set; }
}

class B : A
{
public override Task<int> Prop {
get {
throw new ApplicationException ();
}
set {
throw new ApplicationException ();
}
}

public override async Task<int> Foo (int value)
{
return await base.Foo (value) + 1;
}

public async Task<int> Foo2 (int value)
{
base.Prop = Task.FromResult (value);
return await base.Prop;
}
}

class Program
{
static int Main()
{
var b = new B ();
if (b.Foo (3).Result != 4)
return 1;

if (b.Foo2 (5).Result != 5)
return 2;

Console.WriteLine("ok");
return 0;
}
}
66 changes: 66 additions & 0 deletions mcs/tests/ver-il-net_4_5.xml
Expand Up @@ -56011,6 +56011,72 @@
</method>
</type>
</test>
<test name="test-async-33.cs">
<type name="A">
<method name="System.Threading.Tasks.Task`1[System.Int32] Foo(Int32)" attrs="454">
<size>15</size>
</method>
<method name="System.Threading.Tasks.Task`1[System.Int32] get_Prop()" attrs="2502">
<size>14</size>
</method>
<method name="Void set_Prop(System.Threading.Tasks.Task`1[System.Int32])" attrs="2502">
<size>8</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="B">
<method name="System.Threading.Tasks.Task`1[System.Int32] get_Prop()" attrs="2246">
<size>7</size>
</method>
<method name="Void set_Prop(System.Threading.Tasks.Task`1[System.Int32])" attrs="2246">
<size>7</size>
</method>
<method name="System.Threading.Tasks.Task`1[System.Int32] Foo(Int32)" attrs="198">
<size>49</size>
</method>
<method name="System.Threading.Tasks.Task`1[System.Int32] Foo2(Int32)" attrs="134">
<size>49</size>
</method>
<method name="System.Threading.Tasks.Task`1[System.Int32] &lt;Foo&gt;__BaseCallProxy0(Int32)" attrs="129">
<size>15</size>
</method>
<method name="Void &lt;set_Prop&gt;__BaseCallProxy1(System.Threading.Tasks.Task`1[System.Int32])" attrs="129">
<size>8</size>
</method>
<method name="System.Threading.Tasks.Task`1[System.Int32] &lt;get_Prop&gt;__BaseCallProxy2()" attrs="129">
<size>14</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="Program">
<method name="Int32 Main()" attrs="145">
<size>76</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="B+&lt;Foo&gt;c__async0">
<method name="Void MoveNext()" attrs="486">
<size>177</size>
</method>
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
<size>13</size>
</method>
</type>
<type name="B+&lt;Foo2&gt;c__async1">
<method name="Void MoveNext()" attrs="486">
<size>191</size>
</method>
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
<size>13</size>
</method>
</type>
</test>
<test name="test-cls-00.cs">
<type name="CLSCLass_6">
<method name="Void add_Disposed(Delegate)" attrs="2182">
Expand Down

0 comments on commit 989100d

Please sign in to comment.