Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix source generator for exception types and fix is operator #1682

Merged
merged 11 commits into from
Aug 1, 2024
15 changes: 15 additions & 0 deletions src/Authoring/WinRT.SourceGenerator/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,10 @@ public static string GetAbiType(ITypeSymbol type, TypeMapper mapper)
{
return "IntPtr";
}
else if (typeStr == "System.Exception")
{
return "ABI.System.Exception";
}

if (type.IsValueType)
{
Expand Down Expand Up @@ -669,6 +673,17 @@ public static string GetMarshalerClass(string type, string abiType, TypeKind kin
return "global::ABI.System.Type";
}
}
else if (type == "System.Exception" || type == "Exception")
{
if (isArray)
{
return "MarshalNonBlittable<global::System.Exception>";
}
else
{
return "global::ABI.System.Exception";
}
}
else if (type == "System.Object" || type == "object")
{
return "MarshalInspectable<object>";
Expand Down
32 changes: 32 additions & 0 deletions src/Tests/FunctionalTests/Collections/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@
networkNames.AddRange(names);
}

if (names is IList<double> networkNamesList)
{
return 101;
}

var exceptionList = new List<Exception>();
instance.BindableIterableProperty = exceptionList;
if (exceptionList != instance.BindableIterableProperty)
{
return 101;
}

var exceptionList2 = new List<ArgumentException>();
instance.BindableIterableProperty = exceptionList2;
if (exceptionList2 != instance.BindableIterableProperty)
{
return 101;
}

instance.BindableIterableProperty = CustomClass.Instances;
if (CustomClass.Instances != instance.BindableIterableProperty)
{
Expand All @@ -113,6 +132,19 @@
return 101;
}

var uriList = new List<Uri>();
instance.BindableIterableProperty = uriList;
if (uriList != instance.BindableIterableProperty)
{
return 101;
}

var dateTimeOffsetList = new List<System.DateTimeOffset>();
instance.BindableIterableProperty = dateTimeOffsetList;
if (dateTimeOffsetList != instance.BindableIterableProperty)
{
return 101;
}

return 100;

Expand Down
15 changes: 15 additions & 0 deletions src/Tests/TestComponentCSharp/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,21 @@ namespace winrt::TestComponentCSharp::implementation
std::copy(_ints.begin(), _ints.end(), ints.begin());
}

com_array<winrt::hresult> Class::GetAndSetHResults(array_view<winrt::hresult const> hresults)
{
return com_array<winrt::hresult>(hresults.begin(), hresults.end());
}

com_array<winrt::Windows::Foundation::Uri> Class::GetAndSetUris(array_view<winrt::Windows::Foundation::Uri const> uris)
{
return com_array<winrt::Windows::Foundation::Uri>(uris.begin(), uris.end());
}

com_array<winrt::Windows::Foundation::DateTime> Class::GetAndSetDateTimes(array_view<winrt::Windows::Foundation::DateTime const> datetime)
{
return com_array<winrt::Windows::Foundation::DateTime>(datetime.begin(), datetime.end());
}

