-
Notifications
You must be signed in to change notification settings - Fork 64
Remove trim and AOT warning suppressions #1416
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
base: main
Are you sure you want to change the base?
Changes from all commits
e67049b
a7a04b1
43bb790
f7a6836
6ba9f3f
e2b3282
30ea2d5
7ad819b
1bdd03f
c9939e1
d71cca5
527f0b3
b276451
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,7 +83,7 @@ public override string ToString () | |
| public partial class JniTypeManager : IDisposable, ISetRuntime { | ||
|
|
||
| internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; | ||
| internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods; | ||
| internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.AllMethods; | ||
| internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes; | ||
| internal const DynamicallyAccessedMemberTypes MethodsConstructors = MethodsAndPrivateNested | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; | ||
|
|
||
|
|
@@ -261,28 +261,35 @@ protected virtual IEnumerable<string> GetSimpleReferences (Type type) | |
|
|
||
| static readonly string[] EmptyStringArray = Array.Empty<string> (); | ||
| static readonly Type[] EmptyTypeArray = Array.Empty<Type> (); | ||
| const string NotUsedInAndroid = "This code path is not used in Android projects."; | ||
|
|
||
| // FIXME: https://github.com/dotnet/java-interop/issues/1192 | ||
| [UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = NotUsedInAndroid)] | ||
| static Type MakeArrayType (Type type) => | ||
| type.MakeArrayType (); | ||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| public virtual Type? GetType (JniTypeSignature typeSignature) | ||
| { | ||
| AssertValid (); | ||
|
|
||
| // FIXME: https://github.com/dotnet/java-interop/issues/1192 | ||
| [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = NotUsedInAndroid)] | ||
| [UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = NotUsedInAndroid)] | ||
| static Type MakeGenericType (Type type, Type arrayType) => | ||
| type.MakeGenericType (arrayType); | ||
| if (!typeSignature.IsValid || typeSignature.SimpleReference == null || typeSignature.ArrayRank != 0) | ||
| return null; | ||
|
|
||
| [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = "Types returned here should be preserved via other means.")] | ||
| [return: DynamicallyAccessedMembers (MethodsConstructors)] | ||
| public Type? GetType (JniTypeSignature typeSignature) | ||
| return GetBuiltInTypeForSimpleReference (typeSignature.SimpleReference); | ||
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| public virtual Type? GetTypeAssignableTo ( | ||
| JniTypeSignature typeSignature, | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type targetType) | ||
| { | ||
| AssertValid (); | ||
|
|
||
| return GetTypes (typeSignature).FirstOrDefault (); | ||
| var type = GetType (typeSignature); | ||
| if (type != null && targetType.IsAssignableFrom (type)) { | ||
| return type; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| [RequiresDynamicCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| [RequiresUnreferencedCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| public virtual IEnumerable<Type> GetTypes (JniTypeSignature typeSignature) | ||
| { | ||
| AssertValid (); | ||
|
|
@@ -292,6 +299,8 @@ public virtual IEnumerable<Type> GetTypes (JniTypeSignature typeSignature) | |
| return CreateGetTypesEnumerator (typeSignature); | ||
| } | ||
|
|
||
| [RequiresDynamicCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| [RequiresUnreferencedCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| IEnumerable<Type> CreateGetTypesEnumerator (JniTypeSignature typeSignature) | ||
| { | ||
| if (!typeSignature.IsValid) | ||
|
|
@@ -313,7 +322,7 @@ IEnumerable<Type> CreateGetTypesEnumerator (JniTypeSignature typeSignature) | |
| var rank = typeSignature.ArrayRank; | ||
| var arrayType = type; | ||
| while (rank-- > 0) { | ||
| arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType); | ||
| arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType); | ||
| } | ||
| yield return arrayType; | ||
| } | ||
|
|
@@ -322,13 +331,15 @@ IEnumerable<Type> CreateGetTypesEnumerator (JniTypeSignature typeSignature) | |
| var rank = typeSignature.ArrayRank; | ||
| var arrayType = type; | ||
| while (rank-- > 0) { | ||
| arrayType = MakeArrayType (arrayType); | ||
| arrayType = arrayType.MakeArrayType (); | ||
| } | ||
| yield return arrayType; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [RequiresDynamicCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| [RequiresUnreferencedCode ("JNI type lookup may need to construct array or generic wrapper types dynamically.")] | ||
| IEnumerable<Type> GetPrimitiveArrayTypesForSimpleReference (JniTypeSignature typeSignature, Type type) | ||
| { | ||
| int index = -1; | ||
|
|
@@ -345,14 +356,14 @@ IEnumerable<Type> GetPrimitiveArrayTypesForSimpleReference (JniTypeSignature typ | |
| var rank = typeSignature.ArrayRank-1; | ||
| var arrayType = t; | ||
| while (rank-- > 0) { | ||
| arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType); | ||
| arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType); | ||
| } | ||
| yield return arrayType; | ||
|
|
||
| rank = typeSignature.ArrayRank-1; | ||
| arrayType = t; | ||
| while (rank-- > 0) { | ||
| arrayType = MakeArrayType (arrayType); | ||
| arrayType = arrayType.MakeArrayType (); | ||
| } | ||
| yield return arrayType; | ||
| } | ||
|
|
@@ -369,14 +380,54 @@ protected virtual IEnumerable<Type> GetTypesForSimpleReference (string jniSimple | |
|
|
||
| IEnumerable<Type> CreateGetTypesForSimpleReferenceEnumerator (string jniSimpleReference) | ||
| { | ||
| if (JniBuiltinSimpleReferenceToType.Value.TryGetValue (jniSimpleReference, out var ret)) { | ||
| var ret = GetBuiltInTypeForSimpleReference (jniSimpleReference); | ||
| if (ret != null) { | ||
| yield return ret; | ||
| } | ||
| yield break; | ||
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| static Type? GetBuiltInTypeForSimpleReference (string jniSimpleReference) | ||
| { | ||
| return jniSimpleReference switch { | ||
| "java/lang/String" => typeof (string), | ||
| "net/dot/jni/internal/JavaProxyObject" => typeof (JavaProxyObject), | ||
| "net/dot/jni/internal/JavaProxyThrowable" => typeof (JavaProxyThrowable), | ||
| "net/dot/jni/ManagedPeer" => typeof (ManagedPeer), | ||
| "V" => typeof (void), | ||
| "Z" => typeof (Boolean), | ||
| "java/lang/Boolean" => typeof (Boolean?), | ||
| "B" => typeof (SByte), | ||
| "java/lang/Byte" => typeof (SByte?), | ||
| "C" => typeof (Char), | ||
| "java/lang/Character" => typeof (Char?), | ||
| "S" => typeof (Int16), | ||
| "java/lang/Short" => typeof (Int16?), | ||
| "I" => typeof (Int32), | ||
| "java/lang/Integer" => typeof (Int32?), | ||
| "J" => typeof (Int64), | ||
| "java/lang/Long" => typeof (Int64?), | ||
| "F" => typeof (Single), | ||
| "java/lang/Float" => typeof (Single?), | ||
| "D" => typeof (Double), | ||
| "java/lang/Double" => typeof (Double?), | ||
| _ => null, | ||
| }; | ||
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (MethodsConstructors)] | ||
| public virtual Type? GetTypeForNativeRegistration (JniTypeSignature typeSignature) | ||
| { | ||
| AssertValid (); | ||
|
|
||
| return null; | ||
| } | ||
|
Comment on lines
+419
to
+425
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The This means the trimmer will trust the This is a known limitation of DAM annotations on dictionary-stored types and may be fine if the caller (dotnet/android) guarantees these types are preserved by linker steps, but it's worth documenting as a contract requirement on |
||
|
|
||
| /// <include file="../Documentation/Java.Interop/JniRuntime.JniTypeManager.xml" path="/docs/member[@name='M:GetInvokerType']/*" /> | ||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| [RequiresDynamicCode ("Generic invoker type construction may require runtime generic code generation.")] | ||
| [RequiresUnreferencedCode ("Generic invoker type construction may require unreferenced generic parameter annotations.")] | ||
| public Type? GetInvokerType ( | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type type) | ||
|
|
@@ -388,23 +439,41 @@ IEnumerable<Type> CreateGetTypesForSimpleReferenceEnumerator (string jniSimpleRe | |
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| internal Type? GetInvokerTypeForPeerCreation ( | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type type) | ||
| { | ||
| if (type.IsAbstract || type.IsInterface) { | ||
| return GetInvokerTypeForPeerCreationCore (type); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| protected virtual Type? GetInvokerTypeForPeerCreationCore ( | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type type) | ||
| { | ||
| var signature = type.GetCustomAttribute<JniTypeSignatureAttribute> (); | ||
| if (signature == null || signature.InvokerType == null) { | ||
| return null; | ||
| } | ||
|
|
||
| Type[] arguments = type.GetGenericArguments (); | ||
| if (arguments.Length == 0) | ||
| return signature.InvokerType; | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| [RequiresDynamicCode ("Generic invoker type construction may require runtime generic code generation.")] | ||
| [RequiresUnreferencedCode ("Generic invoker type construction may require unreferenced generic parameter annotations.")] | ||
| protected virtual Type? GetInvokerTypeCore ( | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type type) | ||
| { | ||
| // https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs#L176-L186 | ||
| const string makeGenericTypeMessage = "Generic 'Invoker' types are preserved by the MarkJavaObjects trimmer step."; | ||
|
|
||
| // FIXME: https://github.com/dotnet/java-interop/issues/1192 | ||
| [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = makeGenericTypeMessage)] | ||
| [UnconditionalSuppressMessage ("Trimming", "IL3050", Justification = makeGenericTypeMessage)] | ||
| [return: DynamicallyAccessedMembers (Constructors)] | ||
| static Type MakeGenericType ( | ||
| [DynamicallyAccessedMembers (Constructors)] | ||
| Type type, | ||
| Type [] arguments) => | ||
| type.MakeGenericType (arguments); | ||
|
|
||
| var signature = type.GetCustomAttribute<JniTypeSignatureAttribute> (); | ||
| if (signature == null || signature.InvokerType == null) { | ||
| return null; | ||
|
|
@@ -414,7 +483,7 @@ static Type MakeGenericType ( | |
| if (arguments.Length == 0) | ||
| return signature.InvokerType; | ||
|
|
||
| return MakeGenericType (signature.InvokerType, arguments); | ||
| return signature.InvokerType.MakeGenericType (arguments); | ||
| } | ||
|
|
||
| #if NET | ||
|
|
@@ -457,7 +526,7 @@ static Type MakeGenericType ( | |
|
|
||
| public virtual void RegisterNativeMembers ( | ||
| JniType nativeClass, | ||
| [DynamicallyAccessedMembers (MethodsAndPrivateNested)] | ||
| [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.AllMethods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] | ||
| Type type, | ||
| ReadOnlySpan<char> methods) | ||
| { | ||
|
|
@@ -466,7 +535,7 @@ public virtual void RegisterNativeMembers ( | |
|
|
||
| protected bool TryRegisterNativeMembers ( | ||
| JniType nativeClass, | ||
| [DynamicallyAccessedMembers (MethodsAndPrivateNested)] | ||
| [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.AllMethods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] | ||
| Type type, | ||
| ReadOnlySpan<char> methods) | ||
| { | ||
|
|
@@ -485,7 +554,7 @@ protected bool TryRegisterNativeMembers ( | |
| #endif // NET | ||
| public virtual void RegisterNativeMembers ( | ||
| JniType nativeClass, | ||
| [DynamicallyAccessedMembers (MethodsAndPrivateNested)] | ||
| [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.AllMethods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] | ||
| Type type, | ||
| string? methods) | ||
| { | ||
|
|
@@ -497,7 +566,7 @@ public virtual void RegisterNativeMembers ( | |
| #endif // NET | ||
| protected bool TryRegisterNativeMembers ( | ||
| JniType nativeClass, | ||
| [DynamicallyAccessedMembers (MethodsAndPrivateNested)] | ||
| [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.AllMethods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] | ||
| Type type, | ||
| string? methods) | ||
| { | ||
|
|
@@ -511,8 +580,6 @@ protected bool TryRegisterNativeMembers ( | |
| // https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/PreserveRegistrations.cs#L85 | ||
| const string MarshalMethods = "'jni_marshal_methods' is preserved by the PreserveRegistrations trimmer step."; | ||
|
|
||
| [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = MarshalMethods)] | ||
| [UnconditionalSuppressMessage ("Trimming", "IL2075", Justification = MarshalMethods)] | ||
| bool TryLoadJniMarshalMethods ( | ||
| JniType nativeClass, | ||
| [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] | ||
|
|
@@ -605,4 +672,3 @@ bool FindAndCallRegisterMethod ( | |
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Behavioral change:
GetTypewas previously non-virtualand delegated toGetTypes().FirstOrDefault(), which walked through the overridableGetTypesForSimpleReferencepipeline (including array rank handling, generic wrapping, etc.).Now
GetTypeisvirtualand only checksGetBuiltInTypeForSimpleReference— it explicitly rejects array types (typeSignature.ArrayRank != 0).This is a significant behavioral split:
GetType(new JniTypeSignature("java/lang/String", arrayRank: 1))would return aJavaObjectArray<string>via theGetTypespipeline.nullfrom the base implementation.This seems intentional (the base now requires
ArrayRank == 0), and subclass overrides inJreTypeManagerand tests also enforce this. Just confirming this narrowing is deliberate. Callers relying onGetTypefor array types must now useGetTypesinstead.