Skip to content

Commit 1a305e6

Browse files
Faolan-Radivdiazsa
andauthored
Fixed creating generic type with abstract type when it is has a default constractor constrant (#101963)
* Fixed creating generic type with abstract type when it is has a default constructor constraint * Fix missing ; in test. --------- Co-authored-by: Ivan Diaz <[email protected]>
1 parent 78def3e commit 1a305e6

File tree

6 files changed

+98
-4
lines changed

6 files changed

+98
-4
lines changed

src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/TypeLoader/ConstraintValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private static bool SatisfiesConstraints(this Type genericVariable, SigTypeConte
3838

3939
if ((attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
4040
{
41-
if (!typeArg.HasExplicitOrImplicitPublicDefaultConstructor())
41+
if (!typeArg.HasExplicitOrImplicitPublicDefaultConstructor() || typeArg.IsAbstract)
4242
return false;
4343
}
4444

src/coreclr/vm/typedesc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,7 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra
14551455

14561456
if ((specialConstraints & gpDefaultConstructorConstraint) != 0)
14571457
{
1458-
if (thArg.IsTypeDesc() || (!thArg.AsMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor()))
1458+
if (thArg.IsTypeDesc() || (!thArg.AsMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor() || thArg.IsAbstract()))
14591459
return FALSE;
14601460
}
14611461

src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/GenericServices.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public static bool CanSpecialize(Type type, GenericParameterAttributes attribute
178178
if ((attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
179179
{
180180
// value types always have default constructors
181-
if (!type.IsValueType && (type.GetConstructor(Type.EmptyTypes) == null))
181+
if (!type.IsValueType && ((type.GetConstructor(Type.EmptyTypes) == null) || type.IsAbstract))
182182
{
183183
return false;
184184
}

src/mono/mono/metadata/verify.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <mono/metadata/metadata-internals.h>
2525
#include <mono/metadata/class-internals.h>
2626
#include <mono/metadata/class-init.h>
27+
#include <mono/metadata/class-inlines.h>
2728
#include <mono/metadata/tokentype.h>
2829
#include <mono/metadata/mono-basic-block.h>
2930
#include <mono/metadata/attrdefs.h>
@@ -99,7 +100,7 @@ is_valid_generic_instantiation (MonoGenericContainer *gc, MonoGenericContext *co
99100
if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && m_class_is_valuetype (paramClass))
100101
return FALSE;
101102

102-
if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !m_class_is_valuetype (paramClass) && !mono_class_has_default_constructor (paramClass, TRUE))
103+
if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !m_class_is_valuetype (paramClass) && (!mono_class_has_default_constructor (paramClass, TRUE) || mono_class_is_abstract (paramClass)))
103104
return FALSE;
104105

105106
if (!param_info->constraints)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Reflection;
6+
using Xunit;
7+
8+
public class X
9+
{
10+
public abstract class AbstractClassWithConstructor
11+
{
12+
public AbstractClassWithConstructor()
13+
{
14+
}
15+
}
16+
17+
public static T TestConstructorMethod<T>() where T : new()
18+
{
19+
return new T();
20+
}
21+
22+
public interface IItemCreator
23+
{
24+
public object CreateItem();
25+
}
26+
27+
public sealed class ItemCreator<T> : IItemCreator where T : new()
28+
{
29+
public object CreateItem()
30+
{
31+
return new T();
32+
}
33+
}
34+
35+
[Fact]
36+
public static int TestEntryPoint()
37+
{
38+
var ok = true;
39+
40+
Type type = null;
41+
try
42+
{
43+
type = typeof(ItemCreator<>).MakeGenericType(typeof(AbstractClassWithConstructor));
44+
}
45+
catch
46+
{
47+
//Could check if it is the proper type of exception
48+
}
49+
if (type == null) {
50+
Console.WriteLine("Wasn't able to load type as expected");
51+
}
52+
else
53+
{
54+
Console.WriteLine("Was able to make type which wasn't expected");
55+
ok = false;
56+
}
57+
58+
MethodInfo baseMethod = typeof(X).GetMethod(nameof(TestConstructorMethod), BindingFlags.Static | BindingFlags.Public);
59+
if (baseMethod == null)
60+
{
61+
Console.WriteLine("baseMethod was null which wasn't expected");
62+
ok = false;
63+
}
64+
MethodInfo method = null;
65+
try
66+
{
67+
method = baseMethod.MakeGenericMethod(typeof(AbstractClassWithConstructor));
68+
}
69+
catch
70+
{
71+
//Could check if it is the proper method of exception
72+
}
73+
if (method == null)
74+
{
75+
Console.WriteLine("Wasn't able to load method as expected");
76+
}
77+
else
78+
{
79+
Console.WriteLine("Was able to make method which wasn't expected");
80+
ok = false;
81+
}
82+
83+
Console.WriteLine(ok ? "PASS" : "FAIL");
84+
return ok ? 100 : -1;
85+
}
86+
}
87+
88+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<ItemGroup>
3+
<Compile Include="DisallowAbstractConstructors.cs" />
4+
</ItemGroup>
5+
</Project>

0 commit comments

Comments
 (0)