未验证 提交 d3d10fba 编写于 作者: J Julien Couvreur 提交者: GitHub

Emit AsyncIteratorStateMachine attribute on async-iterator methods (#31553)

上级 ac724330
......@@ -1636,13 +1636,19 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
var arg = new TypedConstant(compilation.GetWellKnownType(WellKnownType.System_Type),
TypedConstantKind.Type, stateMachineType.GetUnboundGenericTypeOrSelf());
if (isAsync)
if (isAsync && isIterator)
{
AddSynthesizedAttribute(ref attributes,
compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor,
ImmutableArray.Create(arg)));
}
else if (isAsync)
{
AddSynthesizedAttribute(ref attributes,
compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor,
ImmutableArray.Create(arg)));
}
if (isIterator)
else if (isIterator)
{
AddSynthesizedAttribute(ref attributes,
compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor,
......
......@@ -465,8 +465,35 @@ public static async System.Collections.Generic.IAsyncEnumerable<int> M()
CompileAndVerify(comp, symbolValidator: module =>
{
var method = module.GlobalNamespace.GetMember<MethodSymbol>("C.M");
AssertEx.SetEqual(new[] { "AsyncStateMachineAttribute", "IteratorStateMachineAttribute" },
AssertEx.SetEqual(new[] { "AsyncIteratorStateMachineAttribute" },
GetAttributeNames(method.GetAttributes()));
var attribute = method.GetAttributes().Single();
var argument = attribute.ConstructorArguments.Single();
Assert.Equal("System.Type", argument.Type.ToTestDisplayString());
Assert.Equal("C.<M>d__0", ((ITypeSymbol)argument.Value).ToTestDisplayString());
});
}
[ConditionalFact(typeof(WindowsDesktopOnly))]
public void AttributesSynthesized_Optional()
{
string source = @"
public class C
{
public static async System.Collections.Generic.IAsyncEnumerable<int> M()
{
await System.Threading.Tasks.Task.CompletedTask;
yield return 4;
}
}";
var comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugDll);
comp.MakeTypeMissing(WellKnownType.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute);
comp.VerifyDiagnostics();
CompileAndVerify(comp, symbolValidator: module =>
{
var method = module.GlobalNamespace.GetMember<MethodSymbol>("C.M");
Assert.Empty(GetAttributeNames(method.GetAttributes()));
});
}
......@@ -1073,9 +1100,9 @@ async System.Collections.Generic.IAsyncEnumerator<int> M()
// (4,60): error CS8370: Feature 'async streams' is not available in C# 7.3. Please use language version 8.0 or greater.
// async System.Collections.Generic.IAsyncEnumerator<int> M()
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("async streams", "8.0").WithLocation(4, 60),
// (23,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (34,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(23, 2)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(34, 2)
);
}
......
......@@ -566,6 +566,7 @@ public void AllWellKnownTypes()
case WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute:
case WellKnownType.System_Index:
case WellKnownType.System_Range:
case WellKnownType.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute:
case WellKnownType.System_IAsyncDisposable:
case WellKnownType.System_Collections_Generic_IAsyncEnumerable_T:
case WellKnownType.System_Collections_Generic_IAsyncEnumerator_T:
......@@ -891,6 +892,7 @@ public void AllWellKnownTypeMembers()
case WellKnownMember.System_Range__Create:
case WellKnownMember.System_Range__FromStart:
case WellKnownMember.System_Range__ToEnd:
case WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor:
case WellKnownMember.System_IAsyncDisposable__DisposeAsync:
case WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator:
case WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync:
......
......@@ -456,6 +456,8 @@ internal enum WellKnownMember
System_Range__FromStart,
System_Range__All,
System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor,
System_IAsyncDisposable__DisposeAsync,
System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator,
System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync,
......@@ -480,5 +482,7 @@ internal enum WellKnownMember
System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
Count
// Remember to update the AllWellKnownTypeMembers tests when making changes here
}
}
......@@ -3137,6 +3137,14 @@ static WellKnownMembers()
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Range - WellKnownType.ExtSentinel),
// System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor
(byte)MemberFlags.Constructor, // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
1, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
(byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Type,
// System_IAsyncDisposable__DisposeAsync
(byte)(MemberFlags.Method | MemberFlags.Virtual), // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_IAsyncDisposable - WellKnownType.ExtSentinel), // DeclaringTypeId
......@@ -3707,6 +3715,8 @@ static WellKnownMembers()
"FromStart", // System_Range__FromStart
"All", // System_Range__All
".ctor", // System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor
"DisposeAsync", // System_IAsyncDisposable__DisposeAsync
"GetAsyncEnumerator", // System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator
"MoveNextAsync", // System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync
......@@ -3757,6 +3767,7 @@ internal static bool IsSynthesizedAttributeOptional(WellKnownMember attributeMem
case WellKnownMember.System_STAThreadAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor:
return true;
default:
......
......@@ -280,6 +280,7 @@ internal enum WellKnownType
System_Index,
System_Range,
System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute,
System_IAsyncDisposable,
System_Collections_Generic_IAsyncEnumerable_T,
System_Collections_Generic_IAsyncEnumerator_T,
......@@ -292,6 +293,8 @@ internal enum WellKnownType
System_Runtime_CompilerServices_AsyncIteratorMethodBuilder,
NextAvailable,
// Remember to update the AllWellKnownTypes tests when making changes here
}
internal static class WellKnownTypes
......@@ -565,6 +568,7 @@ internal static class WellKnownTypes
"System.Index",
"System.Range",
"System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute",
"System.IAsyncDisposable",
"System.Collections.Generic.IAsyncEnumerable`1",
"System.Collections.Generic.IAsyncEnumerator`1",
......@@ -627,11 +631,11 @@ private static void AssertEnumAndTableInSync()
typeIdName = typeIdName.Substring(0, separator);
}
Debug.Assert(name == typeIdName);
Debug.Assert(name == typeIdName, "Enum name and type name must match");
}
Debug.Assert((int)WellKnownType.ExtSentinel == 255);
Debug.Assert((int)WellKnownType.NextAvailable <= 512);
Debug.Assert((int)WellKnownType.NextAvailable <= 512, "Time for a new sentinel");
}
public static bool IsWellKnownType(this WellKnownType typeId)
......
......@@ -132,6 +132,17 @@ public interface IAsyncDisposable
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class AsyncIteratorStateMachineAttribute : StateMachineAttribute
{
public AsyncIteratorStateMachineAttribute(Type stateMachineType) : base(stateMachineType)
{
}
}
}
#nullable disable
namespace System.Threading.Tasks.Sources
......
......@@ -507,6 +507,7 @@ End Namespace
WellKnownType.System_ReadOnlySpan_T,
WellKnownType.System_Index,
WellKnownType.System_Range,
WellKnownType.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute,
WellKnownType.System_IAsyncDisposable,
WellKnownType.System_Collections_Generic_IAsyncEnumerable_T,
WellKnownType.System_Collections_Generic_IAsyncEnumerator_T,
......@@ -561,6 +562,7 @@ End Namespace
WellKnownType.System_ReadOnlySpan_T,
WellKnownType.System_Index,
WellKnownType.System_Range,
WellKnownType.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute,
WellKnownType.System_IAsyncDisposable,
WellKnownType.System_Collections_Generic_IAsyncEnumerable_T,
WellKnownType.System_Collections_Generic_IAsyncEnumerator_T,
......@@ -623,6 +625,7 @@ End Namespace
WellKnownMember.System_ReadOnlySpan_T__ctor,
WellKnownMember.System_ReadOnlySpan_T__get_Item,
WellKnownMember.System_ReadOnlySpan_T__get_Length,
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor,
WellKnownMember.System_IAsyncDisposable__DisposeAsync,
WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator,
WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync,
......@@ -749,6 +752,7 @@ End Namespace
WellKnownMember.System_ReadOnlySpan_T__ctor,
WellKnownMember.System_ReadOnlySpan_T__get_Item,
WellKnownMember.System_ReadOnlySpan_T__get_Length,
WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorStateMachineAttribute__ctor,
WellKnownMember.System_IAsyncDisposable__DisposeAsync,
WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator,
WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册