Don't emit reaonly. prefix for reference loads
[mono.git] / mcs / mcs / async.cs
index 2f30d716b7bbf564968d562d36734814aac34074..1a1345013feae0411909a85e91649806d277b44f 100644 (file)
@@ -22,7 +22,7 @@ namespace Mono.CSharp
 {
        class Await : ExpressionStatement
        {
-               readonly Expression expr;
+               Expression expr;
                AwaitStatement stmt;
 
                public Await (Expression expr, Location loc)
@@ -31,6 +31,13 @@ namespace Mono.CSharp
                        this.loc = loc;
                }
 
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       var t = (Await) target;
+
+                       t.expr = expr.Clone (clonectx);
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        throw new NotImplementedException ("ET");
@@ -72,7 +79,8 @@ namespace Mono.CSharp
                        }
 
                        stmt = new AwaitStatement (expr, loc);
-                       stmt.Resolve (bc);
+                       if (!stmt.Resolve (bc))
+                               return null;
 
                        type = stmt.ResultType;
                        eclass = ExprClass.Variable;
@@ -81,6 +89,14 @@ namespace Mono.CSharp
 
                public override void Emit (EmitContext ec)
                {
+                       stmt.EmitPrologue (ec);
+                       stmt.Emit (ec);
+               }
+
+               public void EmitAssign (EmitContext ec, FieldExpr field)
+               {
+                       stmt.EmitPrologue (ec);
+                       field.InstanceExpression.Emit (ec);
                        stmt.Emit (ec);
                }
 
@@ -142,6 +158,20 @@ namespace Mono.CSharp
                        var fe_awaiter = new FieldExpr (awaiter, loc);
                        fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
 
+                       //
+                       // result = awaiter.GetResult ();
+                       //
+                       var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
+                       mg_result.InstanceExpression = fe_awaiter;
+
+                       mg_result.EmitCall (ec, new Arguments (0));
+               }
+
+               public void EmitPrologue (EmitContext ec)
+               {
+                       var fe_awaiter = new FieldExpr (awaiter, loc);
+                       fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
+
                        //
                        // awaiter = expr.GetAwaiter ();
                        //
@@ -166,18 +196,11 @@ namespace Mono.CSharp
                        mg_completed.EmitCall (ec, args);
 
                        base.DoEmit (ec);
-
-                       //
-                       // result = awaiter.GetResult ();
-                       //
-                       var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc);
-                       mg_result.InstanceExpression = fe_awaiter;
-
-                       mg_result.EmitCall (ec, new Arguments (0));
                }
 
                public void EmitStatement (EmitContext ec)
                {
+                       EmitPrologue (ec);
                        Emit (ec);
 
                        if (ResultType.Kind != MemberKind.Void) {
@@ -295,11 +318,15 @@ namespace Mono.CSharp
 
        public class AsyncInitializer : StateMachineInitializer
        {
+               TypeInferenceContext return_inference;
+
                public AsyncInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType)
                        : base (block, host, returnType)
                {
                }
 
+               #region Properties
+
                public override string ContainerType {
                        get {
                                return "async state machine block";
@@ -312,11 +339,25 @@ namespace Mono.CSharp
                        }
                }
 
+               public Block OriginalBlock {
+                       get {
+                               return block.Parent;
+                       }
+               }
+
+               public TypeInferenceContext ReturnTypeInference {
+                       get {
+                               return return_inference;
+                       }
+               }
+
+               #endregion
+
                public static void Create (ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc)
                {
-                       if (returnType.Kind != MemberKind.Void &&
+                       if (returnType != null && returnType.Kind != MemberKind.Void &&
                                returnType != host.Module.PredefinedTypes.Task.TypeSpec &&
-                               returnType.MemberDefinition != host.Module.PredefinedTypes.TaskGeneric.TypeSpec.MemberDefinition) {
+                               !returnType.IsGenericTask) {
                                host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task<T>");
                        }
 
@@ -351,6 +392,16 @@ namespace Mono.CSharp
                        block.WrapIntoAsyncTask (host, returnType);
                }
 
+               protected override BlockContext CreateBlockContext (ResolveContext rc)
+               {
+                       var ctx = base.CreateBlockContext (rc);
+                       var lambda = rc.CurrentAnonymousMethod as LambdaMethod;
+                       if (lambda != null)
+                               return_inference = lambda.ReturnTypeInference;
+
+                       return ctx;
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        return base.CreateExpressionTree (ec);
@@ -363,8 +414,6 @@ namespace Mono.CSharp
 
                protected override void EmitMoveNextEpilogue (EmitContext ec)
                {
-                       base.EmitMoveNextEpilogue (ec);
-
                        var storey = (AsyncTaskStorey) Storey;
                        storey.EmitSetResult (ec);
                }
@@ -408,7 +457,7 @@ namespace Mono.CSharp
                LocalVariable hoisted_return;
 
                public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type)
-                       : base (initializer.Block, initializer.Host, null, null, "async")
+                       : base (initializer.OriginalBlock, initializer.Host, null, null, "async")
                {
                        return_type = type;
                }