KT-54363 Allow using reified types for catch parameters #5194
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Allow using reified types for catch parameters
For more context read the comment in the YouTrack Issue.
Kotlin/JVM
In Bytecode catch clauses are described by two things: an entry in the exception table and a handler entrypoint in the instructions.
The entry consists out of three labels and type. The first two labels describe the effective range, where exceptions of the specified type are to be caught. If caught, the exception is pushed onto the stack and the execution jumps to the third label. The third label is the handler. Its responsibility its to the receive and store the exception on top of the stack. It is not to be confused with the catch body, which follows with the next label.
The goal is to store information about where type parameters are and replace them with the actual type once known.
The simplest solution would be to store the type parameter in the exception table itself. While the type is a string, it cannot be used for storing the type parameter. The type is loaded eagerly during class initialization. Storing for example
[T?
would lead to a ClassNotFound. This means, that Bytecode does not allow for the exception table to be used for storing a reification markers directly.Instead, I opted to reuse the current reification marker system targeted at the
ASTORE
instruction in the handler.The
ASTORE
instruction can be directly traced back to its entry in the exception table via the label of the handler.During inlining, if the type is known, the instruction is left as is. Instead, the type in the exception table is replaced by the actual type and the marker is removed. If the type parameter is just another type parameter, the value of
LDC
instruction is modified accordingly instead, like it is done in the case of all the others reified operations.Kotlin/Other
As suspected by Roman Elizarov in the issue, the IR inliner seems to be able to correctly inline the catch clause parameter. All of my test cases worked out of the box, once I had disabled the error diagnostics.
Diagnostics
I updated the diagnostics code to only forbid reified types in catch clauses in versions lower than 2.0 and changed the messages accordingly. This way, red code will be preserved for older version.