Skip to content

[Java.Interop] Generic Type Definitions are allowed #1336

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

Merged
merged 1 commit into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Java.Interop/Java.Interop/JavaObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public JavaObject (ref JniObjectReference reference, JniObjectReferenceOptions o
Construct (ref reference, options);
}

[global::Java.Interop.JniConstructorSignature ("()V")]
public unsafe JavaObject ()
: this (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
{
Expand Down
5 changes: 1 addition & 4 deletions src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,7 @@ public JniTypeSignature GetTypeSignature (Type type)

if (type == null)
throw new ArgumentNullException (nameof (type));
if (type.ContainsGenericParameters)
throw new NotSupportedException ($"'{type}' contains a generic type definition. This is not supported.");


type = GetUnderlyingType (type, out int rank);

Expand Down Expand Up @@ -183,8 +182,6 @@ public IEnumerable<JniTypeSignature> GetTypeSignatures (Type type)

if (type == null)
yield break;
if (type.ContainsGenericParameters)
throw new NotSupportedException ($"'{type}' contains a generic type definition. This is not supported.");

type = GetUnderlyingType (type, out int rank);

Expand Down
24 changes: 23 additions & 1 deletion tests/Java.Interop-Tests/Java.Interop/JniTypeManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public void GetTypeSignature_Type ()
Assert.Throws<ArgumentException>(() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (int[,])));
Assert.Throws<ArgumentException>(() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (int[,][])));
Assert.Throws<ArgumentException>(() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (int[][,])));
Assert.Throws<NotSupportedException>(() => JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (Action<>)));
Assert.AreEqual (null, JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (JniRuntimeTest)).SimpleReference);

AssertGetJniTypeInfoForType (typeof (string), "java/lang/String", false, 0);
Expand Down Expand Up @@ -91,6 +90,11 @@ public void GetTypeSignature_Type ()
// Note: dotnet/android@5c23bcda updates Java.Lang.Object to inherit JavaObject; this is not enough,
// as `<GenerateJavaStubs/>` only processes assemblies if they reference Mono.Android.dll.
AssertGetJniTypeInfoForType (typeof (GenericHolder<int>), GenericHolder<int>.JniTypeName, false, 0);

// XAJavaInterop1 Java Callable Wrappers, as used in dotnet/android, may contain
// `Runtime.register("Java.InteropTests.GenericHolder`1, Mono.Android-Tests", …)`,
// which results in a generic type definition. Permit this.
AssertGetJniTypeInfoForType (typeof (GenericHolder<>), GenericHolder<int>.JniTypeName, false, 0);
#endif // !__ANDROID__
}

Expand Down Expand Up @@ -215,6 +219,24 @@ public void GetTypeSignature ()
Assert.AreEqual (typeof (string), GetTypeForSimpleReference ("java/lang/String"));
Assert.AreEqual (null, GetTypeForSimpleReference ("com/example/does/not/exist"));
}

[Test]
public void CanCreateGenericHolder ()
{
using var holder = new GenericHolder<int> ();
}

[Test]
public unsafe void CannotCreateGenericHolderFromJava ()
{
var signature = JniRuntime.CurrentRuntime.TypeManager.GetTypeSignature (typeof (GenericHolder<>));
using var type = new JniType (signature.Name);
var ctor = type.GetConstructor ("()V");
var instance = type.AllocObject ();

Assert.Throws<NotSupportedException>(() =>
JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod (instance, type.PeerReference, ctor));
}
}

[JniTypeSignature (JniTypeName)]
Expand Down