Skip to content

Commit ec0bb49

Browse files
authored
Annotate CreateInstanceForAnotherGenericParameter as PublicParameterlessConstructor (#50390)
This allows private constructors on the Types to be trimmed. Fix #50353
1 parent 260397c commit ec0bb49

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,13 @@ internal static bool HasElementType(RuntimeType type)
209209
return outHandles;
210210
}
211211

212-
internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] RuntimeType type, RuntimeType genericParameter)
212+
internal static object CreateInstanceForAnotherGenericParameter(
213+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] RuntimeType type,
214+
RuntimeType genericParameter)
213215
{
216+
Debug.Assert(type.GetConstructor(Type.EmptyTypes) is ConstructorInfo c && c.IsPublic,
217+
$"CreateInstanceForAnotherGenericParameter requires {nameof(type)} to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.");
218+
214219
object? instantiatedObject = null;
215220

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

227-
internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] RuntimeType type, RuntimeType genericParameter1, RuntimeType genericParameter2)
232+
internal static object CreateInstanceForAnotherGenericParameter(
233+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] RuntimeType type,
234+
RuntimeType genericParameter1,
235+
RuntimeType genericParameter2)
228236
{
237+
Debug.Assert(type.GetConstructor(Type.EmptyTypes) is ConstructorInfo c && c.IsPublic,
238+
$"CreateInstanceForAnotherGenericParameter requires {nameof(type)} to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.");
239+
229240
object? instantiatedObject = null;
230241

231242
IntPtr* pTypeHandles = stackalloc IntPtr[]

src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public override int GetHashCode() =>
120120
[Serializable]
121121
internal sealed partial class EnumComparer<T> : Comparer<T>, ISerializable where T : struct, Enum
122122
{
123-
internal EnumComparer() { }
123+
public EnumComparer() { }
124124

125125
// Used by the serialization engine.
126126
private EnumComparer(SerializationInfo info, StreamingContext context) { }

src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public override int GetHashCode() =>
180180
// Needs to be public to support binary serialization compatibility
181181
public sealed partial class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct, Enum
182182
{
183-
internal EnumEqualityComparer() { }
183+
public EnumEqualityComparer() { }
184184

185185
// This is used by the serialization engine.
186186
private EnumEqualityComparer(SerializationInfo information, StreamingContext context) { }

src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,11 +1835,15 @@ public override Type[] GetGenericParameterConstraints()
18351835
return constraints ?? Type.EmptyTypes;
18361836
}
18371837

1838-
internal static object CreateInstanceForAnotherGenericParameter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type genericType, RuntimeType genericArgument)
1838+
internal static object CreateInstanceForAnotherGenericParameter(
1839+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type genericType,
1840+
RuntimeType genericArgument)
18391841
{
18401842
var gt = (RuntimeType)MakeGenericType(genericType, new Type[] { genericArgument });
18411843
RuntimeConstructorInfo? ctor = gt.GetDefaultConstructor();
1842-
if (ctor is null)
1844+
1845+
// CreateInstanceForAnotherGenericParameter requires type to have a public parameterless constructor so it can be annotated for trimming without preserving private constructors.
1846+
if (ctor is null || !ctor.IsPublic)
18431847
throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, gt));
18441848

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

0 commit comments

Comments
 (0)