Unexpected behaviour for getAt operator operloading with static compilation

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Unexpected behaviour for getAt operator operloading with static compilation

Mirco
Hi,
I've encountered a strange compile error with the getAt method and the @CompileStatic annotation.
Below some scripts to reproduce the error with the GroovyConsole:

import groovy.transform.CompileStatic
@CompileStatic
class Pippo {
    int getAt(String pluto) { return 1 }
    int plus(String paperino) { return 1 }
}
@CompileStatic
public class Demo {
    public static void main(String[] args) {
        def pippo = new Pippo()
        int i = pippo['a']          // [Static type checking] - Cannot assign value of type java.lang.Object to variable of type int
        //int i = pippo.getAt('a')  // Works
        //int i = pippo + 'a'       // Works
    }
}
Demo.main()

At first I thought of some general issue with operator overloading but the plus method does not seem to be affected (last commented line above).
Morevover, my actual code involves generics and in this case new errors came up even with the cast:

import groovy.transform.CompileStatic
@CompileStatic
class Pippo<K,V> {
    V paperino
    V getAt(K pluto) { return paperino }
}
@CompileStatic
public class Demo {
    public static void main(String[] args) {
        Pippo<String, Integer> pippo = new Pippo<>()
        pippo.paperino = 313
        int i = (int) pippo['a']       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
        // int i = pippo.getAt('a')    // works
        println i
    }
}
Demo.main()

If the two generic types are the same (ex. both Integer):

BUG! exception in phase 'class generation' in source unit 'ConsoleScript0' At line 12 column 23
On receiver: pippo with message: getAt and arguments: 1
This method should not have been called. Please try to create a simple example reproducing this error and filea bug report at https://issues.apache.org/jira/browse/GROOVY

import groovy.transform.CompileStatic
@CompileStatic
class Pippo<K,V> {
    V paperino
    V getAt(K pluto) { return paperino }
}
@CompileStatic
public class Demo {
    public static void main(String[] args) {
        Pippo<Integer, Integer> pippo = new Pippo<>()
        pippo.paperino = 313
        int i = (int) pippo[1]       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
        // int i = pippo.getAt('a')    // works
        println i
    }
}
Demo.main()

Is there some known issue about getAt and CompileStatic or simply I misunderstood its use?

Thanks,

M
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected behaviour for getAt operator operloading with static compilation

Basurita
I'm not 100% certain, but my understanding is the following:
When you @CompileStatic the expression `int i= pippo['a']` the compiler will generate bytecode for a method with signature `getAt(String)` that
returns an `Object`
    See  http://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Object.html#getAt(java.lang.String)

The return type is not part of the method's signature, but Object is the expected value according to the specification.
Then, you can't assign an Object to an int without casting. This is the same as in Java, which is what happens when you @CompileStatic.
This has nothing to do with Pippo. You can change Pippo's `getAt` so it returns Object, and you'll get the same error which is correct.
If you KNOW that it's going to be an int at run time, then use a cast, or else define variable `i` as Object (or def).
Or don't use @CompileStatic in Demo (you can leave it for Pippo), and everythin will be resolved dynamically at run time


BBB

On 10/21/17 1:06 PM, Mirco wrote:

> Hi,
> I've encountered a strange compile error with the getAt method and the @CompileStatic annotation.
> Below some scripts to reproduce the error with the GroovyConsole:
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo {
>     int getAt(String pluto) { return 1 }
>     int plus(String paperino) { return 1 }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         def pippo = new Pippo()
>         int i = pippo['a']          // [Static type checking] - Cannot assign value of type java.lang.Object to variable of type int
>         //int i = pippo.getAt('a')  // Works
>         //int i = pippo + 'a'       // Works
>     }
> }
> Demo.main()
>
> At first I thought of some general issue with operator overloading but the plus method does not seem to be affected (last commented line above).
> Morevover, my actual code involves generics and in this case new errors came up even with the cast:
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo<K,V> {
>     V paperino
>     V getAt(K pluto) { return paperino }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         Pippo<String, Integer> pippo = new Pippo<>()
>         pippo.paperino = 313
>         int i = (int) pippo['a']       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
>         // int i = pippo.getAt('a')    // works
>         println i
>     }
> }
> Demo.main()
>
> If the two generic types are the same (ex. both Integer):
>
> BUG! exception in phase 'class generation' in source unit 'ConsoleScript0' At line 12 column 23
> On receiver: pippo with message: getAt and arguments: 1
> This method should not have been called. Please try to create a simple example reproducing this error and filea bug report at
> https://issues.apache.org/jira/browse/GROOVY <https://issues.apache.org/jira/browse/GROOVY>
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo<K,V> {
>     V paperino
>     V getAt(K pluto) { return paperino }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         Pippo<Integer, Integer> pippo = new Pippo<>()
>         pippo.paperino = 313
>         int i = (int) pippo[1]       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
>         // int i = pippo.getAt('a')    // works
>         println i
>     }
> }
> Demo.main()
>
> Is there some known issue about getAt and CompileStatic or simply I misunderstood its use?
>
> Thanks,
>
> M



