apache / apache/royale-compiler

ClassCastException compiling [Bindable] classes whose public var implements interface accessors (getter/setter)

Open
#251 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
113
Forks
54
PR merge metrics
No merged PRs in 30d

Description

Building with a 1.0.1-SNAPSHOT build of the Apache Royale compiler (with the "function type expressions" feature enabled), the compile-js process throws an internal java.lang.ClassCastException when a [Bindable] class implements an interface accessor pair (getter/setter) with a single public var.

```
java.lang.ClassCastException
at FunctionDefinition.resolveReturnType(FunctionDefinition.java:227)
at FunctionDefinition.hasCompatibleSignature(FunctionDefinition.java:607)
at InterfaceDefinition.validateClassImplementsAllMethods(InterfaceDefinition.java:543)
```

Steps to reproduce

Declare an interface with an accessor pair:
```
public interface IModel
{
function get currentSubView():String;
function set currentSubView(value:String):void;
}
```
Implement it with a [Bindable] class and a public var:
```
[Bindable]
public class Model implements IModel
{
public var currentSubView:String = "";
}
```
Compile for JSRoyale (js target) with the 1.0.1-SNAPSHOT SDK.

Expected result:
Compiles without errors: in AS3 a public var counts as both a getter and a setter, so it correctly satisfies the accessor pair.

Actual result:
ClassCastException in FunctionDefinition.resolveReturnType (line 227).

Possible cause:
My reading of the code points to the following, though I'm not fully certain:

For [Bindable] variables, the compiler generates synthetic getters/setters (SyntheticBindableGetterDefinition/SyntheticBindableSetterDefinition) whose AST node is the VariableNode (see BaseTypedDefinitionNode.buildBindableGetter()/buildBindableSetter() → setNode(this)).
In FunctionDefinition.resolveReturnType() (block introduced by commit 7405d89e0, "function type expressions"), the cast IFunctionNode funcNode = (IFunctionNode) getNode(); assumes every FunctionDefinition is backed by a function node; for synthetic bindable accessors the node is a VariableNode, which is not an IFunctionNode.
The check added later in commit 72a4a2826 (!(funcNode instanceof IAccessorNode)) covers real accessors (get/set written in code), but not synthetic bindable accessors, and it also runs after the cast.

Possible approach (my opinion, to be validated):
I'm not sure what the best way to solve this is, but my first hypothesis would be to guard the cast with instanceof IFunctionNode before performing it in FunctionDefinition.resolveReturnType() (lines 225-247), so that definitions backed by a VariableNode simply skip the block:

```
if (project.getAllowStrictFunctionTypes())
{
// synthetic accessors ([Bindable] vars) may be backed by a non-function node
if (getNode() instanceof IFunctionNode)
{
IFunctionNode funcNode = (IFunctionNode) getNode();
if (!(funcNode instanceof IAccessorNode))
{
// ...function type expression metadata...
}
}
}
```
A cleaner solution will probably occur to you (for example, handling it when the synthetic accessors are created, or as part of the function type expressions logic itself), and in any case I haven't thoroughly validated all the cases. What do you think? Am I overlooking anything?

Environment:
SDK: Apache Royale 1.0.1-SNAPSHOT (built from the royale-compiler sources)
Maven 3.9.9, Java with the compiler built from source
Full build log attached to the issue.
[debugroyale.log](https://github.com/user-attachments/files/31161908/debugroyale.log)

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in FunctionDefinition.java around resolveReturnType() lines 225-247 and inspect how BaseTypedDefinitionNode.buildBindableGetter() and buildBindableSetter() assign nodes to synthetic accessors. Reproduce the issue with the IModel/Model example using compile-js and function type expressions enabled. Done means the [Bindable] public var satisfies the interface accessor pair without a ClassCastException, while real function type expression handling remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.