Skip to content

Commit

Permalink
Annotate CreateInstanceForAnotherGenericParameter as PublicParameterl…
Browse files Browse the repository at this point in the history
…essConstructor (dotnet#50390)

This allows private constructors on the Types to be trimmed.

Fix dotnet#50353
  • Loading branch information
eerhardt authored Mar 30, 2021
1 parent 260397c commit ec0bb49
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 6 deletions.
15 changes: 13 additions & 2 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,13 @@ internal static bool HasElementType(RuntimeType type)
return outHandles;
}

internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] RuntimeType type, RuntimeType genericParameter)
internal static object CreateInstanceForAnotherGenericParameter(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] RuntimeType type,
RuntimeType genericParameter)
{
Debug.Assert(type.GetConstructor(Type.EmptyTypes) is ConstructorInfo c && c.IsPublic,
$"CreateInstanceForAnotherGenericParameter requires {nameof(type)} to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.");

object? instantiatedObject = null;

IntPtr typeHandle = genericParameter.GetTypeHandleInternal().Value;
Expand All @@ -224,8 +229,14 @@ internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAcce
return instantiatedObject!;
}

internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] RuntimeType type, RuntimeType genericParameter1, RuntimeType genericParameter2)
internal static object CreateInstanceForAnotherGenericParameter(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] RuntimeType type,
RuntimeType genericParameter1,
RuntimeType genericParameter2)
{
Debug.Assert(type.GetConstructor(Type.EmptyTypes) is ConstructorInfo c && c.IsPublic,
$"CreateInstanceForAnotherGenericParameter requires {nameof(type)} to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.");

object? instantiatedObject = null;

IntPtr* pTypeHandles = stackalloc IntPtr[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public override int GetHashCode() =>
[Serializable]
internal sealed partial class EnumComparer<T> : Comparer<T>, ISerializable where T : struct, Enum
{
internal EnumComparer() { }
public EnumComparer() { }

// Used by the serialization engine.
private EnumComparer(SerializationInfo info, StreamingContext context) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public override int GetHashCode() =>
// Needs to be public to support binary serialization compatibility
public sealed partial class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct, Enum
{
internal EnumEqualityComparer() { }
public EnumEqualityComparer() { }

// This is used by the serialization engine.
private EnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1835,11 +1835,15 @@ public override Type[] GetGenericParameterConstraints()
return constraints ?? Type.EmptyTypes;
}

internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type genericType, RuntimeType genericArgument)
internal static object CreateInstanceForAnotherGenericParameter(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type genericType,
RuntimeType genericArgument)
{
var gt = (RuntimeType)MakeGenericType(genericType, new Type[] { genericArgument });
RuntimeConstructorInfo? ctor = gt.GetDefaultConstructor();
if (ctor is null)

// CreateInstanceForAnotherGenericParameter requires type to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.
if (ctor is null || !ctor.IsPublic)
throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, gt));

return ctor.InternalInvoke(null, null, wrapExceptions: true)!;
Expand Down

0 comments on commit ec0bb49

Please sign in to comment.