Reply | Threaded
Open this post in threaded view
|

Re: Unexpected behaviour for getAt operator operloading with static compilation

paulk_asert
I haven't had a chance to look into your error yet but whenever you see:
BUG! exception in phase 'xxxxxx', that is a bug. We should either be producing some
correct behavior or giving a more friendly error message in this case.
Please raise a Jira issue.

Thanks, Paul.

On Sun, Oct 22, 2017 at 2:43 AM, Basurita <[hidden email]> wrote:
I'm not 100% certain, but my understanding is the following:
When you @CompileStatic the expression `int i= pippo['a']` the compiler will generate bytecode for a method with signature `getAt(String)` that
returns an `Object`
    See  http://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Object.html#getAt(java.lang.String)

The return type is not part of the method's signature, but Object is the expected value according to the specification.
Then, you can't assign an Object to an int without casting. This is the same as in Java, which is what happens when you @CompileStatic.
This has nothing to do with Pippo. You can change Pippo's `getAt` so it returns Object, and you'll get the same error which is correct.
If you KNOW that it's going to be an int at run time, then use a cast, or else define variable `i` as Object (or def).
Or don't use @CompileStatic in Demo (you can leave it for Pippo), and everythin will be resolved dynamically at run time


BBB

On 10/21/17 1:06 PM, Mirco wrote:
> Hi,
> I've encountered a strange compile error with the getAt method and the @CompileStatic annotation.
> Below some scripts to reproduce the error with the GroovyConsole:
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo {
>     int getAt(String pluto) { return 1 }
>     int plus(String paperino) { return 1 }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         def pippo = new Pippo()
>         int i = pippo['a']          // [Static type checking] - Cannot assign value of type java.lang.Object to variable of type int
>         //int i = pippo.getAt('a')  // Works
>         //int i = pippo + 'a'       // Works
>     }
> }
> Demo.main()
>
> At first I thought of some general issue with operator overloading but the plus method does not seem to be affected (last commented line above).
> Morevover, my actual code involves generics and in this case new errors came up even with the cast:
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo<K,V> {
>     V paperino
>     V getAt(K pluto) { return paperino }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         Pippo<String, Integer> pippo = new Pippo<>()
>         pippo.paperino = 313
>         int i = (int) pippo['a']       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
>         // int i = pippo.getAt('a')    // works
>         println i
>     }
> }
> Demo.main()
>
> If the two generic types are the same (ex. both Integer):
>
> BUG! exception in phase 'class generation' in source unit 'ConsoleScript0' At line 12 column 23
> On receiver: pippo with message: getAt and arguments: 1
> This method should not have been called. Please try to create a simple example reproducing this error and filea bug report at
> https://issues.apache.org/jira/browse/GROOVY <https://issues.apache.org/jira/browse/GROOVY>
>
> import groovy.transform.CompileStatic
> @CompileStatic
> class Pippo<K,V> {
>     V paperino
>     V getAt(K pluto) { return paperino }
> }
> @CompileStatic
> public class Demo {
>     public static void main(String[] args) {
>         Pippo<Integer, Integer> pippo = new Pippo<>()
>         pippo.paperino = 313
>         int i = (int) pippo[1]       // groovy.lang.MissingPropertyException: No such property: a for class: Pippo
>         // int i = pippo.getAt('a')    // works
>         println i
>     }
> }
> Demo.main()
>
> Is there some known issue about getAt and CompileStatic or simply I misunderstood its use?
>
> Thanks,
>
> M