IVectorView<int32_t> Class::GetIntVector()
{
return winrt::single_threaded_vector_view(std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
Expand Down
4 changes: 4 additions & 0 deletions src/Tests/TestComponentCSharp/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ namespace winrt::TestComponentCSharp::implementation
com_array<int32_t> GetInts();
void FillInts(array_view<int32_t> ints);

com_array<winrt::hresult> GetAndSetHResults(array_view<winrt::hresult const> hresults);
com_array<winrt::Windows::Foundation::Uri> GetAndSetUris(array_view<winrt::Windows::Foundation::Uri const> uris);
com_array<winrt::Windows::Foundation::DateTime> GetAndSetDateTimes(array_view<winrt::Windows::Foundation::DateTime const> datetime);

Windows::Foundation::IAsyncOperation<int32_t> GetIntAsync();
Windows::Foundation::IAsyncOperationWithProgress<hstring, int32_t> GetStringAsync();

Expand Down
4 changes: 4 additions & 0 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.idl
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ namespace TestComponentCSharp
Int32[] GetInts();
void FillInts(ref Int32[] ints);

Windows.Foundation.HResult[] GetAndSetHResults(Windows.Foundation.HResult[] hresults);
Windows.Foundation.Uri[] GetAndSetUris(Windows.Foundation.Uri[] uris);
Windows.Foundation.DateTime[] GetAndSetDateTimes(Windows.Foundation.DateTime[] datetime);

// Generics
Windows.Foundation.IAsyncOperation<Int32> GetIntAsync();
Windows.Foundation.IAsyncOperationWithProgress<String, Int32> GetStringAsync();
Expand Down
1 change: 1 addition & 0 deletions src/WinRT.Runtime/FundamentalMarshalers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ internal static class NonBlittableMarshallingStubs
public static object DateTimeOffset_FromManaged(global::System.DateTimeOffset value) => DateTimeOffset.FromManaged(value);

public static object Type_CreateMarshalerArray(global::System.Type[] value) => Type.CreateMarshalerArray(value);
public static object Exception_CreateMarshalerArray(global::System.Exception[] value) => global::WinRT.MarshalNonBlittable<global::System.Exception>.CreateMarshalerArray(value);

private static void NoOp(object obj)
{
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/IWinRTObject.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ internal sealed bool IsInterfaceImplementedFallback(RuntimeTypeHandle interfaceT
return false;
}

Type helperType = type.FindHelperType();
Type helperType = type.FindHelperType(throwIfNotImplemented);
if (helperType is null || !helperType.IsInterface)
{
return false;
Expand Down
26 changes: 24 additions & 2 deletions src/WinRT.Runtime/Marshalers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ static MarshalGeneric()
typeof(T) == typeof(ulong) ||
typeof(T) == typeof(float) ||
typeof(T) == typeof(double) ||
typeof(T) == typeof(Guid))
typeof(T) == typeof(Guid) ||
typeof(Exception).IsAssignableFrom(typeof(T)))
{
// Special case some well known primitive types that we know might be constructed
// for this type, but not actually used. For these, we just keep all default values.
Expand Down Expand Up @@ -1009,11 +1010,12 @@ private static Type GetAbiType()
return Enum.GetUnderlyingType(typeof(T));
}

// These 4 types are true non blittable types that are valid to use here
// These 5 types are true non blittable types that are valid to use here
if (typeof(T) == typeof(bool)) return typeof(byte);
if (typeof(T) == typeof(char)) return typeof(ushort);
if (typeof(T) == typeof(global::System.TimeSpan)) return typeof(global::ABI.System.TimeSpan);
if (typeof(T) == typeof(DateTimeOffset)) return typeof(global::ABI.System.DateTimeOffset);
if (typeof(T) == typeof(global::System.Exception)) return typeof(global::ABI.System.Exception);

// These types are actually blittable, but this marshaller is still constructed elsewhere.
// Just return null instead of using MarshalGeneric<T>, to avoid constructing that too.
Expand Down Expand Up @@ -2026,6 +2028,26 @@ static Marshaler()
DisposeMarshalerArray = new Action<object>(ABI.System.Type.DisposeMarshalerArray);
DisposeAbiArray = new Action<object>(ABI.System.Type.DisposeAbiArray);
}
else if (typeof(Exception).IsAssignableFrom(typeof(T)))
manodasanW marked this conversation as resolved.
Show resolved Hide resolved
{
AbiType = typeof(ABI.System.Exception);
CreateMarshaler = (T value) => ABI.System.Exception.CreateMarshaler((Exception)(object)value);
CreateMarshaler2 = CreateMarshaler;
GetAbi = (object box) => ABI.System.Exception.GetAbi((ABI.System.Exception.Marshaler)box);
FromAbi = (object value) => (T)(object)ABI.System.Exception.FromAbi((ABI.System.Exception)value);
CopyAbi = (object box, IntPtr dest) => ABI.System.Exception.CopyAbi((ABI.System.Exception.Marshaler)box, dest);
CopyManaged = (Action<T, IntPtr>)(object)new Action<Exception, IntPtr>(ABI.System.Exception.CopyManaged);
FromManaged = (T value) => ABI.System.Exception.FromManaged((Exception)(object)value);
DisposeMarshaler = (object box) => ABI.System.Exception.DisposeMarshaler((ABI.System.Exception.Marshaler)box);
DisposeAbi = (object box) => ABI.System.Exception.DisposeAbi((ABI.System.Exception)box);
CreateMarshalerArray = (Func<T[], object>)(object)new Func<Exception[], object>(ABI.System.NonBlittableMarshallingStubs.Exception_CreateMarshalerArray);
GetAbiArray = new Func<object, (int, IntPtr)>(MarshalNonBlittable<Exception>.GetAbiArray);
FromAbiArray = (Func<object, T[]>)(object)new Func<object, Exception[]>(MarshalNonBlittable<Exception>.FromAbiArray);
FromManagedArray = (Func<T[], (int, IntPtr)>)(object)new Func<Exception[], (int, IntPtr)>(MarshalNonBlittable<Exception>.FromManagedArray);
CopyManagedArray = (Action<T[], IntPtr>)(object)new Action<Exception[], IntPtr>(MarshalNonBlittable<Exception>.CopyManagedArray);
DisposeMarshalerArray = new Action<object>(MarshalNonBlittable<Exception>.DisposeMarshalerArray);
DisposeAbiArray = new Action<object>(MarshalNonBlittable<Exception>.DisposeAbiArray);
}
else if (typeof(T).IsValueType)
{
if (typeof(T) == typeof(bool))
Expand Down
3 changes: 2 additions & 1 deletion src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,5 @@ TypesMustExist : Type 'WinRT.WinRTAssemblyExportsTypeAttribute' does not exist i
TypesMustExist : Type 'Microsoft.UI.Xaml.Data.BindableCustomProperty' does not exist in the reference but it does exist in the implementation.
TypesMustExist : Type 'WinRT.BindableCustomPropertyAttribute' does not exist in the reference but it does exist in the implementation.
TypesMustExist : Type 'Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation' does not exist in the reference but it does exist in the implementation.
Total Issues: 272
MembersMustExist : Member 'public void ABI.System.Uri.DisposeAbiArray(System.Object)' does not exist in the reference but it does exist in the implementation.
Total Issues: 273
19 changes: 18 additions & 1 deletion src/WinRT.Runtime/Projections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

namespace WinRT
{
// Marker type to indicate the helper type cannot be constructed on AOT.
internal sealed class HelperTypeMetadataNotAvailableOnAot
{
}

#if EMBED
internal
#else
Expand Down Expand Up @@ -262,6 +267,18 @@ private static void RegisterCustomAbiTypeMappingNoLock(
DynamicallyAccessedMemberTypes.PublicFields)]
#endif
public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRuntimeClass = false)
{
return FindCustomHelperTypeMapping(publicType, filterToRuntimeClass, false);
}

#if NET
[UnconditionalSuppressMessage("Trimming", "IL2055", Justification = "The type arguments are guaranteed to be valid for the generic ABI types.")]
[UnconditionalSuppressMessage("Trimming", "IL2068", Justification = "All types added to 'CustomTypeToHelperTypeMappings' have metadata explicitly preserved.")]
[return: DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicFields)]
#endif
internal static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRuntimeClass, bool returnMarkerTypeIfNotAotCompatible)
{
rwlock.EnterReadLock();
try
Expand All @@ -283,7 +300,7 @@ public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRun
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot retrieve a helper type for public type '{publicType}'.");
return returnMarkerTypeIfNotAotCompatible ? typeof(HelperTypeMetadataNotAvailableOnAot) : throw new NotSupportedException($"Cannot retrieve a helper type for public type '{publicType}'.");
}
#endif

