Skip to content

Commit f47c54d

Browse files
committed
Fix AwaitResolver for real async Task<T> subtypes
The runtime type of async Task<T> is often a subclass like AsyncStateMachineBox<TResult, TStateMachine>, not Task<T> itself. Walk up the BaseType chain to find Task<T> so that await on real async .NET operations (e.g. HttpClient.GetStringAsync) correctly returns the result instead of None.
1 parent 5a09b4d commit f47c54d

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

src/core/IronPython/Runtime/Types/PythonTypeInfo.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -980,15 +980,21 @@ internal static MemberGroup GetExtensionMemberGroup(Type type, MemberInfo[] news
980980
}
981981

982982
if (typeof(Task).IsAssignableFrom(type)) {
983-
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) {
983+
// Walk up the type hierarchy to find Task<T> (the runtime type may be
984+
// a subclass such as AsyncStateMachineBox<TResult, TStateMachine>).
985+
Type taskType = type;
986+
while (taskType != null && !(taskType.IsGenericType && taskType.GetGenericTypeDefinition() == typeof(Task<>))) {
987+
taskType = taskType.BaseType;
988+
}
989+
if (taskType != null) {
984990
// Only use the generic TaskAwaitable<T> if the result type is visible
985991
// (e.g. Task.CompletedTask is Task<VoidTaskResult> at runtime where
986992
// VoidTaskResult is internal — fall back to non-generic TaskAwaitable)
987-
Type resultType = type.GetGenericArguments()[0];
993+
Type resultType = taskType.GetGenericArguments()[0];
988994
if (resultType.IsVisible) {
989995
MethodInfo genMeth = typeof(InstanceOps).GetMethod(nameof(InstanceOps.TaskAwaitMethodGeneric));
990996
return new MemberGroup(
991-
MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(type.GetGenericArguments()), type)
997+
MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(taskType.GetGenericArguments()), type)
992998
);
993999
}
9941000
}

0 commit comments

Comments
 (0)