[
https://issues.apache.org/jira/browse/GROOVY-12319?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Daniel Sun updated GROOVY-12319:
--------------------------------
Description:
Groovy already accepts most Java generics. Three Java forms still fail: two in
the parser, one in {{GenericsVisitor}}. Each has a local workaround.
Method type arguments such as {{Helper.<String>identity( x )}} already work and
are not part of this request.
h3. 1. Diamond {{<>}} on an anonymous class
Java 9+ (JEP 213, JLS 15.9.5) allows diamond when creating an anonymous class,
if the target type supplies the type arguments:
{code:java}
Processor<String> p = new Processor<>() {
public String process(String val) { return val.toUpperCase(); }
};
{code}
This should work in assignment, as a method argument, and under
{{@TypeChecked}} / {{@CompileStatic}}, for both interfaces and abstract classes.
*Actual:* Groovy rejects it with {{Cannot use diamond <> with anonymous inner
classes}}.
*Workaround:* write the type arguments explicitly:
{code:java}
Processor<String> p = new Processor<String>() {
public String process(String val) { return val.toUpperCase(); }
};
{code}
GROOVY-6730 and GROOVY-7159 were false-positive STC errors when diamond was
_not_ used. They did not add this form.
h3. 2. Qualified parameterized inner types ("rare" types)
Java allows an inner type to keep the enclosing type's arguments (JLS 4.5):
{code:java}
class Outer<T> {
class Inner<U> {}
}
Outer<String>.Inner<Integer> x = new Outer<String>().new Inner<Integer>("v", 1);
{code}
The same qualification appears as a field or method type, nested in another
type argument ({{List<Outer<String>.Inner<Integer>>}}), on {{implements}}, and
in {{new Outer<T>.Inner<U>(...)}} inside the outer class.
*Actual:* Groovy fails to parse {{Outer<String>.Inner}} ({{Unexpected input}}).
*Workaround:* a factory that returns {{Inner}} without naming
{{Outer<T>.Inner}}.
h3. 3. Explicit type arguments on constructors, {{this()}} and {{super()}}
Java allows constructor type arguments independently of the class type
arguments (JLS 15.9 / 8.8.7.1):
{code:java}
class Box {
<T> Box(T t) {}
Box() { <String>this("x"); }
}
class Derived extends Box {
Derived() { <String>super("y"); }
}
class Outer {
class Inner {
<T> Inner(T t) {}
}
}
new <String>Box("x");
new Outer().new <String>Inner("z");
{code}
*Actual:* Groovy fails at {{new <}} with {{Unexpected input: '<'}}.
*Workaround:* inference, e.g. {{new Box("x")}}.
Constructor type arguments are already tracked by GROOVY-10501. The {{this()}}
/ {{super()}} / inner-{{new}} forms are the same JLS production and should be
handled together.
h3. Expected
All three forms compile in dynamic Groovy and under {{@TypeChecked}} /
{{@CompileStatic}}, matching javac on well-formed programs.
The same well-formedness rules as javac still apply. These remain compile
errors:
{code:java}
new Object<>() {} // diamond on a non-generic type
class C extends ArrayList<> {} // diamond on a class declaration
List<> list; // diamond on a field
new <String>Box<>("x") // diamond combined with constructor type
arguments
Outer<String, Integer>.Inner x; // wrong arity
x instanceof Outer<String>.Inner // parameterized type is not reifiable
new Outer<String>.Inner[1] // generic array creation
{code}
was:
Groovy already accepts most Java generics. Three Java forms still fail — two in
the parser, one in {{GenericsVisitor}}. Each has a local workaround. Method
type arguments such as {{Helper.<String>identity(x\)}} already work and are not
part of this request.
h3. 1. Diamond {{<>}} on an anonymous class
Java 9+ (JEP 213) allows:
{code:java}
Processor<String> p = new Processor<>() {
public String process(String val) { return val; }
};
{code}
Groovy rejects this with {{Cannot use diamond <> with anonymous inner
classes}}. Writing new Processor<String>() \{ ... \} compiles.
GROOVY-6730 and GROOVY-7159 were false-positive STC errors when diamond was
_not_ used; they did not add this form.
h3. 2. Qualified parameterized inner types ("rare" types)
Java allows an inner type to keep the outer's type arguments:
{code:java}
class Outer<T> {
class Inner<U> {}
}
Outer<String>.Inner<Integer> x;
{code}
Groovy fails to parse {{Outer<String>.Inner}} ({{Unexpected input}}). A factory
that returns {{Inner}} without naming {{Outer<T>.Inner}} is a workaround. The
same qualification appears in {{o.new Inner<Integer>(42)}}.
h3. 3. Explicit type arguments on constructors, {{this()}} and {{super()}}
Java allows:
{code:java}
class Box {
<T> Box(T t) {}
}
new <String>Box("x");
{code}
and, on generic constructors, {{<T>this()}}, {{<T>super()}},
{{recv.<T>super()}}, and {{outer.new <T>Inner(...)}}.
Groovy fails at {{new <}} with {{Unexpected input: '<'}}. Inference ({{new
Box("x")}}) is the workaround.
Constructor type arguments are already tracked by GROOVY-10501. The {{this()}}
/ {{super()}} / inner-{{new}} forms are the same JLS production (JLS 15.9) and
should be handled together.
h3. Related
* GROOVY-10501 — constructor type arguments (open)
* GROOVY-6730, GROOVY-7159 — diamond + anonymous class, STC false positives
(fixed)
> Java compatibility: remaining generic type syntax
> -------------------------------------------------
>
> Key: GROOVY-12319
> URL: https://issues.apache.org/jira/browse/GROOVY-12319
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Priority: Major
>
> Groovy already accepts most Java generics. Three Java forms still fail: two
> in the parser, one in {{GenericsVisitor}}. Each has a local workaround.
> Method type arguments such as {{Helper.<String>identity( x )}} already work
> and are not part of this request.
> h3. 1. Diamond {{<>}} on an anonymous class
> Java 9+ (JEP 213, JLS 15.9.5) allows diamond when creating an anonymous
> class, if the target type supplies the type arguments:
> {code:java}
> Processor<String> p = new Processor<>() {
> public String process(String val) { return val.toUpperCase(); }
> };
> {code}
> This should work in assignment, as a method argument, and under
> {{@TypeChecked}} / {{@CompileStatic}}, for both interfaces and abstract
> classes.
> *Actual:* Groovy rejects it with {{Cannot use diamond <> with anonymous inner
> classes}}.
> *Workaround:* write the type arguments explicitly:
> {code:java}
> Processor<String> p = new Processor<String>() {
> public String process(String val) { return val.toUpperCase(); }
> };
> {code}
> GROOVY-6730 and GROOVY-7159 were false-positive STC errors when diamond was
> _not_ used. They did not add this form.
> h3. 2. Qualified parameterized inner types ("rare" types)
> Java allows an inner type to keep the enclosing type's arguments (JLS 4.5):
> {code:java}
> class Outer<T> {
> class Inner<U> {}
> }
> Outer<String>.Inner<Integer> x = new Outer<String>().new Inner<Integer>("v",
> 1);
> {code}
> The same qualification appears as a field or method type, nested in another
> type argument ({{List<Outer<String>.Inner<Integer>>}}), on {{implements}},
> and in {{new Outer<T>.Inner<U>(...)}} inside the outer class.
> *Actual:* Groovy fails to parse {{Outer<String>.Inner}} ({{Unexpected
> input}}).
> *Workaround:* a factory that returns {{Inner}} without naming
> {{Outer<T>.Inner}}.
> h3. 3. Explicit type arguments on constructors, {{this()}} and {{super()}}
> Java allows constructor type arguments independently of the class type
> arguments (JLS 15.9 / 8.8.7.1):
> {code:java}
> class Box {
> <T> Box(T t) {}
> Box() { <String>this("x"); }
> }
> class Derived extends Box {
> Derived() { <String>super("y"); }
> }
> class Outer {
> class Inner {
> <T> Inner(T t) {}
> }
> }
> new <String>Box("x");
> new Outer().new <String>Inner("z");
> {code}
> *Actual:* Groovy fails at {{new <}} with {{Unexpected input: '<'}}.
> *Workaround:* inference, e.g. {{new Box("x")}}.
> Constructor type arguments are already tracked by GROOVY-10501. The
> {{this()}} / {{super()}} / inner-{{new}} forms are the same JLS production
> and should be handled together.
> h3. Expected
> All three forms compile in dynamic Groovy and under {{@TypeChecked}} /
> {{@CompileStatic}}, matching javac on well-formed programs.
> The same well-formedness rules as javac still apply. These remain compile
> errors:
> {code:java}
> new Object<>() {} // diamond on a non-generic type
> class C extends ArrayList<> {} // diamond on a class declaration
> List<> list; // diamond on a field
> new <String>Box<>("x") // diamond combined with constructor type
> arguments
> Outer<String, Integer>.Inner x; // wrong arity
> x instanceof Outer<String>.Inner // parameterized type is not reifiable
> new Outer<String>.Inner[1] // generic array creation
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)