-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Related to dotnet/roslyn#55190
The following program throws CustomAttributeFormatException (using the generic-attributes feature compiler):
using System;
using System.Reflection;
class Attr<T> : Attribute { public Attr(T param) { } }
[Attr<string>("a")]
class Program
{
static void Main()
{
// below line throws 'System.Reflection.CustomAttributeFormatException : Binary format of the specified custom attribute was invalid.'
var attrs = CustomAttributeData.GetCustomAttributes(typeof(Program));
Console.Write(attrs);
}
}Importantly, if we change the constructor parameter type to string, we don't get an exception. It's also worth noting that if we declare a property of a type parameter type, then specify a value for it at the usage of the attribute, we decode it just fine.
The compiler produces this IL for the type Program:
.class private auto ansi beforefieldinit Program
extends [netstandard]System.Object
{
.custom instance void class Attr`1<string>::.ctor(!0) = (
01 00 01 61 00 00
)
// Methods
.method private hidebysig static
void Main () cil managed
{
// Method begins at RVA 0x2058
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldtoken Program
IL_0005: call class [netstandard]System.Type [netstandard]System.Type::GetTypeFromHandle(valuetype [netstandard]System.RuntimeTypeHandle)
IL_000a: call class [netstandard]System.Collections.Generic.IList`1<class [netstandard]System.Reflection.CustomAttributeData> [netstandard]System.Reflection.CustomAttributeData::GetCustomAttributes(class [netstandard]System.Reflection.MemberInfo)
IL_000f: call void [netstandard]System.Console::Write(object)
IL_0014: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x206e
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [netstandard]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class Program
§II.21 Custom attributes in ECMA 335 reads:
Custom attributes are declared using the directive .custom, followed by the method declaration for a type constructor, optionally followed by a Bytes in parentheses:
CustomDecl ::= Ctor [ '=''('Bytes')']The Ctor item represents a method declaration §II.15.4, specific for the case where the method's name is
.ctor.
It seems like for the feature "generic attributes" to work properly it is necessary for the Ctor item to represent a method reference rather than a method declaration, because the method in question could be contained in a constructed type. However, I am not sure I comprehend the finer points of the spec here.
Actually, I am not sure if what I am observing is a compiler bug, or a coreclr bug, or a spec issue. Poking around the compiler's emit of the attribute constructor, it does seem to be simply producing a reference to the constructed method symbol.