From e582b1ecf27613a747d436b12748fc7ad80d0e7d Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 19 May 2011 17:30:14 +0100 Subject: [PATCH] New tests. --- mcs/errors/cs1986-2.cs | 18 +++++++++++++++ mcs/errors/cs1986-3.cs | 20 ++++++++++++++++ mcs/errors/cs1986.cs | 11 +++++++++ mcs/errors/cs1991.cs | 13 +++++++++++ mcs/errors/cs1999-2.cs | 19 +++++++++++++++ mcs/errors/cs1999.cs | 19 +++++++++++++++ mcs/mcs/async.cs | 52 ++++++++++++++++++++++++++++++------------ mcs/mcs/ecore.cs | 1 - mcs/mcs/expression.cs | 27 +++++++++++++++------- mcs/mcs/ikvm.cs | 3 +++ 10 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 mcs/errors/cs1986-2.cs create mode 100644 mcs/errors/cs1986-3.cs create mode 100644 mcs/errors/cs1986.cs create mode 100644 mcs/errors/cs1991.cs create mode 100644 mcs/errors/cs1999-2.cs create mode 100644 mcs/errors/cs1999.cs diff --git a/mcs/errors/cs1986-2.cs b/mcs/errors/cs1986-2.cs new file mode 100644 index 00000000000..deb3aa92dc2 --- /dev/null +++ b/mcs/errors/cs1986-2.cs @@ -0,0 +1,18 @@ +// CS1986: The `await' operand type `int' must have suitable GetAwaiter method +// Line: 15 +// Compiler options: -langversion:future + +static class S +{ + public static void GetAwaiter (this int i) + { + } +} + +class A +{ + static async void Test () + { + await 1; + } +} \ No newline at end of file diff --git a/mcs/errors/cs1986-3.cs b/mcs/errors/cs1986-3.cs new file mode 100644 index 00000000000..76beac75cda --- /dev/null +++ b/mcs/errors/cs1986-3.cs @@ -0,0 +1,20 @@ +// CS1986: The `await' operand type `A' must have suitable GetAwaiter method +// Line: 15 +// Compiler options: -langversion:future + +static class S +{ + public static void GetAwaiter (this int i) + { + } +} + +class A +{ + bool GetAwaiter; + + static async void Test () + { + await new A (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs1986.cs b/mcs/errors/cs1986.cs new file mode 100644 index 00000000000..c1f3fea94a7 --- /dev/null +++ b/mcs/errors/cs1986.cs @@ -0,0 +1,11 @@ +// CS1986: The `await' operand type `int' must have suitable GetAwaiter method +// Line: 8 +// Compiler options: -langversion:future + +class A +{ + static async void Test () + { + await 1; + } +} \ No newline at end of file diff --git a/mcs/errors/cs1991.cs b/mcs/errors/cs1991.cs new file mode 100644 index 00000000000..e493b0c936e --- /dev/null +++ b/mcs/errors/cs1991.cs @@ -0,0 +1,13 @@ +// CS1991: Cannot await `void' expression +// Line: 10 +// Compiler options: -langversion:future + +using System; + +class A +{ + static async void Test () + { + await Console.WriteLine ("await"); + } +} diff --git a/mcs/errors/cs1999-2.cs b/mcs/errors/cs1999-2.cs new file mode 100644 index 00000000000..e84d5bd0326 --- /dev/null +++ b/mcs/errors/cs1999-2.cs @@ -0,0 +1,19 @@ +// CS1999: The awaiter type `int' must have suitable IsCompleted, OnCompleted, and GetResult members +// Line: 16 +// Compiler options: -langversion:future + +static class S +{ + public static int GetAwaiter (this int i) + { + return 1; + } +} + +class A +{ + static async void Test () + { + await 9; + } +} \ No newline at end of file diff --git a/mcs/errors/cs1999.cs b/mcs/errors/cs1999.cs new file mode 100644 index 00000000000..e84d5bd0326 --- /dev/null +++ b/mcs/errors/cs1999.cs @@ -0,0 +1,19 @@ +// CS1999: The awaiter type `int' must have suitable IsCompleted, OnCompleted, and GetResult members +// Line: 16 +// Compiler options: -langversion:future + +static class S +{ + public static int GetAwaiter (this int i) + { + return 1; + } +} + +class A +{ + static async void Test () + { + await 9; + } +} \ No newline at end of file diff --git a/mcs/mcs/async.cs b/mcs/mcs/async.cs index 740401ad102..3f9081c414a 100644 --- a/mcs/mcs/async.cs +++ b/mcs/mcs/async.cs @@ -29,9 +29,12 @@ namespace Mono.CSharp protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name) { - rc.Report.Error (1986, loc, - "The `await' operand type `{0}' must have suitable GetAwaiter method", - type.GetSignatureForError ()); + Error_WrongGetAwaiter (rc, loc, type); + } + + protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + rc.Report.Error (1991, loc, "Cannot await `{0}' expression", type.GetSignatureForError ()); } } @@ -40,7 +43,7 @@ namespace Mono.CSharp MethodSpec on_completed; public Await (Expression expr, Location loc) - : base (new AwaitableMemberAccess (expr), loc) + : base (expr, loc) { } @@ -80,6 +83,13 @@ namespace Mono.CSharp mg_completed.EmitCall (ec, args); } + static void Error_WrongGetAwaiter (ResolveContext rc, Location loc, TypeSpec type) + { + rc.Report.Error (1986, loc, + "The `await' operand type `{0}' must have suitable GetAwaiter method", + type.GetSignatureForError ()); + } + void Error_WrongAwaiterPattern (ResolveContext rc, TypeSpec awaiter) { rc.Report.Error (1999, loc, "The awaiter type `{0}' must have suitable IsCompleted, OnCompleted, and GetResult members", @@ -91,25 +101,30 @@ namespace Mono.CSharp if (!base.Resolve (bc)) return false; - // - // Check whether the expression is awaitable - // - var t = expr.Type; - // // The task t is of type dynamic // - if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) throw new NotImplementedException ("dynamic await"); - var mg = expr as MethodGroupExpr; - if (mg == null) - throw new NotImplementedException ("wrong expression kind"); + // + // Check whether the expression is awaitable + // + Expression ama = new AwaitableMemberAccess (expr).Resolve (bc); + if (ama == null) + return false; Arguments args = new Arguments (0); - //expr = mg.OverloadResolve (bc, ref args, null, OverloadResolver.Restrictions.NoBaseMembers); - expr = new Invocation (expr, args).Resolve (bc); + var errors_printer = new SessionReportPrinter (); + var old = bc.Report.SetPrinter (errors_printer); + ama = new Invocation (ama, args).Resolve (bc); + + if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) { + bc.Report.SetPrinter (old); + Error_WrongGetAwaiter (bc, loc, expr.Type); + return false; + } var awaiter_type = expr.Type; awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (awaiter_type, loc); @@ -123,11 +138,18 @@ namespace Mono.CSharp if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null) { // valid } else { + bc.Report.SetPrinter (old); Error_WrongAwaiterPattern (bc, awaiter_type); return false; } } + if (errors_printer.ErrorsCount > 0) { + bc.Report.SetPrinter (old); + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + // // void OnCompleted (Action) // diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 1f12df3dbf8..c8a8f044fc0 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -2509,7 +2509,6 @@ namespace Mono.CSharp { get; } - // TODO: Not needed protected abstract TypeSpec DeclaringType { get; } diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index cdc977d083d..1d4471ee32b 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -7534,6 +7534,22 @@ namespace Mono.CSharp return e; } + protected virtual void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + if (type == InternalType.NullLiteral && rc.IsRuntimeBinder) + rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value"); + else + Unary.Error_OperatorCannotBeApplied (rc, loc, ".", type); + } + + public static bool IsValidDotExpression (TypeSpec type) + { + const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | + MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; + + return (type.Kind & dot_kinds) != 0; + } + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) { var sn = expr as SimpleName; @@ -7594,14 +7610,8 @@ namespace Mono.CSharp return new DynamicMemberBinder (Name, args, loc); } - const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | - MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; - - if ((expr_type.Kind & dot_kinds) == 0) { - if (expr_type == InternalType.NullLiteral && rc.IsRuntimeBinder) - rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value"); - else - Unary.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type); + if (!IsValidDotExpression (expr_type)) { + Error_OperatorCannotBeApplied (rc, expr_type); return null; } @@ -8306,6 +8316,7 @@ namespace Mono.CSharp } #region Properties + protected override TypeSpec DeclaringType { get { return best_candidate.DeclaringType; diff --git a/mcs/mcs/ikvm.cs b/mcs/mcs/ikvm.cs index d78744d286c..28ea7758cd9 100644 --- a/mcs/mcs/ikvm.cs +++ b/mcs/mcs/ikvm.cs @@ -356,6 +356,9 @@ namespace Mono.CSharp default_references.Add ("Microsoft.CSharp.dll"); } + if (compiler.Settings.Version == LanguageVersion.Future) + default_references.Add ("Mono.Async.dll"); + return default_references.ToArray (); } -- 2.25.1