Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 3 additions & 2 deletions src/coreclr/vm/genericdict.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,8 @@ Dictionary::PopulateEntry(
th = th.GetMethodTable()->GetMethodTableMatchingParentClass(declaringType.AsMethodTable());
}

th.GetMethodTable()->EnsureInstanceActive();
PTR_MethodTable pMT = th.IsByRef() ? th.GetTypeParam().GetMethodTable() : th.GetMethodTable();
pMT->EnsureInstanceActive();

result = (CORINFO_GENERIC_HANDLE)th.AsPtr();
break;
Expand Down Expand Up @@ -992,7 +993,7 @@ Dictionary::PopulateEntry(
if (nonExpansive)
return NULL;

pOwnerMT = ownerType.GetMethodTable();
pOwnerMT = ownerType.IsByRef() ? ownerType.GetTypeParam().GetMethodTable() : ownerType.GetMethodTable();
_ASSERTE(pOwnerMT != NULL);

IfFailThrow(ptr.GetData(&methodFlags));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@

using Xunit;

struct Struct { }
struct Struct
{
public Type Value;
private void SetType(Type type) => Value = type;
private void SetType<T>() => Value = typeof(T);
}

struct GenericStruct<T>
{
public Type Value;
private void SetType(Type type) => Value = type;
private void SetType<U>() => Value = typeof(U);
}

interface I1 { }

Expand Down Expand Up @@ -112,6 +124,12 @@ static class Accessors<V>
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "CreateMessage")]
public extern static string CreateMessage(GenericBase<V> b, V v);

[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetType")]
public extern static void SetType(ref GenericStruct<V> s, Type type);

[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetType")]
public extern static void SetType<U>(ref GenericStruct<V> s);

[UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "ElementType")]
public extern static Type ElementType(MyList<V> l);

Expand All @@ -128,6 +146,15 @@ static class Accessors<V>
public extern static ref V GetPrivateStaticField(MyList<V> d);
}

static class Accessors
{
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetType")]
public extern static void SetType<U>(ref Struct s);

[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetType")]
public extern static void SetType(ref Struct s, Type type);
}

[Fact]
public static void Verify_Generic_AccessStaticFieldClass()
{
Expand Down Expand Up @@ -459,6 +486,68 @@ public static void Verify_Generic_GenericTypeGenericStaticMethod()
}
}

[Fact]
public static void Verify_Generic_Structs()
{
Console.WriteLine($"Running {nameof(Verify_Generic_Structs)}");

{
Struct s = new();
Accessors.SetType(ref s, typeof(int));
Assert.Equal(typeof(int), s.Value);
Accessors.SetType(ref s, typeof(string));
Assert.Equal(typeof(string), s.Value);
Accessors.SetType(ref s, typeof(Struct));
Assert.Equal(typeof(Struct), s.Value);
Accessors.SetType(ref s, typeof(GenericStruct<int>));
Assert.Equal(typeof(GenericStruct<int>), s.Value);
Accessors.SetType(ref s, typeof(GenericStruct<string>));
Assert.Equal(typeof(GenericStruct<string>), s.Value);
}

{
Struct s = new();
Accessors.SetType<int>(ref s);
Assert.Equal(typeof(int), s.Value);
Accessors.SetType<string>(ref s);
Assert.Equal(typeof(string), s.Value);
Accessors.SetType<Struct>(ref s);
Assert.Equal(typeof(Struct), s.Value);
Accessors.SetType<GenericStruct<int>>(ref s);
Assert.Equal(typeof(GenericStruct<int>), s.Value);
Accessors.SetType<GenericStruct<string>>(ref s);
Assert.Equal(typeof(GenericStruct<string>), s.Value);
}

{
GenericStruct<int> s = new();
Accessors<int>.SetType(ref s, typeof(int));
Assert.Equal(typeof(int), s.Value);
Accessors<int>.SetType<string>(ref s);
Assert.Equal(typeof(string), s.Value);
Accessors<int>.SetType<Struct>(ref s);
Assert.Equal(typeof(Struct), s.Value);
Accessors<int>.SetType<GenericStruct<int>>(ref s);
Assert.Equal(typeof(GenericStruct<int>), s.Value);
Accessors<int>.SetType<GenericStruct<string>>(ref s);
Assert.Equal(typeof(GenericStruct<string>), s.Value);
}

{
GenericStruct<string> s = new();
Accessors<string>.SetType(ref s, typeof(int));
Assert.Equal(typeof(int), s.Value);
Accessors<string>.SetType<string>(ref s);
Assert.Equal(typeof(string), s.Value);
Accessors<string>.SetType<Struct>(ref s);
Assert.Equal(typeof(Struct), s.Value);
Accessors<string>.SetType<GenericStruct<int>>(ref s);
Assert.Equal(typeof(GenericStruct<int>), s.Value);
Accessors<string>.SetType<GenericStruct<string>>(ref s);
Assert.Equal(typeof(GenericStruct<string>), s.Value);
}
}

class MethodWithConstraints
{
private string M<T, U>() where T : U, I2<T>
Expand Down
Loading