[
https://issues.apache.org/jira/browse/GROOVY-10763?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King closed GROOVY-10763.
------------------------------
> ClassNode setSuperClass and setInterfaces should update usingGenerics
> ---------------------------------------------------------------------
>
> Key: GROOVY-10763
> URL: https://issues.apache.org/jira/browse/GROOVY-10763
> Project: Groovy
> Issue Type: Bug
> Components: Compiler
> Affects Versions: 4.0.5
> Reporter: Christopher Smith
> Assignee: Eric Milles
> Priority: Major
> Fix For: 5.0.0-alpha-1
>
>
> I have an annotation that, if an annotated class has no {{{}extends{}}},
> should make it extend {{{}Resource<A>{}}}, where {{A}} is determined by
> Logic. I attempted to create the {{ClassNode}} representing the intended base
> class and assign it as the derived class's {{{}superClass{}}}:
> {code:groovy}
> println resource.superClass // java.lang.Object
> def sc = makeClassSafeWithGenerics(TYPE_RESOURCE, attr)
> println sc // Resource<com.example.Derived$Attributes> -> Resource<A>
> println sc.genericsTypes // [com.example.Derived$Attributes]
> cn.superClass = sc
> def sc2 = cn.superClass
> println sc2 // Resource<A>
> println cn.@superClass // Resource<com.example.Derived$Attributes> ->
> Resource<A>
> println sc2 == sc // true, but compares only the erasure
> println sc2 === sc // false
> {code}
> The compiler then proceeds to write out a {{.class}} file extending the raw
> {{Resource}} type. The compiler writes the correct {{Resource<Attributes>}}
> if it is typed out inline in the input file.
> I've confirmed that the {{ClassNode TYPE_RESOURCE}} is not a redirect or a
> genericsPlaceholder, so the {{superClass}} assignment appears to be a direct
> field assignment (once {{redirect()}} returns {{{}this{}}}), and
> {{getUnresolvedSuperClass}} appears to read the field directly
> ({{{}lazyInitDone{}}} is already true), but using {{.@superClass}} returns
> the generic copy and {{.superClass}} (which is used by the rest of the
> compilation process) the raw copy.
>
> {*}Update{*}: {{[email protected]}} is true, and {{getSuperClass}}
> unwraps redirects ({{{}ClassNode:1040{}}} in 4.0.5). This appears to be a
> logic error precisely because of this discard-generics-on-read effect.
> {*}Update 2{*}: I see the same "superclass is a redirect, and
> {{getSuperClass}} returns a raw type" on a class where the generics are
> specified in Groovy source code, but this class has the correct generics
> written into the bytecode where the ASTT-modified class does not. I cannot
> find any way to distinguish between the {{{}ClassNode{}}}s for the
> superclasses in these cases, but the output differs. (In case it's relevant
> at all, constructing a node for an interface type that has generic parameters
> and adding it to a class writes the type parameters into the bytecode; it's
> only the superclass that gets erased.)
> {*}Update 3{*}: In the case of a resource subclass that has type parameters
> defined in Groovy source, the field {{usesGenerics}} is set to true,
> presumably via the check at {{{}ClassNode:345{}}}. I have tried manually
> setting {{{}cn.usingGenerics = true{}}}, but that's triggering a (spurious?)
> "transform used a generics containing... directly" error downstream. It seems
> like a bug that the constructor sets {{usesGenerics}} if the superclass uses
> generics but that {{setSuperClass}} does not.
> {*}Update 4{*}: Adding the explicit {{cn.usingGenerics = true}} fixes the
> missing type parameters in the bytecode, at the cost of having to make
> spurious calls to {{.plainNodeReference}} later. It appears that the compiler
> is checking {{usingGenerics}} on class nodes when writing the {{extends}}
> part of the bytecode but not {{{}implements{}}}. There seem to be two logical
> bugs here: If the superclass has generic types, it shouldn't matter what the
> flag is on the subclass (write the type parameters as for interfaces), and
> creating a {{ClassNode}} that extends a generic superclass but does not
> itself have type parameters (e.g., {{{}StringMap extends HashMap<String,
> String>{}}}) should not trigger the "you must copy this node to refer to it"
> check.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)