Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some System.Reflection.Emit implementations of Type.IsByRefLike still throw NotSupportedException: "Derived classes must provide an implementation" #91532

Open
stakx opened this issue Sep 4, 2023 · 6 comments
Labels
area-System.Reflection.Emit bug help wanted [up-for-grabs] Good issue for external contributors
Milestone

Comments

@stakx
Copy link
Contributor

stakx commented Sep 4, 2023

Description

Certain System.Reflection.Emit (SRE) subclasses of Type appear to be missing an implementation for the Type.IsByRefLike property. When queried, a NotSupportedException ("Derived classes must provide an implementation") gets thrown when they should probably just return false.

I've so far found two such types that both seem to involve generics: System.Reflection.Emit.TypeBuilderInstantiation and System.Reflection.Emit.SymbolType.

Could it be that these two types were overlooked back in #34846?

Reproduction Steps

Here is one code example that reproduces the problem for System.Reflection.Emit.TypeBuilderInstantiation:

var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("A"), AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("A");
var genericTypeBuilder = moduleBuilder.DefineType("C", TypeAttributes.Class);
_ = genericTypeBuilder.DefineGenericParameters("T");
var closedGenericTypeBuilder = genericTypeBuilder.MakeGenericType(typeof(object));
Console.WriteLine(closedGenericTypeBuilder.GetType().FullName);
Console.WriteLine(closedGenericTypeBuilder.IsByRefLike);

(I haven't yet been able to create a short code repro for System.Reflection.Emit.SymbolType, but will add one if I can figure it out.)

Expected behavior

Prints the following to the console:

System.Reflection.Emit.TypeBuilderInstantiation
False

Actual behavior

Prints the following to the console:

System.Reflection.Emit.TypeBuilderInstantiation
Unhandled exception. System.NotSupportedException: Derived classes must provide an implementation.
   at System.Type.get_IsByRefLike()
   at Program.Main ...

The exception is caused by the IsByRefLike query in the last line of code.

Regression?

I don't think this is a regression, since the same error also occurs on older .NET runtimes (e. g. .NET Core 3.1). It appears like this simply hasn't been implemented yet at all.

Known Workarounds

I don't know of any workaround short of wrapping IsByRefLike queries in an extension method that catches the exception and converts it to false, then calling that extension method instead of using IsByRefLike directly:

static bool IsByRefLikeSafe(this Type type)
{
    try
    {
        return type.IsByRefLike;
    }
    catch (NotSupportedException)
    {
        return false;
    }
}

Configuration

  • I've run the code repro on the following runtimes:
    • .NET Core 3.1
    • .NET 6
    • .NET 7
  • OS: Windows 11 Pro (22H2), build 22621.2134
  • Architecture: x64

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 4, 2023
@ghost
Copy link

ghost commented Sep 4, 2023

Tagging subscribers to this area: @dotnet/area-system-reflection-emit
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Certain System.Reflection.Emit (SRE) subclasses of Type appear to be missing an implementation for the Type.IsByRef property. When queried, a NotSupportedException ("Derived classes must provide an implementation") gets thrown when they should probably just return false.

I've so far found two such types that both seem to involve generics: System.Reflection.Emit.TypeBuilderInstantiation and System.Reflection.Emit.SymbolType.

Could it be that these two types were overlooked back in #34846?

Reproduction Steps

Here is one code example that reproduces the problem for System.Reflection.Emit.TypeBuilderInstantiation:

var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("A"), AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("A");
var genericTypeBuilder = moduleBuilder.DefineType("C", TypeAttributes.Class);
_ = genericTypeBuilder.DefineGenericParameters("T");
var closedGenericTypeBuilder = genericTypeBuilder.MakeGenericType(typeof(object));
Console.WriteLine(closedGenericTypeBuilder.GetType().FullName);
Console.WriteLine(closedGenericTypeBuilder.IsByRefLike);

(I haven't yet been able to create a short code repro for System.Reflection.Emit.SymbolType, but will add one if I can figure it out.)

Expected behavior

Prints the following to the console:

System.Reflection.Emit.TypeBuilderInstantiation
False

Actual behavior

Prints the following to the console:

System.Reflection.Emit.TypeBuilderInstantiation
Unhandled exception. System.NotSupportedException: Derived classes must provide an implementation.
   at System.Type.get_IsByRefLike()
   at Program.Main ...

The exception is caused by the IsByRefLike query in the last line of code.

Regression?

I don't think this is a regression, since the same error also occurs on older .NET runtimes (e. g. .NET Core 3.1). It appears like this simply hasn't been implemented yet at all.

Known Workarounds

I don't know of any workaround short of wrapping IsByRefLike queries in an extension method that catches the exception and converts it to false, then calling that extension method instead of using IsByRefLike directly:

static bool IsByRefLikeSafe(this Type type)
{
    try
    {
        return type.IsByRefLike;
    }
    catch (NotSupportedException)
    {
        return false;
    }
}

Configuration

  • I've run the code repro on the following runtimes:
    • .NET Core 3.1
    • .NET 6
    • .NET 7
  • OS: Windows 11 Pro (22H2), build 22621.2134
  • Architecture: x64

Other information

No response

Author: stakx
Assignees: -
Labels:

area-System.Reflection.Emit

Milestone: -

@steveharter steveharter added bug and removed untriaged New issue has not been triaged by the area owner labels Sep 5, 2023
@steveharter steveharter added this to the Future milestone Sep 5, 2023
@steveharter steveharter added the help wanted [up-for-grabs] Good issue for external contributors label Sep 5, 2023
@karakasa
Copy link
Contributor

I went through the codebase and found 4 types not implementing IsByRefLike. Should they all return false?

System.Reflection.Emit.TypeBuilderInstantiation
System.Reflection.Emit.SymbolType
System.Reflection.Emit.TypeBuilderImpl
System.Reflection.Emit.GenericTypeParameterBuilderImpl

@stakx
Copy link
Contributor Author

stakx commented Sep 22, 2023

I strongly suspect that the last one (GenericTypeParameterBuilderImpl) at the very least should return false, since by-ref-like types may not be used as generic type arguments... if that's what this class represents.

@MichalPetryka
Copy link
Contributor

since by-ref-like types may not be used as generic type arguments

Worth noting that this might change, cc @jaredpar for progress on that

@jaredpar
Copy link
Member

In terms of updates on ref struct generic arguments ... for a long time I thought that effectively three features were tied together design wise: ref struct generic arguments, ref struct implementing interfaces and ref struct as ref fields.

During the .NET 8 timeframe I was convinced that we can separate the design for ref struct as ref fields. That's fortunate because it's probably the one with the most open questions. Basically design issues where there are presently no good answers. The other two features have some challenges but they're more in realm of deciding which design is best. If we committed to the feature I'm pretty confident we could ship it in a .NET release.

So at this point it's more a question of where it fits in the priority ranking.

@buyaa-n
Copy link
Member

buyaa-n commented Nov 1, 2023

I went through the codebase and found 4 types not implementing IsByRefLike. Should they all return false?

System.Reflection.Emit.TypeBuilderInstantiation
System.Reflection.Emit.SymbolType
System.Reflection.Emit.TypeBuilderImpl
System.Reflection.Emit.GenericTypeParameterBuilderImpl

Looks they should all return false, though I would leave TypeBuilderImpl and GenericTypeParameterBuilderImpl out of this because they are new types that are not complete (many other unimplemented APIs not only IsByRefLike) and not exposed publicly yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Reflection.Emit bug help wanted [up-for-grabs] Good issue for external contributors
Projects
None yet
Development

No branches or pull requests

6 participants