[ 
https://issues.apache.org/jira/browse/GROOVY-12755?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18142140#comment-18142140
 ] 

ASF GitHub Bot commented on GROOVY-12755:
-----------------------------------------

codeconsole commented on PR #3286:
URL: https://github.com/apache/groovy/pull/3286#issuecomment-6773195812

   @daniellansun thanks. I reproduced each case against the branch and against 
javac. New commits on top of 2ce6046aa3, after merging master:
   
   1. **Enclosing type arguments.** `erasureOf` drops the enclosing type too, 
so an `Outer<String>.Inner` receiver gives `Class<? extends Outer.Inner>`. I 
did it there and not in `ClassNode.getPlainNodeReference`, which is documented 
to copy the enclosing type and has many other callers. `Class<? extends 
Outer.Inner>` is accepted and `Class<? extends Outer<String>.Inner>` is 
rejected.
   
      One difference from javac is left: inside `Outer<T>.Inner`, the simple 
name in `Class<? extends Inner>` is still accepted. The resolver gives a simple 
name no enclosing parameterization, so `Inner` and `Outer.Inner` are the same 
type to the checker. Also, the error message prints the raw inner type as 
`Outer<T>.Inner`. That is how `GenericsType` prints a non-static inner type 
that has no enclosing type, on master as well.
   
   2. **Raw bound against a parameterized bound.** 
`StaticTypeCheckingSupport.upperBoundEscapes` is new, next to 
`concreteArgumentContainsWildcard` and `typeVariableBoundEscapes`, and is 
called from the same two places: `checkTypeGenerics` (assignment and return) 
and the declared-parameter check in `typeCheckMethodsWithGenerics`. `? extends 
A` is rejected for `? extends B` when `B` is parameterized, or has a 
parameterized enclosing type, and `A` is raw; and when `B` is a type variable 
and `A` is not one.
   
      Your three returns are now errors, and so are the two hand-written cases 
(`Class<? extends List>` as `Class<? extends List<String>>`, and `Class<? 
extends Number>` as `Class<? extends T>`). The argument position is covered 
too, since javac rejects it as well: `accept(strings.getClass())` for 
`accept(Class<? extends List<String>>)`.
   
      Left as before: a raw type that is not a wildcard bound (`List<String> x 
= rawList`, or `Class<ArrayList>` for `Class<? extends List<String>>`), a 
source bound that is a type variable, an inference variable, and a property of 
a raw receiver (`rawHolder.type = c` for a `Class<? extends T> type`).
   
      One consequence to be aware of: `<T> Class<? extends T> typeOf(T t) { 
t.getClass() }` compiled before this PR, with `getClass()` as `Class<?>`, and 
is now an error, as in javac, which wants the cast.
   
   3. **Intersection.** `erasureOf` takes the leftmost component, so `((Number 
& Runnable) o).getClass()` is `Class<? extends Number>` and is rejected for 
`Class<? extends Runnable>`.
   
   4. **Spread.** `PropertyLookup.visitMethod` gives `Object#getClass` the same 
type, so `list*.class` is `List<Class<? extends String>>`, like 
`list*.getClass()`.
   
   5. **Tests.** `GenericsSTCTest` records the inferred type with `@ASTTest` 
for the nested, intersection and spread receivers, and has the negative cases 
for the three returns, the assignment, the argument, and the two hand-written 
bounds, with the forms that must keep compiling beside them. 
`GenericsJavaCompatibilityTest` gets six negative cases checked against javac 
(parameterized receiver, `T extends Comparable<T>`, `this` in a generic class, 
`Outer<String>.Inner`, the intersection, and `Class<? extends Number>` for 
`Class<? extends T>`) and the positive `Outer.Inner` one. The eleven new 
negative and inferred-type tests fail without the change.
   
   6. **CI.** Master is merged, so 
`StaticCompileRuntimePackageTest.testSystemProperty` has the restored property.
   
   Class literals are untouched: only a zero-argument `getClass` declared on 
`Object` takes the new path. GROOVY-12754 (#3285) is still the first commit 
here and has to go in first.
   




> STC: e.getClass() is typed Class<?>, so since GROOVY-12714 it is rejected 
> where a Class<? extends T> is expected
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12755
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12755
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static Type Checker
>    Affects Versions: 7.0.0-alpha-1, 6.0.1
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> JLS 4.3.2 gives a call {{e.getClass()}} the type {{Class<? extends |T|>}}, 
> where {{|T|}} is the erasure of the static type of {{e}}. Static type 
> checking types it with the declared return type of {{Object#getClass()}}, 
> {{Class<?>}}. Until GROOVY-12714 the wildcard check accepted {{Class<?>}} 
> where a {{Class<? extends T>}} was expected. Since GROOVY-12714 (GROOVY_6_0_X 
> and master) it is rejected:
> {code:groovy}
> @groovy.transform.CompileStatic
> class C {
>     interface Store {}
>     static <T> T with(Class<? extends Store> type, Closure<T> body) { 
> body.call() }
>     static class Adapter { Adapter(Class<? extends Store> type) {} }
>     static Object viaMethod(Store store) { with(store.getClass()) { 1 } }
>     static Object viaProperty(Store store) { with(store.class) { 1 } }
>     static Object viaConstructor(Store store) { new Adapter(store.getClass()) 
> }
>     static Class<? extends Store> viaReturn(Store store) { store.getClass() }
> }
> {code}
> {noformat}
> [Static type checking] - Cannot call <T> C#with(java.lang.Class<? extends 
> C.Store>, groovy.lang.Closure<T>) with arguments [java.lang.Class<?>, 
> groovy.lang.Closure]
> [Static type checking] - Cannot call <T> C#with(java.lang.Class<? extends 
> C.Store>, groovy.lang.Closure<T>) with arguments [java.lang.Class<?>, 
> groovy.lang.Closure]
> [Static type checking] - Cannot call C$Adapter#<init>(java.lang.Class<? 
> extends C.Store>) with arguments [java.lang.Class<?>]
> [Static type checking] - Incompatible generic argument types. Cannot assign 
> java.lang.Class<?> to: java.lang.Class<? extends C.Store>
> {noformat}
> javac accepts the equivalent Java. Grails no longer compiles against 
> GROOVY_6_0_X: it passes {{datastore.getClass()}} to a {{Class<? extends 
> Datastore>}} parameter and {{registrar.getClass()}} to a {{Class<? extends 
> BeanRegistrar>}} one 
> (https://github.com/apache/grails-core/actions/runs/42702095261).
> Typing {{e.getClass()}} and {{e.class}} as {{Class<? extends |T|>}} makes 
> more calls pass an upper-bounded wildcard for a bounded type parameter, such 
> as {{foo(list.class)}} for {{<T extends List<Integer>> foo(Class<T>)}}, which 
> GROOVY-12754 rejected. So this depends on GROOVY-12754.
> The inferred type of {{list.class}} for a raw {{List list}} changes from 
> {{Class<? extends Object>}} to {{Class<? extends List>}}, and the GROOVY-5415 
> error for {{a.bar(this.getClass())}} now names {{Class<? extends ClassB>}}; 
> the two tests that assert those types are updated.
> PR: https://github.com/apache/groovy/pull/3286



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to