[ https://issues.apache.org/jira/browse/GROOVY-10763?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Christopher Smith updated GROOVY-10763: --------------------------------------- Description: 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. was: 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 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). I cannot figure out how the reference for {{sc}} (generic) is getting replaced with a raw copy, but it happens immediately (not later in the compilation process) and is carried through to the bytecode. Summary: Generic types are cleared on read when a ClassNode is assigned as a superClass (was: Generic types are cleared when a ClassNode is assigned as a superClass) > Generic types are cleared on read when a ClassNode is assigned as a superClass > ------------------------------------------------------------------------------ > > 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 > Priority: Major > > 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. -- This message was sent by Atlassian Jira (v8.20.10#820010)