Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,24 @@ private partial bool TryHandleIntrinsic(
}
}
}
else if (typeInstantiated.Instantiation.IsConstrainedToBeReferenceTypes())
{
// This will always succeed thanks to the runtime type loader
}
else
{
triggersWarning = true;
}
if (typeInstantiated.Instantiation.IsConstrainedToBeReferenceTypes())
{
// This will always succeed thanks to the runtime type loader
}
else
{
triggersWarning = true;
}

// This should technically be in the IsConstrainedToBeReferenceTypes branch above
// but we have trim warning suppressions in dotnet/runtime and elsewhere that rely on the implementation
// detail that reference type instantiations will work, even if the generic is not
// constrained to be a reference type.
// MarkType will try to come up with a reference type type loader template.
_reflectionMarker.MarkType(_diagnosticContext.Origin, typeInstantiated, "MakeGenericType");
}
}
else if (value == NullValue.Instance)
{
Expand Down
56 changes: 56 additions & 0 deletions src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private static int Main()
Test105034Regression.Run();
TestMethodsNeededFromNativeLayout.Run();
TestFieldAndParamMetadata.Run();
TestActivationWithoutConstructor.Run();
TestNestedMakeGeneric.Run();

//
// Mostly functionality tests
Expand Down Expand Up @@ -859,6 +861,60 @@ public static void Run()
}
}

class TestActivationWithoutConstructor
{
public static void Run()
{
{
object o = Activator.CreateInstance(typeof(StructForCreateInstanceDirect<>).MakeGenericType(GetTheType()));
if (!o.ToString().Contains(nameof(StructForCreateInstanceDirect<>)))
throw new Exception();
}

{
object o = CreateInstance(typeof(StructForCreateInstanceIndirect<>).MakeGenericType(GetTheType()));
if (!o.ToString().Contains(nameof(StructForCreateInstanceIndirect<>)))
throw new Exception();

static object CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type t)
=> Activator.CreateInstance(t);
}

{
object o = RuntimeHelpers.GetUninitializedObject(typeof(StructForGetUninitializedObject<>).MakeGenericType(GetTheType()));
if (!o.ToString().Contains(nameof(StructForGetUninitializedObject<>)))
throw new Exception();
}

[MethodImpl(MethodImplOptions.NoInlining)]
static Type GetTheType() => typeof(Atom);
}

class Atom;

struct StructForCreateInstanceDirect<T> where T : class;
struct StructForCreateInstanceIndirect<T> where T : class;
struct StructForGetUninitializedObject<T> where T : class;
}

class TestNestedMakeGeneric
{
class Outie<T> where T : class;
class Innie<T> where T : class;
class Atom;

public static void Run()
{
Type inner = typeof(Innie<>).MakeGenericType(GetAtom());
Type outer = typeof(Outie<>).MakeGenericType(inner);

Console.WriteLine(Activator.CreateInstance(outer));

[MethodImpl(MethodImplOptions.NoInlining)]
static Type GetAtom() => typeof(Atom);
}
}

class TestCreateDelegate
{
internal class Greeter
Expand Down
Loading