From notifications-return-16213-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Tue Apr 16 22:59:02 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id BF58B180630 for ; Wed, 17 Apr 2019 00:59:01 +0200 (CEST) Received: (qmail 89162 invoked by uid 500); 16 Apr 2019 22:59:01 -0000 Mailing-List: contact notifications-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list notifications@groovy.apache.org Received: (qmail 89150 invoked by uid 99); 16 Apr 2019 22:59:01 -0000 Received: from mailrelay1-us-west.apache.org (HELO mailrelay1-us-west.apache.org) (209.188.14.139) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 16 Apr 2019 22:59:01 +0000 Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 7135DE00A5 for ; Tue, 16 Apr 2019 22:59:00 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 2B0A624422 for ; Tue, 16 Apr 2019 22:59:00 +0000 (UTC) Date: Tue, 16 Apr 2019 22:59:00 +0000 (UTC) From: "Eric Milles (JIRA)" To: notifications@groovy.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Comment Edited] (GROOVY-9086) @CompileStatic of closure calls with OWNER_FIRST fail at runtime with ClassCastException MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/GROOVY-9086?page=3Dcom.atlassia= n.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=3D168= 19556#comment-16819556 ]=20 Eric Milles edited comment on GROOVY-9086 at 4/16/19 10:58 PM: --------------------------------------------------------------- The {{DelegationMetadata}} is deciphered by this method in {{StaticTypeChec= kingVisitor}} to produce "Receiver\{type=3DTest.C1, data=3Ddelegate.delegat= e\}": {code:java} protected void addReceivers(final List> receivers, final Collection> owners, final boolean implicitThis) { if (typeCheckingContext.delegationMetadata =3D=3D null || !implicit= This) { receivers.addAll(owners); return; } DelegationMetadata dmd =3D typeCheckingContext.delegationMetadata; StringBuilder path =3D new StringBuilder(); while (dmd !=3D null) { int strategy =3D dmd.getStrategy(); ClassNode delegate =3D dmd.getType(); dmd =3D dmd.getParent(); switch (strategy) { case Closure.OWNER_FIRST: receivers.addAll(owners); path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); break; case Closure.DELEGATE_FIRST: path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); receivers.addAll(owners); break; case Closure.OWNER_ONLY: receivers.addAll(owners); dmd =3D null; break; case Closure.DELEGATE_ONLY: path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); dmd =3D null; break; } path.append('.'); } } {code} It starts from the innermost scope and moves outwards. It seems that "owne= r" should be appended for each parent so that the path correctly refers to = outer scopes. Here is what I am trying out: {code:java} protected void addReceivers(final List> receivers, final Collection> owners, final boolean implicitThis) { if (typeCheckingContext.delegationMetadata =3D=3D null || !implicit= This) { receivers.addAll(owners); return; } DelegationMetadata dmd =3D typeCheckingContext.delegationMetadata; StringBuilder path =3D new StringBuilder(); while (dmd !=3D null) { int strategy =3D dmd.getStrategy(); ClassNode delegate =3D dmd.getType(); dmd =3D dmd.getParent(); switch (strategy) { case Closure.OWNER_FIRST: receivers.addAll(owners); doAddDelegateReceiver(receivers, path, delegate); break; case Closure.DELEGATE_FIRST: doAddDelegateReceiver(receivers, path, delegate); receivers.addAll(owners); break; case Closure.OWNER_ONLY: receivers.addAll(owners); dmd =3D null; break; case Closure.DELEGATE_ONLY: doAddDelegateReceiver(receivers, path, delegate); dmd =3D null; break; } path.append("owner."); } } private static void doAddDelegateReceiver(final List> = receivers, final CharSequence path, final ClassNode delegate) { receivers.add(new Receiver(delegate, path.toString() + "del= egate")); if (isTraitHelper(delegate)) { receivers.add(new Receiver(delegate.getOuterClass(), pa= th.toString() + "delegate")); } } {code} was (Author: emilles): The {{DelegationMetadata}} is deciphered by this method in {{StaticTypeChec= kingVisitor}} to produce "Receiver\{type=3DTest.C1, data=3Ddelegate.delegat= e\}": {code:java} protected void addReceivers(final List> receivers, final Collection> owners, final boolean implicitThis) { if (typeCheckingContext.delegationMetadata =3D=3D null || !implicit= This) { receivers.addAll(owners); return; } DelegationMetadata dmd =3D typeCheckingContext.delegationMetadata; StringBuilder path =3D new StringBuilder(); while (dmd !=3D null) { int strategy =3D dmd.getStrategy(); ClassNode delegate =3D dmd.getType(); dmd =3D dmd.getParent(); switch (strategy) { case Closure.OWNER_FIRST: receivers.addAll(owners); path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); break; case Closure.DELEGATE_FIRST: path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); receivers.addAll(owners); break; case Closure.OWNER_ONLY: receivers.addAll(owners); dmd =3D null; break; case Closure.DELEGATE_ONLY: path.append("delegate"); doAddDelegateReceiver(receivers, path, delegate); dmd =3D null; break; } path.append('.'); } } {code} > @CompileStatic of closure calls with OWNER_FIRST fail at runtime with Cla= ssCastException > -------------------------------------------------------------------------= --------------- > > Key: GROOVY-9086 > URL: https://issues.apache.org/jira/browse/GROOVY-9086 > Project: Groovy > Issue Type: Bug > Components: Static compilation > Affects Versions: 2.5.6 > Environment: WIndows7, Groovy 2.5.6, Java 8 + 11 > Reporter: Andreas Turban > Priority: Major > Attachments: TestScript.groovy > > > The attached script fails with a ClassCastException, when method m2 is an= notated with=C2=A0 > =C2=A0 > {code:java} > strategy =3D Closure.OWNER_FIRST > {code} > =C2=A0but work with=C2=A0 > =C2=A0 > {code:java} > strategy =3D Closure.DELEGATE_FIRST > {code} > =C2=A0The expected system-out should be=C2=A0 > =C2=A0 > {code:java} > c1Method called{code} > =C2=A0in both cases. The generated bytecode for closure=C2=A0Test$_test_c= losure1$_closure2.class contains a call to getDelegate() instead of getOwne= r() in case of Closure.OWNER_FIRST. But correctly generates code getOwner()= in case of Closure.DELEGATE_FIRST. > The resulting ClassCastException at runtime is: > {code:java} > java.lang.ClassCastException: Test$C2 cannot be cast to groovy.lang.Closu= re > at Test$_test_closure1$_closure2.doCall(TestScript.groovy:28) > at Test$_test_closure1$_closure2.doCall(TestScript.groovy) > at Test.m2(TestScript.groovy:20) > at Test$_test_closure1.doCall(TestScript.groovy:26) > at Test$_test_closure1.doCall(TestScript.groovy) > at Test.m1(TestScript.groovy:8) > at Test.test(TestScript.groovy:25) > at Test$test.call(Unknown Source) > at TestScript.run(TestScript.groovy:42) > {code} > The wrong bytecode for case=C2=A0Closure.OWNER_FIRST: > {code:java} > public java.lang.Object doCall(java.lang.Object); > descriptor: (Ljava/lang/Object;)Ljava/lang/Object; > flags: ACC_PUBLIC > Code: > stack=3D1, locals=3D2, args_size=3D2 > 0: aload_0 > 1: checkcast #2 // class Test$_test_closure1$_closure2 > 4: invokevirtual #29 // Method getDelegate:()Ljava/lang/Object; > 7: checkcast #4 // class groovy/lang/Closure > 10: invokevirtual #30 // Method groovy/lang/Closure.getDelegate:()Ljava/l= ang/Object; > 13: checkcast #32 // class Test$C1 > 16: invokevirtual #36 // Method Test$C1.c1Method:()V > 19: aconst_null > 20: areturn > {code} > The correct bytecode for case=C2=A0Closure.DELEGATE_FIRST: > {code:java} > public java.lang.Object doCall(java.lang.Object); > descriptor: (Ljava/lang/Object;)Ljava/lang/Object; > flags: ACC_PUBLIC > Code: > stack=3D1, locals=3D2, args_size=3D2 > 0: aload_0 > 1: checkcast #2 // class Test$_test_closure1$_closure2 > 4: invokevirtual #29 // Method getOwner:()Ljava/lang/Object; > 7: checkcast #4 // class groovy/lang/Closure > 10: invokevirtual #32 // Method groovy/lang/Closure.getDelegate:()Ljava/l= ang/Object; > 13: checkcast #34 // class Test$C1 > 16: invokevirtual #38 // Method Test$C1.c1Method:()V > 19: aconst_null > 20: areturn > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)