Skip to content

Commit

Permalink
Fixed creating generic type with abstract type when it is has a defa…
Browse files Browse the repository at this point in the history
…ult constructor constraint
  • Loading branch information
Faolan-Rad committed Aug 2, 2024
1 parent 014632b commit cfeb12c
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private static bool SatisfiesConstraints(this Type genericVariable, SigTypeConte

if ((attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
{
if (!typeArg.HasExplicitOrImplicitPublicDefaultConstructor())
if (!typeArg.HasExplicitOrImplicitPublicDefaultConstructor() || typeArg.IsAbstract)
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/typedesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra

if ((specialConstraints & gpDefaultConstructorConstraint) != 0)
{
if (thArg.IsTypeDesc() || (!thArg.AsMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor()))
if (thArg.IsTypeDesc() || (!thArg.AsMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor() || thArg.IsAbstract()))
return FALSE;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public static bool CanSpecialize(Type type, GenericParameterAttributes attribute
if ((attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
{
// value types always have default constructors
if (!type.IsValueType && (type.GetConstructor(Type.EmptyTypes) == null))
if (!type.IsValueType && ((type.GetConstructor(Type.EmptyTypes) == null) || type.IsAbstract))
{
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/metadata/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/class-init.h>
#include <mono/metadata/class-inlines.h>
#include <mono/metadata/tokentype.h>
#include <mono/metadata/mono-basic-block.h>
#include <mono/metadata/attrdefs.h>
Expand Down Expand Up @@ -99,7 +100,7 @@ is_valid_generic_instantiation (MonoGenericContainer *gc, MonoGenericContext *co
if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && m_class_is_valuetype (paramClass))
return FALSE;

if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !m_class_is_valuetype (paramClass) && !mono_class_has_default_constructor (paramClass, TRUE))
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)))
return FALSE;

if (!param_info->constraints)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Reflection;
using Xunit;

public class X
{
public abstract class AbstractClassWithConstructor
{
public AbstractClassWithConstructor()
{
}
}

public static T TestConstructorMethod<T>() where T : new()
{
return new T();
}

public interface IItemCreator
{
public object CreateItem();
}

public sealed class ItemCreator<T> : IItemCreator where T : new()
{
public object CreateItem()
{
return new T();
}
}

[Fact]
public static int TestEntryPoint()
{
var ok = true;

Type type = null;
try
{
type = typeof(ItemCreator<>).MakeGenericType(typeof(AbstractClassWithConstructor))

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-arm64 Release AllSubsets_Mono_Minijit_RuntimeTests minijit)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/__w/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-x64 Release AllSubsets_Mono_Interpreter_RuntimeTests monointerpreter)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/Users/runner/work/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build coreclr Common Pri0 Test Build AnyOS AnyCPU checked)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/__w/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-x64 Release AllSubsets_Mono_LLVMAot_RuntimeTests llvmaot)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/__w/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-x64 Release AllSubsets_Mono_Minijit_RuntimeTests minijit)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/Users/runner/work/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release AllSubsets_Mono_RuntimeTests monointerpreter)

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/__w/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/Users/runner/work/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]

Check failure on line 43 in src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs

View check run for this annotation

Azure Pipelines / runtime

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs#L43

src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.cs(43,95): error CS1002: ; expected [/__w/1/s/src/tests/reflection/DisallowAbstractConstructors/DisallowAbstractConstructors.csproj]
}
catch
{
//Could check if it is the proper type of exception
}
if (type == null) {
Console.WriteLine("Wasn't able to load type as expected");
}
else
{
Console.WriteLine("Was able to make type which wasn't expected");
ok = false;
}

MethodInfo baseMethod = typeof(X).GetMethod(nameof(TestConstructorMethod), BindingFlags.Static | BindingFlags.Public);
if (baseMethod == null)
{
Console.WriteLine("baseMethod was null which wasn't expected");
ok = false;
}
MethodInfo method = null;
try
{
method = baseMethod.MakeGenericMethod(typeof(AbstractClassWithConstructor));
}
catch
{
//Could check if it is the proper method of exception
}
if (method == null)
{
Console.WriteLine("Wasn't able to load method as expected");
}
else
{
Console.WriteLine("Was able to make method which wasn't expected");
ok = false;
}

Console.WriteLine(ok ? "PASS" : "FAIL");
return ok ? 100 : -1;
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Compile Include="DisallowAbstractConstructors.cs" />
</ItemGroup>
</Project>

0 comments on commit cfeb12c

Please sign in to comment.