public override bool Resolve(BlockContext bc) { if (bc.CurrentBlock is Linq.QueryBlock) { bc.Report.Error(1995, loc, "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause"); return(false); } if (!base.Resolve(bc)) { return(false); } type = expr.Type; Arguments args = new Arguments(0); // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; awaiter_definition = bc.Module.GetAwaiter(awaiter_type); if (!awaiter_definition.IsValidPattern) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } if (!awaiter_definition.INotifyCompletion) { bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'", awaiter_type.GetSignatureForError(), bc.Module.PredefinedTypes.INotifyCompletion.GetSignatureForError()); return(false); } expr = ama; result_type = awaiter_definition.GetResult.ReturnType; return(true); }