Skip to content

Commit

Permalink
Fix recurisve issue with covariant interfaces and fix IID being wrong…
Browse files Browse the repository at this point in the history
… for custom type mapped interfaces (#1297)
  • Loading branch information
manodasanW authored Mar 14, 2023
1 parent ea463c3 commit 8d8f1e1
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/Tests/UnitTest/GuidTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ public void TestGenerics()
AssertGuid<IList<Uri>>("0d82bd8d-fe62-5d67-a7b9-7886dd75bc4e");
AssertGuid<IList<AsyncActionCompletedHandler>>("5dafe591-86dc-59aa-bfda-07f5d59fc708");
AssertGuid<IList<ComposedNonBlittableStruct>>("c8477314-b257-511b-a3a1-9e4eb6385152");
AssertGuid<IList<IDisposable>>("1bfca4f6-2c4e-5174-9869-b39d35848fcc");
AssertGuid<IList<IWwwFormUrlDecoderEntry>>("2f5fb6d3-231f-57a1-9f2a-daa7e43bf075");
AssertGuid<IList<WwwFormUrlDecoderEntry>>("1d9ba3f5-b997-5a7d-82c4-7857ecbf3a42");
AssertGuid<IList<Deferral>>("a3c9b753-57ad-537f-9626-4ae5785473d4");
AssertGuid<IList<DateTimeOffset>>("94390dc5-e442-5870-88b6-007e232f902c");
AssertGuid<IList<Point>>("c0d513a9-ec4a-5a5d-b6d5-b707defdb9f7");
}
}
}
28 changes: 26 additions & 2 deletions src/Tests/UnitTest/TestComponentCSharp_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2276,8 +2276,32 @@ internal class ManagedType { }
public void CCWOfListOfManagedType()
{
using var ccw = ComWrappersSupport.CreateCCWForObject(new List<ManagedType>());
using var qiResult = ccw.As(GuidGenerator.GetIID(typeof(global::System.Collections.Generic.IEnumerable<object>).GetHelperType()));
}
using var qiResult = ccw.As(GuidGenerator.GetIID(typeof(global::System.Collections.Generic.IEnumerable<object>).GetHelperType()));
}

internal class ManagedType2 : List<ManagedType2> { }

internal class ManagedType3 : List<ManagedType3>, IDisposable
{
public void Dispose()
{
}
}

[Fact]
public void CCWOfListOfManagedType2()
{
using var ccw = ComWrappersSupport.CreateCCWForObject(new ManagedType2());
var qiResult = ccw.As(GuidGenerator.GetIID(typeof(global::System.Collections.Generic.IEnumerable<object>).GetHelperType()));
}

[Fact]
public void CCWOfListOfManagedType3()
{
using var ccw = ComWrappersSupport.CreateCCWForObject(new ManagedType3());
var qiResult = ccw.As(GuidGenerator.GetIID(typeof(global::System.Collections.Generic.IEnumerable<object>).GetHelperType()));
var qiResult2 = ccw.As(GuidGenerator.GetIID(typeof(global::System.Collections.Generic.IEnumerable<IDisposable>).GetHelperType()));
}

[Fact]
public void WeakReferenceOfManagedObject()
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ internal static List<ComInterfaceEntry> GetInterfaceTableEntries(
}

if (iface.IsConstructedGenericType
&& Projections.TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, out var compatibleIfaces))
&& Projections.TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, null, out var compatibleIfaces))
{
foreach (var compatibleIface in compatibleIfaces)
{
Expand Down
5 changes: 4 additions & 1 deletion src/WinRT.Runtime/GuidGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ public static string GetSignature(
}
}

type = type.IsInterface ? (type.GetAuthoringMetadataType() ?? type) : type;
// For authoring interfaces, we use the metadata type to get the guid.
// For built-in system interfaces that are custom type mapped, we use the helper type to get the guid.
// For others, either the type itself or the helper type has the same guid and can be used.
type = type.IsInterface ? (type.GetAuthoringMetadataType() ?? helperType ?? type) : type;

if (type.IsGenericType)
{
Expand Down
23 changes: 19 additions & 4 deletions src/WinRT.Runtime/Projections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public static bool TryGetCompatibleWindowsRuntimeTypeForVariantType(Type type, o
return true;
}

private static HashSet<Type> GetCompatibleTypes(Type type)
private static HashSet<Type> GetCompatibleTypes(Type type, Stack<Type> typeStack)
{
HashSet<Type> compatibleTypes = new HashSet<Type>();

Expand All @@ -352,7 +352,7 @@ private static HashSet<Type> GetCompatibleTypes(Type type)
}

if (iface.IsConstructedGenericType
&& TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, out var compatibleIfaces))
&& TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, typeStack, out var compatibleIfaces))
{
compatibleTypes.UnionWith(compatibleIfaces);
}
Expand Down Expand Up @@ -411,7 +411,7 @@ void GetAllPossibleTypeCombinationsCore(List<Type> accum, Stack<Type> stack, IEn
}
}

internal static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(Type type, out IEnumerable<Type> compatibleTypes)
internal static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(Type type, Stack<Type> typeStack, out IEnumerable<Type> compatibleTypes)
{
compatibleTypes = null;
if (!type.IsConstructedGenericType)
Expand All @@ -426,6 +426,19 @@ internal static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(Type type
return false;
}

if (typeStack == null)
{
typeStack = new Stack<Type>();
}
else
{
if (typeStack.Contains(type))
{
return false;
}
}
typeStack.Push(type);

var genericConstraints = definition.GetGenericArguments();
var genericArguments = type.GetGenericArguments();
List<List<Type>> compatibleTypesPerGeneric = new List<List<Type>>();
Expand All @@ -441,17 +454,19 @@ internal static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(Type type
}
else if (!argumentCovariantObject)
{
typeStack.Pop();
return false;
}

if (argumentCovariantObject)
{
compatibleTypesForGeneric.AddRange(GetCompatibleTypes(genericArguments[i]));
compatibleTypesForGeneric.AddRange(GetCompatibleTypes(genericArguments[i], typeStack));
}

compatibleTypesPerGeneric.Add(compatibleTypesForGeneric);
}

typeStack.Pop();
compatibleTypes = GetAllPossibleTypeCombinations(compatibleTypesPerGeneric, definition);
return true;
}
Expand Down

0 comments on commit 8d8f1e1

Please sign in to comment.