|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
using Basic.Reference.Assemblies;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public class BindingAwaitTests : CompilingTestBase
{
[WorkItem(547172, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547172")]
[Fact, WorkItem(531516, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531516")]
public void Bug18241()
{
var tree = SyntaxFactory.ParseSyntaxTree(" class C { void M() { await X() on ");
SourceText text = tree.GetText();
TextSpan span = new TextSpan(text.Length, 0);
TextChange change = new TextChange(span, "/*comment*/");
SourceText newText = text.WithChanges(change);
// This line caused an assertion and then crashed in the parser.
var newTree = tree.WithChangedText(newText);
}
[Fact]
public void AwaitBadExpression()
{
var source = @"
static class Program
{
static void Main() { }
static async void f()
{
await goo;
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (8,15): error CS0103: The name 'goo' does not exist in the current context
// await goo;
Diagnostic(ErrorCode.ERR_NameNotInContext, "goo").WithArguments("goo"));
}
[Fact]
public void MissingGetAwaiterInstanceMethod()
{
var source = @"
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (8,9): error CS1061: 'A' does not contain a definition for 'GetAwaiter' and no extension method 'GetAwaiter' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?)
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "await new A()").WithArguments("A", "GetAwaiter")
);
}
[Fact]
public void InaccessibleGetAwaiterInstanceMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
await new C();
await new D();
}
}
class A
{
Awaiter GetAwaiter() { return new Awaiter(); }
}
class B
{
private Awaiter GetAwaiter() { return new Awaiter(); }
}
class C
{
protected Awaiter GetAwaiter() { return new Awaiter(); }
}
class D
{
public Awaiter GetAwaiter() { return new Awaiter(); }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0122: 'A.GetAwaiter()' is inaccessible due to its protection level
// await new A();
Diagnostic(ErrorCode.ERR_BadAccess, "await new A()").WithArguments("A.GetAwaiter()"),
// (11,9): error CS0122: 'B.GetAwaiter()' is inaccessible due to its protection level
// await new B();
Diagnostic(ErrorCode.ERR_BadAccess, "await new B()").WithArguments("B.GetAwaiter()"),
// (12,9): error CS0122: 'C.GetAwaiter()' is inaccessible due to its protection level
// await new C();
Diagnostic(ErrorCode.ERR_BadAccess, "await new C()").WithArguments("C.GetAwaiter()")
);
}
[Fact]
public void StaticGetAwaiterMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
}
}
class A
{
public Awaiter GetAwaiter() { return new Awaiter(); }
}
class B
{
public static Awaiter GetAwaiter() { return new Awaiter(); }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (11,9): error CS1986: 'await' requires that the type B have a suitable GetAwaiter method
// await new B();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new B()").WithArguments("B")
);
}
[Fact]
public void GetAwaiterFieldOrProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B(null);
}
}
class A
{
Awaiter GetAwaiter { get { return new Awaiter(); } }
}
class B
{
public Awaiter GetAwaiter;
public B(Awaiter getAwaiter)
{
this.GetAwaiter = getAwaiter;
}
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS1955: Non-invocable member 'A.GetAwaiter' cannot be used like a method.
// await new A();
Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "await new A()").WithArguments("A.GetAwaiter"),
// (11,9): error CS1955: Non-invocable member 'B.GetAwaiter' cannot be used like a method.
// await new B(null);
Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "await new B(null)").WithArguments("B.GetAwaiter")
);
}
[Fact]
public void GetAwaiterParams()
{
var source = @"
using System;
public class A
{
public Awaiter GetAwaiter(params object[] xs) { throw new Exception(); }
}
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (22,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void VoidReturningGetAwaiterMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public void GetAwaiter() { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void InaccessibleGetAwaiterExtensionMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
await new C();
}
}
class A { }
class B { }
class C { }
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
static Awaiter GetAwaiter(this A a)
{
return new Awaiter();
}
private static Awaiter GetAwaiter(this B a)
{
return new Awaiter();
}
public static Awaiter GetAwaiter(this C a)
{
return new Awaiter();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,15): error CS1929: 'A' does not contain a definition for 'GetAwaiter' and the best extension method overload 'MyExtensions.GetAwaiter(C)' requires a receiver of type 'C'
// await new A();
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "new A()").WithArguments("A", "GetAwaiter", "MyExtensions.GetAwaiter(C)", "C"),
// (11,15): error CS1929: 'B' does not contain a definition for 'GetAwaiter' and the best extension method overload 'MyExtensions.GetAwaiter(C)' requires a receiver of type 'C'
// await new B();
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "new B()").WithArguments("B", "GetAwaiter", "MyExtensions.GetAwaiter(C)", "C")
);
}
[Fact]
public void GetAwaiterExtensionMethodLookup()
{
var source = @"
using System;
class A { }
class B { }
class C { }
static class Test
{
static async void F()
{
new A().GetAwaiter();
new B().GetAwaiter();
new C().GetAwaiter();
await new A();
await new B();
await new C();
}
static Awaiter GetAwaiter(this A a) { throw new Exception(); }
static void GetAwaiter(this B a) { throw new Exception(); }
}
static class E
{
public static void GetAwaiter(this A a) { throw new Exception(); }
public static Awaiter GetAwaiter(this B a) { throw new Exception(); }
public static Awaiter GetAwaiter(this C a) { throw new Exception(); }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (14,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(A)' and 'E.GetAwaiter(A)'
// new A().GetAwaiter();
Diagnostic(ErrorCode.ERR_AmbigCall, "GetAwaiter").WithArguments("Test.GetAwaiter(A)", "E.GetAwaiter(A)"),
// (15,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(B)' and 'E.GetAwaiter(B)'
// new B().GetAwaiter();
Diagnostic(ErrorCode.ERR_AmbigCall, "GetAwaiter").WithArguments("Test.GetAwaiter(B)", "E.GetAwaiter(B)"),
// (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(A)' and 'E.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("Test.GetAwaiter(A)", "E.GetAwaiter(A)"),
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(B)' and 'E.GetAwaiter(B)'
// await new B();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new B()").WithArguments("Test.GetAwaiter(B)", "E.GetAwaiter(B)")
);
}
[Fact]
public void ExtensionDuellingLookup()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class E
{
public static Awaiter GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this I2 a) { throw new Exception(); }
}
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
public static void GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this I2 a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (31,9): error CS0121: The call is ambiguous between the following methods or properties: 'E.GetAwaiter(I1)' and 'E.GetAwaiter(I2)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("E.GetAwaiter(I1)", "E.GetAwaiter(I2)")
);
}
[Fact]
public void ExtensionDuellingMoreDerivedMoreOptional()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
public static Awaiter GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this A a, object o = null) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (19,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionDuellingLessDerivedLessOptional()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
public static void GetAwaiter(this A a, object o = null) { throw new Exception(); }
public static Awaiter GetAwaiter(this I1 a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (19,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionSiblingLookupOnExtraOptionalParam()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this A a, object o = null) { throw new Exception(); }
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void ExtensionSiblingLookupOnVoidReturn()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this A a) { throw new Exception(); }
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(A)' and 'E.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("Test.GetAwaiter(A)", "E.GetAwaiter(A)"));
}
[Fact]
public void ExtensionSiblingLookupOnInapplicable()
{
var source = @"
using System;
public class A { }
public class B { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this B a) { throw new Exception(); }
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void ExtensionSiblingLookupOnOptional()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
public static Awaiter GetAwaiter(this object a, object o = null) { throw new Exception(); }
}
public static class E
{
public static void GetAwaiter(this object a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (24,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionSiblingDuellingLookupOne()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
}
public static class E1
{
public static void GetAwaiter(this A a) { throw new Exception(); }
}
public static class E2
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (20,9): error CS0121: The call is ambiguous between the following methods or properties: 'E1.GetAwaiter(A)' and 'E2.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("E1.GetAwaiter(A)", "E2.GetAwaiter(A)")
);
}
[Fact]
public void ExtensionSiblingDuellingLookupTwo()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
}
public static class E1
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
public static class E2
{
public static void GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (20,9): error CS0121: The call is ambiguous between the following methods or properties: 'E1.GetAwaiter(A)' and 'E2.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("E1.GetAwaiter(A)", "E2.GetAwaiter(A)")
);
}
[Fact]
public void ExtensionSiblingLookupOnLessDerived()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
public static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this object a) { throw new Exception(); }
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void ExtensionSiblingLookupOnEquallyDerived()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class Test
{
static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static Awaiter GetAwaiter(this object a) { throw new Exception(); }
}
public static class EE
{
public static void GetAwaiter(this object a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (24,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(object)' and 'EE.GetAwaiter(object)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("Test.GetAwaiter(object)", "EE.GetAwaiter(object)")
);
}
[Fact]
public void ExtensionSiblingBadLookupOnEquallyDerived()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class Test
{
static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static void GetAwaiter(this object a) { throw new Exception(); }
}
public static class EE
{
public static Awaiter GetAwaiter(this object a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (24,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.GetAwaiter(object)' and 'EE.GetAwaiter(object)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("Test.GetAwaiter(object)", "EE.GetAwaiter(object)")
);
}
[Fact]
public void ExtensionParentNamespaceLookupOnOnReturnTypeMismatch()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this A a) { throw new Exception(); }
}
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (24,17): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionParentNamespaceLookupOnOnInapplicableCandidate()
{
var source = @"
using System;
public class A { }
public class B { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
static class Test
{
static async void F()
{
await new A();
}
public static void GetAwaiter(this B a) { throw new Exception(); }
}
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void ExtensionParentNamespaceLookupOnOptional()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
static class Test
{
static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static Awaiter GetAwaiter(this A a, object o = null) { throw new Exception(); }
}
}
public static class EE
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (11,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionParentNamespaceLookupOnLessDerived()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
static class Test
{
static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static void GetAwaiter(this object a) { throw new Exception(); }
}
}
public static class EE
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (11,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void ExtensionParentNamespaceDuellingLookupBad()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace child
{
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
}
}
public static class E1
{
public static void GetAwaiter(this A a) { throw new Exception(); }
}
public static class E2
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (23,13): error CS0121: The call is ambiguous between the following methods or properties: 'E1.GetAwaiter(A)' and 'E2.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("E1.GetAwaiter(A)", "E2.GetAwaiter(A)")
);
}
[Fact]
public void ExtensionParentNamespaceDuellingLookupWasGoodNowBad()
{
var source = @"
using System;
public class A { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace child
{
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
}
}
public static class E1
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
public static class E2
{
public static void GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (23,13): error CS0121: The call is ambiguous between the following methods or properties: 'E1.GetAwaiter(A)' and 'E2.GetAwaiter(A)'
// await new A();
Diagnostic(ErrorCode.ERR_AmbigCall, "await new A()").WithArguments("E1.GetAwaiter(A)", "E2.GetAwaiter(A)")
);
}
[Fact]
public void ExtensionParentNamespaceSingleClassDuel()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
public static class Test
{
static async void F()
{
await new A();
}
static void Main()
{
F();
}
}
}
}
public static class E2
{
public static void GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void TruncateExtensionMethodLookupAfterFirstNamespace()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
public static class Test
{
public static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static void GetAwaiter(this I1 a) { throw new Exception(); }
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}
}
public static class E2
{
public static void GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void BadTruncateExtensionMethodLookupAfterFirstNamespace()
{
var source = @"
using System;
public interface I1 { }
public interface I2 { }
public class A : I1, I2 { }
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(System.Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
namespace parent
{
namespace child
{
public static class Test
{
public static void Main()
{
F();
}
static async void F()
{
await new A();
}
public static void GetAwaiter(this I1 a) { throw new Exception(); }
}
}
public static class E
{
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}
}
public static class E2
{
public static void GetAwaiter(this I1 a) { throw new Exception(); }
public static Awaiter GetAwaiter(this A a) { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (11,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void FallbackToGetAwaiterExtensionMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
private Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
public static Awaiter GetAwaiter(this A a)
{
return new Awaiter();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
}
[Fact]
public void BadFallbackToGetAwaiterExtensionMethodInPresenceOfInstanceGetAwaiterMethodWithOptionalParameter()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter(object o = null) { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
public static Awaiter GetAwaiter(this A a)
{
return new Awaiter();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A"));
}
[Fact]
public void GetAwaiterMethodWithNonZeroArity()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
await new C();
await new D();
await new E();
}
}
class A
{
public Awaiter GetAwaiter(object o = null) { return null; }
}
class B
{
public Awaiter GetAwaiter(object o) { return null; }
}
class C
{
}
class D
{
}
class E
{
public Awaiter GetAwaiter() { return null; }
public Awaiter GetAwaiter(object o = null) { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
public static Awaiter GetAwaiter(this C a, object o = null)
{
return new Awaiter();
}
public static Awaiter GetAwaiter(this D a, object o)
{
return new Awaiter();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS1986: 'await' requires that the type A have a suitable GetAwaiter method
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new A()").WithArguments("A").WithLocation(10, 9),
// (11,9): error CS7036: There is no argument given that corresponds to the required parameter 'o' of 'B.GetAwaiter(object)'
// await new B();
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "await new B()").WithArguments("o", "B.GetAwaiter(object)").WithLocation(11, 9),
// (12,9): error CS1986: 'await' requires that the type C have a suitable GetAwaiter method
// await new C();
Diagnostic(ErrorCode.ERR_BadAwaitArg, "await new C()").WithArguments("C").WithLocation(12, 9),
// (13,15): error CS1929: 'D' does not contain a definition for 'GetAwaiter' and the best extension method overload 'MyExtensions.GetAwaiter(C, object)' requires a receiver of type 'C'
// await new D();
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "new D()").WithArguments("D", "GetAwaiter", "MyExtensions.GetAwaiter(C, object)", "C").WithLocation(13, 15));
}
[Fact]
public void GetAwaiterMethodWithNonZeroTypeParameterArity()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
}
}
class A
{
public Awaiter GetAwaiter<T>() { return null; }
}
class B
{
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
public static Awaiter GetAwaiter<T>(this B a)
{
return null;
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0411: The type arguments for method 'A.GetAwaiter<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// await new A();
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "await new A()").WithArguments("A.GetAwaiter<T>()"),
// (11,9): error CS0411: The type arguments for method 'MyExtensions.GetAwaiter<T>(B)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// await new B();
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "await new B()").WithArguments("MyExtensions.GetAwaiter<T>(B)")
);
}
[Fact]
public void AwaiterImplementsINotifyCompletion()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
await new C();
await new D();
}
}
class A
{
public Awaiter1 GetAwaiter() { return null; }
}
class B
{
public Awaiter2 GetAwaiter() { return null; }
}
class C
{
public Awaiter3 GetAwaiter() { return null; }
}
class D
{
public Awaiter4 GetAwaiter() { return null; }
}
class Awaiter1 : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
class OnCompletedImpl : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
}
class Awaiter2 : OnCompletedImpl
{
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
interface OnCompletedInterface : System.Runtime.CompilerServices.INotifyCompletion
{
}
class Awaiter3 : OnCompletedInterface
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
class Awaiter4
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (13,9): error CS4027: 'Awaiter4' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new D();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new D()").WithArguments("Awaiter4", "System.Runtime.CompilerServices.INotifyCompletion"));
}
[WorkItem(770448, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/770448")]
[Fact]
public void AwaiterImplementsINotifyCompletion_Constraint()
{
var source =
@"using System.Runtime.CompilerServices;
class Awaitable<T>
{
internal T GetAwaiter() { return default(T); }
}
interface IA
{
bool IsCompleted { get; }
object GetResult();
}
interface IB : IA, INotifyCompletion
{
}
class A
{
public void OnCompleted(System.Action a) { }
internal bool IsCompleted { get { return true; } }
internal object GetResult() { return null; }
}
class B : A, INotifyCompletion
{
}
class C
{
static async void F<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>()
where T1 : IA
where T2 : IA, INotifyCompletion
where T3 : IB
where T4 : T1, INotifyCompletion
where T5 : T3
where T6 : A
where T7 : A, INotifyCompletion
where T8 : B
where T9 : T6, INotifyCompletion
where T10 : T8
{
await new Awaitable<T1>();
await new Awaitable<T2>();
await new Awaitable<T3>();
await new Awaitable<T4>();
await new Awaitable<T5>();
await new Awaitable<T6>();
await new Awaitable<T7>();
await new Awaitable<T8>();
await new Awaitable<T9>();
await new Awaitable<T10>();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (37,9): error CS4027: 'T1' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<T1>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<T1>()").WithArguments("T1", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(37, 9),
// (42,9): error CS4027: 'T6' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<T6>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<T6>()").WithArguments("T6", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(42, 9));
}
[WorkItem(770448, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/770448")]
[Fact]
public void AwaiterImplementsINotifyCompletion_InheritedConstraint()
{
var source =
@"using System;
using System.Runtime.CompilerServices;
class Awaitable<T>
{
internal T GetAwaiter() { return default(T); }
}
interface IA
{
bool IsCompleted { get; }
object GetResult();
}
interface IB : IA, INotifyCompletion
{
}
class B : IA, INotifyCompletion
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public object GetResult() { return null; }
}
struct S : IA, INotifyCompletion
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public object GetResult() { return null; }
}
class C<T> where T : IA
{
internal virtual async void F<U>() where U : T
{
await new Awaitable<U>();
}
}
class D1 : C<IB>
{
internal override async void F<T1>()
{
await new Awaitable<T1>();
}
}
class D2 : C<B>
{
internal override async void F<T2>()
{
await new Awaitable<T2>();
}
}
class D3 : C<S>
{
internal override async void F<T3>()
{
await new Awaitable<T3>();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (31,9): error CS4027: 'U' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<U>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<U>()").WithArguments("U", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(31, 9),
// (52,9): error CS0117: 'T3' does not contain a definition for 'IsCompleted'
// await new Awaitable<T3>();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new Awaitable<T3>()").WithArguments("T3", "IsCompleted").WithLocation(52, 9));
}
[WorkItem(770448, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/770448")]
[Fact]
public void AwaiterImplementsINotifyCompletion_UserDefinedConversion()
{
var source =
@"using System;
using System.Runtime.CompilerServices;
class Awaitable<T>
{
internal T GetAwaiter() { return default(T); }
}
interface IA : INotifyCompletion
{
bool IsCompleted { get; }
object GetResult();
}
class A : INotifyCompletion
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public object GetResult() { return null; }
}
class B
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public static implicit operator A(B b) { return default(A); }
}
class B<T> where T : INotifyCompletion
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public static implicit operator T(B<T> b) { return default(T); }
}
class C
{
async void F()
{
await new Awaitable<B>();
await new Awaitable<B<IA>>();
await new Awaitable<B<A>>();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (34,9): error CS4027: 'B' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<B>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<B>()").WithArguments("B", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(34, 9),
// (35,9): error CS4027: 'B<IA>' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<B<IA>>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<B<IA>>()").WithArguments("B<IA>", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(35, 9),
// (36,9): error CS4027: 'B<A>' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new Awaitable<B<A>>();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new Awaitable<B<A>>()").WithArguments("B<A>", "System.Runtime.CompilerServices.INotifyCompletion").WithLocation(36, 9));
}
/// <summary>
/// Should call ICriticalNotifyCompletion.UnsafeOnCompleted
/// if the awaiter type implements ICriticalNotifyCompletion.
/// </summary>
[Fact]
public void AwaiterImplementsICriticalNotifyCompletion_Constraint()
{
var source =
@"using System;
using System.Runtime.CompilerServices;
class Awaitable<T>
{
internal T GetAwaiter() { return default(T); }
}
class A : INotifyCompletion
{
public void OnCompleted(Action a) { }
public bool IsCompleted { get { return true; } }
public object GetResult() { return null; }
}
class B : A, ICriticalNotifyCompletion
{
public void UnsafeOnCompleted(Action a) { }
}
class C
{
static async void F<T1, T2, T3, T4, T5, T6>()
where T1 : A
where T2 : A, ICriticalNotifyCompletion
where T3 : B
where T4 : T1
where T5 : T2
where T6 : T1, ICriticalNotifyCompletion
{
await new Awaitable<T1>();
await new Awaitable<T2>();
await new Awaitable<T3>();
await new Awaitable<T4>();
await new Awaitable<T5>();
await new Awaitable<T6>();
}
}";
var compilation = CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
var verifier = CompileAndVerify(compilation);
var actualIL = verifier.VisualizeIL("C.<F>d__0<T1, T2, T3, T4, T5, T6>.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()");
var calls = actualIL.Split(new[] { '\n', '\r' }, System.StringSplitOptions.RemoveEmptyEntries).Where(s => s.Contains("OnCompleted")).ToArray();
Assert.Equal(6, calls.Length);
Assert.Equal(" IL_0056: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitOnCompleted<T1, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T1, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[0]);
Assert.Equal(" IL_00b9: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitUnsafeOnCompleted<T2, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T2, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[1]);
Assert.Equal(" IL_011c: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitUnsafeOnCompleted<T3, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T3, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[2]);
Assert.Equal(" IL_0182: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitOnCompleted<T4, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T4, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[3]);
Assert.Equal(" IL_01ea: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitUnsafeOnCompleted<T5, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T5, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[4]);
Assert.Equal(" IL_0252: call \"void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.AwaitUnsafeOnCompleted<T6, C.<F>d__0<T1, T2, T3, T4, T5, T6>>(ref T6, ref C.<F>d__0<T1, T2, T3, T4, T5, T6>)\"", calls[5]);
}
[Fact]
public void ConditionalOnCompletedImplementation()
{
var source = @"
using System;
using System.Diagnostics;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
await new B();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class B
{
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
[Conditional(""Condition"")]
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}
static class MyExtensions
{
public static Awaiter GetAwaiter(this B a)
{
return null;
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (28,17): error CS0629: Conditional member 'Awaiter.OnCompleted(System.Action)' cannot implement interface member 'System.Runtime.CompilerServices.INotifyCompletion.OnCompleted(System.Action)' in type 'Awaiter'
// public void OnCompleted(Action x) { }
Diagnostic(ErrorCode.ERR_InterfaceImplementedByConditional, "OnCompleted").WithArguments("Awaiter.OnCompleted(System.Action)", "System.Runtime.CompilerServices.INotifyCompletion.OnCompleted(System.Action)", "Awaiter"));
}
[Fact]
public void MissingIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'Awaiter' does not contain a definition for 'IsCompleted'
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new A()").WithArguments("Awaiter", "IsCompleted"));
}
[Fact]
public void InaccessibleIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'Awaiter' does not contain a definition for 'IsCompleted'
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new A()").WithArguments("Awaiter", "IsCompleted"));
}
[Fact]
public void StaticIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public static bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0176: Member 'Awaiter.IsCompleted' cannot be accessed with an instance reference; qualify it with a type name instead
// await new A();
Diagnostic(ErrorCode.ERR_ObjectProhibited, "await new A()").WithArguments("Awaiter.IsCompleted")
);
}
[Fact]
public void StaticWriteonlyIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public static bool IsCompleted { set { } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0176: Member 'Awaiter.IsCompleted' cannot be accessed with an instance reference; qualify it with a type name instead
// await new A();
Diagnostic(ErrorCode.ERR_ObjectProhibited, "await new A()").WithArguments("Awaiter.IsCompleted")
);
}
[Fact]
public void StaticAccessorlessIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public static bool IsCompleted { }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (25,24): error CS0548: 'Awaiter.IsCompleted': property or indexer must have at least one accessor
// public static bool IsCompleted { }
Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "IsCompleted").WithArguments("Awaiter.IsCompleted"),
// (10,9): error CS0176: Member 'Awaiter.IsCompleted' cannot be accessed with an instance reference; qualify it with a type name instead
// await new A();
Diagnostic(ErrorCode.ERR_ObjectProhibited, "await new A()").WithArguments("Awaiter.IsCompleted")
);
}
[Fact]
public void NonBooleanIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public int IsCompleted { get { return -1; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS4011: 'await' requires that the return type 'Awaiter' of 'A.GetAwaiter()' have suitable IsCompleted, OnCompleted, and GetResult members, and implement INotifyCompletion or ICriticalNotifyCompletion
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaiterPattern, "await new A()").WithArguments("Awaiter", "A"));
}
[Fact]
public void WriteonlyIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public bool IsCompleted { set { } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'A' does not contain a definition for 'IsCompleted'
// await new A();
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "await new A()").WithArguments("Awaiter.IsCompleted"));
}
[Fact]
public void WriteonlyNonBooleanIsCompletedProperty()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult() { throw new Exception(); }
public int IsCompleted { set { } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'A' does not contain a definition for 'IsCompleted'
// await new A();
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "await new A()").WithArguments("Awaiter.IsCompleted"));
}
[Fact]
public void MissingGetResultInstanceMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'Awaiter' does not contain a definition for 'GetResult'
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new A()").WithArguments("Awaiter", "GetResult"));
}
[Fact]
public void InaccessibleGetResultInstanceMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
private bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0122: 'Awaiter.GetResult()' is inaccessible due to its protection level
// await new A();
Diagnostic(ErrorCode.ERR_BadAccess, "await new A()").WithArguments("Awaiter.GetResult()")
);
}
[Fact]
public void StaticResultMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public static bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0176: Member 'Awaiter.GetResult()' cannot be accessed with an instance reference; qualify it with a type name instead
// await new A();
Diagnostic(ErrorCode.ERR_ObjectProhibited, "await new A()").WithArguments("Awaiter.GetResult()"));
}
[Fact]
public void GetResultExtensionMethod()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool IsCompleted { get { return false; } }
}
static class MyExtensions
{
public static bool GetResult(this Awaiter a)
{
throw new Exception();
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0117: 'Awaiter' does not contain a definition for 'GetResult'
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new A()").WithArguments("Awaiter", "GetResult"));
}
[Fact]
public void GetResultWithNonZeroArity()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult(object o = null) { throw new Exception(); }
public bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS4011: 'await' requires that the return type 'Awaiter' of 'A.GetAwaiter()' have suitable IsCompleted, OnCompleted, and GetResult members, and implement INotifyCompletion or ICriticalNotifyCompletion
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaiterPattern, "await new A()").WithArguments("Awaiter", "A"));
}
[Fact]
public void GetResultWithNonZeroTypeParameterArity()
{
var source = @"
using System;
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
public bool GetResult<T>() { throw new Exception(); }
public bool IsCompleted { get { return false; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS0411: The type arguments for method 'Awaiter.GetResult<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// await new A();
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "await new A()").WithArguments("Awaiter.GetResult<T>()")
);
}
[Fact]
public void ConditionalGetResult()
{
var source = @"
using System;
using System.Diagnostics;
static class Program
{
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return new Awaiter(); }
}
class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public void OnCompleted(Action x) { }
[Conditional(""X"")]
public void GetResult() { Console.WriteLine(""unconditional""); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (15,9): error CS4011: 'await' requires that the return type 'Awaiter' of 'A.GetAwaiter()' have suitable IsCompleted, OnCompleted, and GetResult members, and implement INotifyCompletion or ICriticalNotifyCompletion
// await new A();
Diagnostic(ErrorCode.ERR_BadAwaiterPattern, "await new A()").WithArguments("Awaiter", "A"));
}
[Fact]
public void Missing_IsCompleted_INotifyCompletion_GetResult()
{
var source = @"
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter //: System.Runtime.CompilerServices.INotifyCompletion
{
//public void OnCompleted(Action x) { }
//public bool GetResult() { throw new Exception(); }
//public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (8,9): error CS0117: 'Awaiter' does not contain a definition for 'IsCompleted'
// await new A();
Diagnostic(ErrorCode.ERR_NoSuchMember, "await new A()").WithArguments("Awaiter", "IsCompleted"));
}
[Fact]
public void Missing_INotifyCompletion_GetResult()
{
var source = @"
static class Program
{
static void Main() { }
static async void f()
{
await new A();
}
}
class A
{
public Awaiter GetAwaiter() { return null; }
}
class Awaiter //: System.Runtime.CompilerServices.INotifyCompletion
{
//public void OnCompleted(Action x) { }
//public bool GetResult() { throw new Exception(); }
public bool IsCompleted { get { return true; } }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (8,9): error CS4027: 'Awaiter' does not implement 'System.Runtime.CompilerServices.INotifyCompletion'
// await new A();
Diagnostic(ErrorCode.ERR_DoesntImplementAwaitInterface, "await new A()").WithArguments("Awaiter", "System.Runtime.CompilerServices.INotifyCompletion"));
}
[Fact]
public void BadAwaitArg_NeedSystem()
{
var source = @"
// using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
class App {
static void Main() {
EnumDevices().Wait();
}
private static async Task EnumDevices() {
await DeviceInformation.FindAllAsync();
return;
}
}";
CreateCompilationWithWinRT(source).VerifyDiagnostics(
// (12,9): error CS4035: 'Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection>' does not contain a definition for 'GetAwaiter' and no extension method 'GetAwaiter' accepting a first argument of type 'Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection>' could be found (are you missing a using directive for 'System'?)
// await DeviceInformation.FindAllAsync();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtensionNeedUsing, "await DeviceInformation.FindAllAsync()").WithArguments("Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection>", "GetAwaiter", "System")
);
}
[Fact]
public void ErrorInAwaitSubexpression()
{
var source = @"
class C
{
async void M()
{
using (await goo())
{
}
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (6,22): error CS0103: The name 'goo' does not exist in the current context
// using (await goo())
Diagnostic(ErrorCode.ERR_NameNotInContext, "goo").WithArguments("goo"));
}
[Fact]
public void BadAwaitArgIntrinsic()
{
var source = @"
class Test
{
public void goo() { }
public async void awaitVoid()
{
await goo();
}
public async void awaitNull()
{
await null;
}
public async void awaitMethodGroup()
{
await goo;
}
public async void awaitLambda()
{
await (x => x);
}
public static void Main() { }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (8,9): error CS4008: Cannot await 'void'
// await goo();
Diagnostic(ErrorCode.ERR_BadAwaitArgVoidCall, "await goo()"),
// (13,9): error CS4001: Cannot await '<null>;'
// await null;
Diagnostic(ErrorCode.ERR_BadAwaitArgIntrinsic, "await null").WithArguments("<null>"),
// (18,9): error CS4001: Cannot await 'method group'
// await goo;
Diagnostic(ErrorCode.ERR_BadAwaitArgIntrinsic, "await goo").WithArguments("method group"),
// (23,9): error CS4001: Cannot await 'lambda expression'
// await (x => x);
Diagnostic(ErrorCode.ERR_BadAwaitArgIntrinsic, "await (x => x)").WithArguments("lambda expression"));
}
[Fact]
public void BadAwaitArgVoidCall()
{
var source = @"
using System.Threading.Tasks;
class Test
{
public async void goo()
{
await Task.Factory.StartNew(() => { });
}
public async void bar()
{
await goo();
}
public static void Main() { }
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (10,9): error CS4008: Cannot await 'void'
// await goo();
Diagnostic(ErrorCode.ERR_BadAwaitArgVoidCall, "await goo()"));
}
[Fact, WorkItem(531356, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531356")]
public void Repro_17997()
{
var source = @"
class C
{
public IVsTask ResolveReferenceAsync()
{
return this.VsTasksService.InvokeAsync(async delegate
{
return null;
});
}
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (4,12): error CS0246: The type or namespace name 'IVsTask' could not be found (are you missing a using directive or an assembly reference?)
// public IVsTask ResolveReferenceAsync()
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IVsTask").WithArguments("IVsTask").WithLocation(4, 12),
// (6,21): error CS1061: 'C' does not contain a definition for 'VsTasksService' and no extension method 'VsTasksService' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?)
// return this.VsTasksService.InvokeAsync(async delegate
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "VsTasksService").WithArguments("C", "VsTasksService").WithLocation(6, 21),
// (6,54): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
// return this.VsTasksService.InvokeAsync(async delegate
Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "delegate").WithLocation(6, 54));
}
[Fact, WorkItem(627123, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627123")]
public void Repro_627123()
{
var source = @"
using System;
using System.Runtime.CompilerServices;
interface IA : INotifyCompletion
{
bool IsCompleted { get; }
void GetResult();
}
interface IB : IA
{
new Action GetResult { get; }
}
interface IC
{
IB GetAwaiter();
}
class D
{
Action<IC> a = async x => await x;
}";
CreateCompilationWithMscorlib461(source).VerifyDiagnostics(
// (23,31): error CS0118: 'GetResult' is a property but is used like a method
// Action<IC> a = async x => await x;
Diagnostic(ErrorCode.ERR_BadSKknown, "await x").WithArguments("GetResult", "property", "method")
);
}
[Fact, WorkItem(1091911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1091911")]
public void Repro_1091911()
{
const string source = @"
using System;
using System.Threading.Tasks;
class Repro
{
int Boom { get { return 42; } }
static Task<dynamic> Compute()
{
return Task.FromResult<dynamic>(new Repro());
}
static async Task<int> Bug()
{
dynamic results = await Compute().ConfigureAwait(false);
var x = results.Boom;
return (int)x;
}
static void Main()
{
Console.WriteLine(Bug().Result);
}
}";
var comp = CreateCompilationWithMscorlib461(source, new[] { SystemCoreRef, CSharpRef }, TestOptions.ReleaseExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "42");
}
[Fact]
public void DynamicResultTypeCustomAwaiter()
{
const string source = @"
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
public struct MyTask
{
public readonly Task task;
private readonly Func<dynamic> getResult;
public MyTask(Task task, Func<dynamic> getResult)
{
this.task = task;
this.getResult = getResult;
}
public dynamic Result { get { return this.getResult(); } }
}
public struct MyAwaiter : INotifyCompletion
{
private readonly MyTask task;
public MyAwaiter(MyTask task)
{
this.task = task;
}
public bool IsCompleted { get { return true; } }
public dynamic GetResult() { Console.Write(""dynamic""); return task.Result; }
public void OnCompleted(System.Action continuation) { task.task.ContinueWith(_ => continuation()); }
}
public static class TaskAwaiter
{
public static MyAwaiter GetAwaiter(this MyTask task)
{
return new MyAwaiter(task);
}
}
class Repro
{
int Boom { get { return 42; } }
static MyTask Compute()
{
var task = Task.FromResult(new Repro());
return new MyTask(task, () => task.Result);
}
static async Task<int> Bug()
{
return (await Compute()).Boom;
}
static void Main()
{
Console.WriteLine(Bug().Result);
}
}
";
var comp = CreateCompilationWithMscorlib461(source, new[] { Net40.References.SystemCore, Net40.References.MicrosoftCSharp }, TestOptions.ReleaseExe);
comp.VerifyDiagnostics(
// warning CS1685: The predefined type 'ExtensionAttribute' is defined in multiple assemblies in the global alias; using definition from 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Diagnostic(ErrorCode.WRN_MultiplePredefTypes).WithArguments("System.Runtime.CompilerServices.ExtensionAttribute", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089").WithLocation(1, 1));
// PEVerify: Cannot change initonly field outside its .ctor.
var compiled = CompileAndVerify(comp, expectedOutput: "dynamic42", verify: Verification.FailsPEVerify);
compiled.VerifyIL("MyAwaiter.OnCompleted(System.Action)", @"
{
// Code size 43 (0x2b)
.maxstack 3
.locals init (MyAwaiter.<>c__DisplayClass5_0 V_0) //CS$<>8__locals0
IL_0000: newobj ""MyAwaiter.<>c__DisplayClass5_0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.1
IL_0008: stfld ""System.Action MyAwaiter.<>c__DisplayClass5_0.continuation""
IL_000d: ldarg.0
IL_000e: ldflda ""MyTask MyAwaiter.task""
IL_0013: ldfld ""System.Threading.Tasks.Task MyTask.task""
IL_0018: ldloc.0
IL_0019: ldftn ""void MyAwaiter.<>c__DisplayClass5_0.<OnCompleted>b__0(System.Threading.Tasks.Task)""
IL_001f: newobj ""System.Action<System.Threading.Tasks.Task>..ctor(object, System.IntPtr)""
IL_0024: callvirt ""System.Threading.Tasks.Task System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task>)""
IL_0029: pop
IL_002a: ret
}");
}
}
}
|