"Not a parameterized type!" when indexing a record with a compact constructor and an annotated parameterized types
nithril opened this issue · comments
Hello,
Considering this java record with a compact constructor:
public record MyRecord(List<@NotEmpty String> list) {
public MyRecord {
list = null;
}
}
When indexing the record
Indexer indexer = new Indexer();
indexer.indexClass(MyRecord.class);
Jandex throws a java.lang.IllegalArgumentException: Not a parameterized type!
The error occurs when parsing a type annotation on the record constructor. If the constructor is removed, the class file is parsed just fine. This is how javap -v -p
shows the constructor:
public test.MyRecord(java.util.List<java.lang.String>);
descriptor: (Ljava/util/List;)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Record."<init>":()V
4: aload_0
5: aload_1
6: putfield #7 // Field list:Ljava/util/List;
9: return
LineNumberTable:
line 6: 0
line 7: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Ltest/MyRecord;
0 10 1 list Ljava/util/List;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 10 1 list Ljava/util/List<Ljava/lang/String;>;
MethodParameters:
Name Flags
list
Signature: #37 // (Ljava/util/List<Ljava/lang/String;>;)V
RuntimeVisibleTypeAnnotations:
0: #28(): FIELD, location=[TYPE_ARGUMENT(0)]
test.NotEmpty
It seems to me that the target_type
value of the type annotation is wrong -- it's FIELD
(0x13), but it should be METHOD_PARAMETER
(0x16). Congrats, you found a bug in javac :-)
Jandex should be able to ignore that. I'll try to figure something out.
Also, it seems the problem only appears with a compact constructor. As a workaround, you can use a normal constructor instead of a compact one:
public record MyRecord(List<@NotEmpty String> list) {
public MyRecord(List<@NotEmpty String> list) {
this.list = list;
}
}
It seems to me that the target_type value of the type annotation is wrong -- it's FIELD (0x13), but it should be METHOD_PARAMETER (0x16). Congrats, you found a bug in javac :-)
The merit goes to you :)
Are you sure it should be METHOD_PARAMETER
? AFAIU compact constructor is operating on the fields of the class
Actually a compact constructor has implicitly declared parameters, per the JLS (8.10.4.2. Compact Canonical Constructors). In this case, there's just one parameter, and its type contains a type annotation.
The record also implicitly declares a component field (8.10.3. Record Members). That field's type also contains a type annotation, and it seems to me that javac simply takes the type of the field it generated and pushes it into the constructor parameter list. Which is fine, until there are type annotations :-)
EDIT: the record also implicitly declares an accessor method, but type annotations on its return type seem to be correct.
In any case, I have a workaround for Jandex that will just drop the invalid type annotation.
Done in #219. Thanks for the report!