Expand Down
1 change: 1 addition & 0 deletions src/WinRT.Runtime/Projections/Uri.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ public static IntPtr FromManaged(global::System.Uri value)
public static void DisposeMarshalerArray(MarshalInterfaceHelper<global::System.Uri>.MarshalerArray array) => MarshalInterfaceHelper<global::System.Uri>.DisposeMarshalerArray(array);
public static void DisposeMarshaler(IObjectReference m) { m?.Dispose(); }
public static void DisposeAbi(IntPtr abi) { MarshalInspectable<object>.DisposeAbi(abi); }
public static void DisposeAbiArray(object box) => MarshalInterfaceHelper<global::System.Uri>.DisposeAbiArray(box);

public static string GetGuidSignature()
{
Expand Down
26 changes: 23 additions & 3 deletions src/WinRT.Runtime/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ static class TypeExtensions
#endif
public static Type FindHelperType(this Type type)
{
return type.FindHelperType(true);
}

#if NET
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicFields)]
[UnconditionalSuppressMessage("Trimming", "IL2073", Justification = "Matching trimming annotations are used at all callsites registering helper types present in the cache.")]
#endif
internal static Type FindHelperType(this Type type, bool throwIfNotAotSupported)
{
#if NET
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicFields)]
Expand All @@ -37,7 +47,7 @@ static Type FindHelperTypeNoCache(Type type)
type = typeof(Exception);
}

Type customMapping = Projections.FindCustomHelperTypeMapping(type);
Type customMapping = Projections.FindCustomHelperTypeMapping(type, false, true);
if (customMapping is not null)
{
return customMapping;
Expand Down Expand Up @@ -69,7 +79,17 @@ static Type FindHelperTypeNoCache(Type type)
return FindHelperTypeFallback(type);
}

return HelperTypeCache.GetOrAdd(type, FindHelperTypeNoCache);
var helperType = HelperTypeCache.GetOrAdd(type, FindHelperTypeNoCache);
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
if (helperType == typeof(HelperTypeMetadataNotAvailableOnAot))
{
return throwIfNotAotSupported ? throw new NotSupportedException($"Cannot retrieve a helper type for generic public type '{type}'.") : null;
}
}
#endif
return helperType;

#if NET
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "No members of the generic type are dynamically accessed other than for the attributes on it.")]
Expand All @@ -83,7 +103,7 @@ static Type GetHelperTypeFromAttribute(WindowsRuntimeHelperTypeAttribute helperT
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot retrieve the helper type from generic type '{type}'.");
return typeof(HelperTypeMetadataNotAvailableOnAot);
}
#endif

Expand Down