提交 993be402 编写于 作者: C Charles Stoner 提交者: GitHub

Merge pull request #12671 from cston/tasklike-misc

Misc. changes for Task-like type support
......@@ -941,7 +941,7 @@ private static bool DoesInputTypeContain(BoundExpression argument, TypeSymbol fo
}
var delegateParameters = delegateType.DelegateParameters();
if (delegateParameters.IsEmpty)
if (delegateParameters.IsDefaultOrEmpty)
{
return false;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Roslyn.Utilities;
......@@ -102,6 +103,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
if (method.IsVoidReturningAsync())
{
var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder);
Debug.Assert((object)builderType != null);
MethodSymbol createBuilderMethod;
bool customBuilder = false;
TryGetBuilderMember<MethodSymbol>(
......@@ -110,8 +112,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
builderType,
customBuilder,
out createBuilderMethod);
if ((object)builderType == null ||
(object)createBuilderMethod == null)
if ((object)createBuilderMethod == null)
{
collection = default(AsyncMethodBuilderMemberCollection);
return false;
......@@ -146,6 +147,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
else
{
builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder);
Debug.Assert((object)builderType != null);
TryGetBuilderMember<MethodSymbol>(
F,
WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Create,
......@@ -159,8 +161,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
customBuilder,
out taskProperty);
}
if ((object)builderType == null ||
(object)createBuilderMethod == null ||
if ((object)createBuilderMethod == null ||
(object)taskProperty == null)
{
collection = default(AsyncMethodBuilderMemberCollection);
......@@ -202,11 +203,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
if (!customBuilder)
{
builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T);
if ((object)builderType == null)
{
collection = default(AsyncMethodBuilderMemberCollection);
return false;
}
Debug.Assert((object)builderType != null);
builderType = builderType.Construct(resultType);
}
if (customBuilder)
......
......@@ -355,9 +355,12 @@ public static bool IsDelegateType(this TypeSymbol type)
public static ImmutableArray<ParameterSymbol> DelegateParameters(this TypeSymbol type)
{
Debug.Assert((object)type.DelegateInvokeMethod() != null && !type.DelegateInvokeMethod().HasUseSiteError,
"This method should only be called on valid delegate types.");
return type.DelegateInvokeMethod().Parameters;
var invokeMethod = type.DelegateInvokeMethod();
if ((object)invokeMethod == null)
{
return default(ImmutableArray<ParameterSymbol>);
}
return invokeMethod.Parameters;
}
public static bool TryGetElementTypesIfTupleOrCompatible(this TypeSymbol type, out ImmutableArray<TypeSymbol> elementTypes)
......@@ -1339,28 +1342,30 @@ internal static bool IsCustomTaskType(this NamedTypeSymbol type, out NamedTypeSy
/// </summary>
internal static TypeSymbol NormalizeTaskTypes(this TypeSymbol type, CSharpCompilation compilation)
{
NormalizeTaskTypesCore(compilation, ref type);
NormalizeTaskTypesInType(compilation, ref type);
return type;
}
/// <summary>
/// Replace Task-like types with Task types. Returns true if there were changes.
/// </summary>
private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref TypeSymbol type)
private static bool NormalizeTaskTypesInType(CSharpCompilation compilation, ref TypeSymbol type)
{
switch (type.Kind)
{
case SymbolKind.NamedType:
{
var namedType = (NamedTypeSymbol)type;
var changed = NormalizeTaskTypesCore(compilation, ref namedType);
var changed = type.IsTupleType ?
NormalizeTaskTypesInTuple(compilation, ref namedType) :
NormalizeTaskTypesInNamedType(compilation, ref namedType);
type = namedType;
return changed;
}
case SymbolKind.ArrayType:
{
var arrayType = (ArrayTypeSymbol)type;
var changed = NormalizeTaskTypesCore(compilation, ref arrayType);
var changed = NormalizeTaskTypesInArray(compilation, ref arrayType);
type = arrayType;
return changed;
}
......@@ -1368,7 +1373,7 @@ private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref Ty
return false;
}
private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref NamedTypeSymbol type)
private static bool NormalizeTaskTypesInNamedType(CSharpCompilation compilation, ref NamedTypeSymbol type)
{
bool hasChanged = false;
......@@ -1380,12 +1385,13 @@ private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref Na
type.GetAllTypeArguments(typeArgumentsBuilder, ref useSiteDiagnostics);
for (int i = 0; i < typeArgumentsBuilder.Count; i++)
{
var typeArgNormalized = typeArgumentsBuilder[i].Type;
if (NormalizeTaskTypesCore(compilation, ref typeArgNormalized))
var typeWithModifier = typeArgumentsBuilder[i];
var typeArgNormalized = typeWithModifier.Type;
if (NormalizeTaskTypesInType(compilation, ref typeArgNormalized))
{
hasChanged = true;
// Should preserve custom modifiers (see https://github.com/dotnet/roslyn/issues/12615).
typeArgumentsBuilder[i] = new TypeWithModifiers(typeArgNormalized);
// Preserve custom modifiers but without normalizing those types.
typeArgumentsBuilder[i] = new TypeWithModifiers(typeArgNormalized, typeWithModifier.CustomModifiers);
}
}
if (hasChanged)
......@@ -1415,17 +1421,34 @@ private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref Na
}
type = arity == 0 ?
taskType :
taskType.Construct(type.TypeArgumentsNoUseSiteDiagnostics);
taskType.Construct(
ImmutableArray.Create(
new TypeWithModifiers(
type.TypeArgumentsNoUseSiteDiagnostics[0],
type.HasTypeArgumentsCustomModifiers ? type.TypeArgumentsCustomModifiers[0] : default(ImmutableArray<CustomModifier>))),
unbound: false);
hasChanged = true;
}
return hasChanged;
}
private static bool NormalizeTaskTypesCore(CSharpCompilation compilation, ref ArrayTypeSymbol arrayType)
private static bool NormalizeTaskTypesInTuple(CSharpCompilation compilation, ref NamedTypeSymbol type)
{
Debug.Assert(type.IsTupleType);
var underlyingType = type.TupleUnderlyingType;
if (!NormalizeTaskTypesInNamedType(compilation, ref underlyingType))
{
return false;
}
type = TupleTypeSymbol.Create(underlyingType, type.TupleElementNames);
return true;
}
private static bool NormalizeTaskTypesInArray(CSharpCompilation compilation, ref ArrayTypeSymbol arrayType)
{
var elementType = arrayType.ElementType;
if (!NormalizeTaskTypesCore(compilation, ref elementType))
if (!NormalizeTaskTypesInType(compilation, ref elementType))
{
return false;
}
......
......@@ -3124,13 +3124,13 @@ public static void Main()
[WorkItem(840843, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/840843")]
[Fact]
public void MissingAsyncMethodBuilder()
public void MissingAsyncVoidMethodBuilder()
{
var source = @"
class C
{
async void M() {}
}
}
";
var comp = CSharpTestBaseBase.CreateCompilation(source, new[] { MscorlibRef }, TestOptions.ReleaseDll); // NOTE: 4.0, not 4.5, so it's missing the async helpers.
......@@ -3154,6 +3154,68 @@ class C
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{}").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "SetStateMachine").WithLocation(4, 20));
}
[Fact]
public void MissingAsyncTaskMethodBuilder()
{
var source =
@"using System.Threading.Tasks;
class C
{
async Task M() {}
}";
var comp = CSharpTestBaseBase.CreateCompilation(source, new[] { MscorlibRef }, TestOptions.ReleaseDll); // NOTE: 4.0, not 4.5, so it's missing the async helpers.
comp.VerifyEmitDiagnostics(
// (4,16): 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.
// async Task M() {}
Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M").WithLocation(4, 16),
// (4,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder' is not defined or imported
// async Task M() {}
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "{}").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder").WithLocation(4, 20),
// (4,20): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create'
// async Task M() {}
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{}").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder", "Create").WithLocation(4, 20),
// (4,20): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Task'
// async Task M() {}
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{}").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder", "Task").WithLocation(4, 20),
// (4,20): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext'
// async Task M() {}
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{}").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "MoveNext").WithLocation(4, 20),
// (4,20): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine'
// async Task M() {}
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{}").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "SetStateMachine").WithLocation(4, 20));
}
[Fact]
public void MissingAsyncTaskMethodBuilder_T()
{
var source =
@"using System.Threading.Tasks;
class C
{
async Task<int> F() => 3;
}";
var comp = CSharpTestBaseBase.CreateCompilation(source, new[] { MscorlibRef }, TestOptions.ReleaseDll); // NOTE: 4.0, not 4.5, so it's missing the async helpers.
comp.VerifyEmitDiagnostics(
// (4,21): 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.
// async Task<int> F() => 3;
Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "F").WithLocation(4, 21),
// (4,25): error CS0518: Predefined type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1' is not defined or imported
// async Task<int> F() => 3;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "=> 3").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1").WithLocation(4, 25),
// (4,25): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Create'
// async Task<int> F() => 3;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> 3").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1", "Create").WithLocation(4, 25),
// (4,25): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Task'
// async Task<int> F() => 3;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> 3").WithArguments("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1", "Task").WithLocation(4, 25),
// (4,25): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext'
// async Task<int> F() => 3;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> 3").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "MoveNext").WithLocation(4, 25),
// (4,25): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine'
// async Task<int> F() => 3;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> 3").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "SetStateMachine").WithLocation(4, 25));
}
[Fact]
public void PresentAsyncTasklikeBuilderMethod()
{
......
......@@ -406,6 +406,67 @@ class MyTaskMethodBuilder<T>
Assert.Equal("MyTask<T>", method.ReturnType.ToDisplayString());
}
[Fact]
public void Dynamic()
{
var source =
@"using System;
using System.Runtime.CompilerServices;
class C
{
static void F<T>(Func<MyTask<T>> f) { }
static void G(Func<MyTask<dynamic>> f) { }
static void M(object o)
{
#pragma warning disable CS1998
F(async () => (dynamic)o);
F(async () => new[] { (dynamic)o });
G(async () => o);
#pragma warning restore CS1998
}
}
class MyTask<T>
{
public static MyTaskMethodBuilder<T> CreateAsyncMethodBuilder() => null;
internal Awaiter GetAwaiter() => null;
internal class Awaiter : INotifyCompletion
{
public void OnCompleted(Action a) { }
internal bool IsCompleted => true;
internal T GetResult() => default(T);
}
}
class MyTaskMethodBuilder<T>
{
public void SetStateMachine(IAsyncStateMachine stateMachine) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { }
public void SetException(Exception e) { }
public void SetResult(T t) { }
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { }
public MyTask<T> Task => default(MyTask<T>);
}";
var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef });
var verifier = CompileAndVerify(
compilation,
expectedSignatures: new[]
{
Signature(
"C+<>c__DisplayClass2_0",
"<M>b__0",
".method [System.Runtime.CompilerServices.AsyncStateMachineAttribute(C+<>c__DisplayClass2_0+<<M>b__0>d)] assembly hidebysig instance [System.Runtime.CompilerServices.DynamicAttribute(System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument])] MyTask`1[System.Object] <M>b__0() cil managed"),
Signature(
"C+<>c__DisplayClass2_0",
"<M>b__1",
".method [System.Runtime.CompilerServices.AsyncStateMachineAttribute(C+<>c__DisplayClass2_0+<<M>b__1>d)] assembly hidebysig instance [System.Runtime.CompilerServices.DynamicAttribute(System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument])] MyTask`1[System.Object[]] <M>b__1() cil managed"),
Signature(
"C+<>c__DisplayClass2_0",
"<M>b__2",
".method [System.Runtime.CompilerServices.AsyncStateMachineAttribute(C+<>c__DisplayClass2_0+<<M>b__2>d)] assembly hidebysig instance [System.Runtime.CompilerServices.DynamicAttribute(System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument])] MyTask`1[System.Object] <M>b__2() cil managed"),
});
verifier.VerifyDiagnostics();
}
[Fact]
public void NonTaskBuilder()
{
......@@ -473,5 +534,42 @@ internal class Awaiter : INotifyCompletion
// async MyTask<T> F<T>(T t) => t;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> t").WithArguments("System.IEquatable<T>", "Task").WithLocation(8, 35));
}
[Fact]
public void NonTaskBuilder_Array()
{
var source =
@"using System;
using System.Runtime.CompilerServices;
class C
{
static async void M()
{
#pragma warning disable CS1998
async MyTask F() { };
await F();
#pragma warning restore CS1998
}
}
struct MyTask
{
public static object[] CreateAsyncMethodBuilder() => null;
internal Awaiter GetAwaiter() => null;
internal class Awaiter : INotifyCompletion
{
public void OnCompleted(Action a) { }
internal bool IsCompleted => true;
internal void GetResult() { }
}
}";
var compilation = CreateCompilationWithMscorlib45(source);
compilation.VerifyEmitDiagnostics(
// (8,22): error CS0161: 'F()': not all code paths return a value
// async MyTask F() { };
Diagnostic(ErrorCode.ERR_ReturnExpected, "F").WithArguments("F()").WithLocation(8, 22),
// (8,22): error CS1983: The return type of an async method must be void, Task or Task<T>
// async MyTask F() { };
Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F").WithLocation(8, 22));
}
}
}
......@@ -22,8 +22,8 @@ struct ValueTask<T> { public static Task<T> CreateAsyncMethodBuilder() => null;
";
var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
var methodf = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("f").Single();
var methodg = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("g").Single();
var methodf = compilation.GetMember<MethodSymbol>("C.f");
var methodg = compilation.GetMember<MethodSymbol>("C.g");
Assert.True(methodf.IsAsync);
Assert.True(methodg.IsAsync);
}
......@@ -313,8 +313,8 @@ class ValueTaskMethodBuilder {}
class ValueTaskMethodBuilder<T> {}
";
var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
var methodf = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("f").Single();
var methodg = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("g").Single();
var methodf = compilation.GetMember<MethodSymbol>("C.f");
var methodg = compilation.GetMember<MethodSymbol>("C.g");
Assert.True(methodf.IsAsync);
Assert.True(methodg.IsAsync);
}
......
......@@ -3821,5 +3821,41 @@ Task YAsync()
Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "async () => YAsync()").WithLocation(15, 21)
);
}
[Fact()]
public void DelegateTypeWithNoInvokeMethod()
{
// Delegate type with no Invoke method.
var ilSource =
@".class public auto ansi sealed D`1<T>
extends [mscorlib]System.MulticastDelegate
{
.method public hidebysig specialname rtspecialname
instance void .ctor(object 'object',
native int 'method') runtime managed
{
}
}";
var source =
@"using System;
using System.Threading.Tasks;
class C
{
static void F(D<Task> d) { }
static void F<T>(D<Task<T>> d) { }
static void F(Func<Task> f) { }
static void F<T>(Func<Task<T>> f) { }
static void M()
{
#pragma warning disable CS1998
F(async () => { });
F(async () => { return 3; });
#pragma warning restore CS1998
}
}";
var reference = CompileIL(ilSource);
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference });
compilation.VerifyEmitDiagnostics();
}
}
}
......@@ -585,24 +585,163 @@ struct MyTaskMethodBuilder<T>
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<T>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<T>", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<T>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<MyTask, MyTask[]>[,]", type.ToTestDisplayString());
Assert.Equal("C<System.Threading.Tasks.Task, System.Threading.Tasks.Task[]>[,]", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("C<System.Threading.Tasks.Task, System.Threading.Tasks.Task[]>[,]", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F3").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("A<MyTask<MyTask>>.B<C<System.Int32, MyTask>>", type.ToTestDisplayString());
Assert.Equal("A<System.Threading.Tasks.Task<System.Threading.Tasks.Task>>.B<C<System.Int32, System.Threading.Tasks.Task>>", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("A<System.Threading.Tasks.Task<System.Threading.Tasks.Task>>.B<C<System.Int32, System.Threading.Tasks.Task>>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F4").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("System.Int32*", type.ToTestDisplayString());
Assert.Equal("System.Int32*", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Int32*", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Tuples()
{
string source =
@"using System;
using System.Threading.Tasks;
class C<T, U>
{
#pragma warning disable CS0169
static MyTask<ValueTuple<MyTask, T>> F0;
static ((MyTask a, T b) c, MyTask<(U, MyTask<T>)[]> d) F1;
static Task<(Task, object)[]> F2;
static (MyTask, char, byte, short, ushort, int, uint, long, ulong, char, byte, short, ushort, int, uint, long, MyTask<T>) F3;
#pragma warning restore CS0169
}
struct MyTask
{
public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder();
}
struct MyTask<T>
{
public static MyTaskMethodBuilder<T> CreateAsyncMethodBuilder() => new MyTaskMethodBuilder<T>();
}
struct MyTaskMethodBuilder
{
}
struct MyTaskMethodBuilder<T>
{
}
namespace System
{
struct ValueTuple<T1, T2>
{
}
struct ValueTuple<T1, T2, T3>
{
}
struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, T8>
{
}
}
namespace System.Runtime.CompilerServices
{
class TupleElementNamesAttribute : Attribute
{
public TupleElementNamesAttribute(string[] names) { }
}
}";
var compilation = CreateCompilationWithMscorlib45(source);
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<(MyTask, T)>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<(System.Threading.Tasks.Task, T)>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("((MyTask a, T b) c, MyTask<(U, MyTask<T>)[]> d)", type.ToTestDisplayString());
Assert.Equal("((System.Threading.Tasks.Task a, T b) c, System.Threading.Tasks.Task<(U, System.Threading.Tasks.Task<T>)[]> d)", normalized.ToTestDisplayString());
// No changes.
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("System.Threading.Tasks.Task<(System.Threading.Tasks.Task, System.Object)[]>", type.ToTestDisplayString());
Assert.Same(type, normalized);
// Nested System.ValueTuple<>.
type = compilation.GetMember<FieldSymbol>("C.F3").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("(MyTask, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, MyTask<T>)", type.ToTestDisplayString());
Assert.Equal("(System.Threading.Tasks.Task, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.Threading.Tasks.Task<T>)", normalized.ToTestDisplayString());
Assert.Equal("System.ValueTuple<System.UInt32, System.Int64, MyTask<T>>", GetUnderlyingTupleTypeRest(type).ToTestDisplayString());
Assert.Equal("System.ValueTuple<System.UInt32, System.Int64, System.Threading.Tasks.Task<T>>", GetUnderlyingTupleTypeRest(normalized).ToTestDisplayString());
}
// Return the underlying type of the most-nested part of the TupleTypeSymbol.
private static NamedTypeSymbol GetUnderlyingTupleTypeRest(TypeSymbol type)
{
while (type.IsTupleType)
{
var underlyingType = type.TupleUnderlyingType;
var typeArgs = underlyingType.TypeArguments;
if (typeArgs.Length < 8)
{
return underlyingType;
}
type = typeArgs[7];
}
return null;
}
// Preserve type argument custom modifiers.
[WorkItem(592, "https://github.com/dotnet/roslyn/issues/12615")]
[Fact]
public void NormalizeTaskTypes_TypeArgumentCustomModifiers()
{
var ilSource =
@".class public C
{
.field public static class MyTask`1<class MyTask modopt(class MyTask`1<object>)> F0
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask
{
.method public hidebysig static class MyTaskMethodBuilder CreateAsyncMethodBuilder() cil managed { ldnull ret }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask`1<T>
{
.method public hidebysig static class MyTaskMethodBuilder`1<!T> CreateAsyncMethodBuilder() cil managed { ldnull ret }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder`1<T>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
";
var source =
@"";
var reference = CompileIL(ilSource);
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask modopt(MyTask<System.Object>)>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<System.Threading.Tasks.Task modopt(MyTask<System.Object>)>", normalized.ToTestDisplayString());
}
[Fact]
......@@ -638,16 +777,19 @@ class MyTaskMethodBuilder<V>
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<T, U>.MyTask<U>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<U>", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<U>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<U, C<T, U>.MyTask>.MyTask", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<T, C<T, U>.MyTask<U>>.Inner", type.ToTestDisplayString());
Assert.Equal("C<T, System.Threading.Tasks.Task<U>>.Inner", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("C<T, System.Threading.Tasks.Task<U>>.Inner", normalized.ToTestDisplayString());
}
[Fact]
......@@ -681,12 +823,14 @@ class MyTaskMethodBuilder<V>
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask.A>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<MyTask.A>", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<MyTask.A>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask<System.Object>>.B", type.ToTestDisplayString());
Assert.Equal("MyTask<System.Threading.Tasks.Task<System.Object>>.B", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("MyTask<System.Threading.Tasks.Task<System.Object>>.B", normalized.ToTestDisplayString());
}
/// <summary>
......@@ -720,8 +864,9 @@ struct MyTaskMethodBuilder<T>
var compilation = CreateCompilation(source, references: new[] { MscorlibRef_v20 });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask>", type.ToTestDisplayString());
Assert.Equal("MyTask<MyTask>", type.NormalizeTaskTypes(compilation).ToTestDisplayString());
Assert.Equal("MyTask<MyTask>", normalized.ToTestDisplayString());
}
[Fact]
......
......@@ -8405,27 +8405,26 @@ End Class
<WorkItem(840843, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/840843")>
<Fact>
Public Sub MissingAsyncMethodBuilder()
Dim source = <compilation name="Async">
Public Sub MissingAsyncVoidMethodBuilder()
Dim source =
<compilation name="AsyncVoid">
<file name="a.vb">
Public Class TestCase
Async Sub M()
End Sub
End Class
</file>
</compilation>
</compilation>
Dim comp = CreateCompilationWithReferences(source, {MscorlibRef}, TestOptions.ReleaseDll) ' NOTE: 4.0, Not 4.5, so it's missing the async helpers.
Using stream As New MemoryStream()
AssertTheseDiagnostics(comp.Emit(stream).Diagnostics, <errors>
BC31091: Import of type 'AsyncVoidMethodBuilder' from assembly or module 'Async.dll' failed.
comp.AssertTheseEmitDiagnostics(
<errors>
BC31091: Import of type 'AsyncVoidMethodBuilder' from assembly or module 'AsyncVoid.dll' failed.
Async Sub M()
~~~~~~~~~~~~~~
BC31091: Import of type 'AsyncVoidMethodBuilder' from assembly or module 'Async.dll' failed.
BC31091: Import of type 'AsyncVoidMethodBuilder' from assembly or module 'AsyncVoid.dll' failed.
Async Sub M()
~~~~~~~~~~~~~~
BC31091: Import of type 'IAsyncStateMachine' from assembly or module 'Async.dll' failed.
BC31091: Import of type 'IAsyncStateMachine' from assembly or module 'AsyncVoid.dll' failed.
Async Sub M()
~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext' is not defined.
......@@ -8437,8 +8436,80 @@ BC35000: Requested operation is not available because the runtime library functi
BC42356: This async method lacks 'Await' operators and so 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.
Async Sub M()
~
</errors>)
End Using
</errors>)
End Sub
<Fact>
Public Sub MissingAsyncTaskMethodBuilder()
Dim source =
<compilation name="AsyncTask">
<file name="a.vb">
Imports System.Threading.Tasks
Public Class TestCase
Async Function M() As Task
End Function
End Class
</file>
</compilation>
Dim comp = CreateCompilationWithReferences(source, {MscorlibRef}, TestOptions.ReleaseDll) ' NOTE: 4.0, Not 4.5, so it's missing the async helpers.
comp.AssertTheseEmitDiagnostics(
<errors>
BC31091: Import of type 'AsyncTaskMethodBuilder' from assembly or module 'AsyncTask.dll' failed.
Async Function M() As Task
~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC31091: Import of type 'AsyncTaskMethodBuilder' from assembly or module 'AsyncTask.dll' failed.
Async Function M() As Task
~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC31091: Import of type 'IAsyncStateMachine' from assembly or module 'AsyncTask.dll' failed.
Async Function M() As Task
~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext' is not defined.
Async Function M() As Task
~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine' is not defined.
Async Function M() As Task
~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC42356: This async method lacks 'Await' operators and so 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.
Async Function M() As Task
~
</errors>)
End Sub
<Fact>
Public Sub MissingAsyncTaskMethodBuilder_T()
Dim source =
<compilation name="AsyncTask_T">
<file name="a.vb">
Imports System.Threading.Tasks
Public Class TestCase
Async Function M() As Task(Of Integer)
Return 3
End Function
End Class
</file>
</compilation>
Dim comp = CreateCompilationWithReferences(source, {MscorlibRef}, TestOptions.ReleaseDll) ' NOTE: 4.0, Not 4.5, so it's missing the async helpers.
comp.AssertTheseEmitDiagnostics(
<errors>
BC31091: Import of type 'AsyncTaskMethodBuilder(Of )' from assembly or module 'AsyncTask_T.dll' failed.
Async Function M() As Task(Of Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC31091: Import of type 'AsyncTaskMethodBuilder(Of )' from assembly or module 'AsyncTask_T.dll' failed.
Async Function M() As Task(Of Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC31091: Import of type 'IAsyncStateMachine' from assembly or module 'AsyncTask_T.dll' failed.
Async Function M() As Task(Of Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext' is not defined.
Async Function M() As Task(Of Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Runtime.CompilerServices.IAsyncStateMachine.SetStateMachine' is not defined.
Async Function M() As Task(Of Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC42356: This async method lacks 'Await' operators and so 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.
Async Function M() As Task(Of Integer)
~
</errors>)
End Sub
<WorkItem(863, "https://github.com/dotnet/roslyn/issues/863")>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册