Skip to content

Commit 0817dcf

Browse files
committed
GROOVY-10153
1 parent c49c190 commit 0817dcf

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+30
Original file line numberDiff line numberDiff line change
@@ -4271,6 +4271,36 @@ public void testTypeChecked10128() {
42714271
runConformTest(sources);
42724272
}
42734273

4274+
@Test
4275+
public void testTypeChecked10153() {
4276+
//@formatter:off
4277+
String[] sources = {
4278+
"Main.groovy",
4279+
"class A {}\n" +
4280+
"class B extends A {}\n" +
4281+
"class C extends B {}\n" +
4282+
"class Foo<T extends A> {}\n" +
4283+
"@groovy.transform.TypeChecked\n" +
4284+
"void test() {\n" +
4285+
" Foo<? super C> foo = new Foo<B>()\n" + // ? is not a valid substitute for <T extends A>
4286+
"}\n" +
4287+
"test()\n",
4288+
};
4289+
//@formatter:on
4290+
4291+
if (isAtLeastGroovy(30)) {
4292+
runConformTest(sources);
4293+
} else {
4294+
runNegativeTest(sources,
4295+
"----------\n" +
4296+
"1. ERROR in Main.groovy (at line 7)\n" +
4297+
"\tFoo<? super C> foo = new Foo<B>()\n" +
4298+
"\t ^^^^^^^^^\n" +
4299+
"Groovy:The type ? is not a valid substitute for the bounded parameter <T extends A>\n" +
4300+
"----------\n");
4301+
}
4302+
}
4303+
42744304
@Test
42754305
public void testTypeChecked10166() {
42764306
//@formatter:off

base/org.codehaus.groovy30/src/org/codehaus/groovy/control/ResolveVisitor.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import java.util.ListIterator;
7777
import java.util.Map;
7878
import java.util.Objects;
79+
import java.util.Optional;
7980
import java.util.Set;
8081
import java.util.function.Predicate;
8182

@@ -544,7 +545,9 @@ protected boolean resolve(final ClassNode type, final boolean testModuleImports,
544545
type.setGenericsPlaceHolder(true);
545546
return true;
546547
}
547-
548+
// GRECLIPSE add
549+
try {
550+
// GRECLIPSE end
548551
if (currentClass.getNameWithoutPackage().equals(typeName)) {
549552
type.setRedirect(currentClass);
550553
return true;
@@ -556,6 +559,21 @@ protected boolean resolve(final ClassNode type, final boolean testModuleImports,
556559
(testDefaultImports && !type.hasPackageName() && resolveFromDefaultImports(type, true)) ||
557560
resolveToOuter(type) ||
558561
(testStaticInnerClasses && type.hasPackageName() && resolveFromStaticInnerClasses(type, true));
562+
// GRECLIPSE add -- GROOVY-10153: deal with "Foo<? super Bar> -> Foo<T extends Baz>"
563+
} finally {
564+
if (type.isRedirectNode()) Optional.ofNullable(type.getGenericsTypes()).ifPresent(arguments -> {
565+
for (int i = 0, n = arguments.length; i < n; i += 1) { GenericsType argument = arguments[i];
566+
if (!argument.isWildcard() || argument.getUpperBounds() != null) continue;
567+
GenericsType[] parameters = type.redirect().getGenericsTypes();
568+
if (parameters != null && i < parameters.length) {
569+
ClassNode implicitBound = parameters[i].getType();
570+
if (!implicitBound.equals(ClassHelper.OBJECT_TYPE))
571+
argument.getType().setRedirect(implicitBound);
572+
}
573+
}
574+
});
575+
}
576+
// GRECLIPSE end
559577
}
560578

561579
protected boolean resolveNestedClass(final ClassNode type) {

base/org.codehaus.groovy40/src/org/codehaus/groovy/control/ResolveVisitor.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import java.util.ListIterator;
7676
import java.util.Map;
7777
import java.util.Objects;
78+
import java.util.Optional;
7879
import java.util.Set;
7980
import java.util.function.Predicate;
8081

@@ -457,7 +458,9 @@ protected boolean resolve(final ClassNode type, final boolean testModuleImports,
457458
type.setGenericsPlaceHolder(true);
458459
return true;
459460
}
460-
461+
// GRECLIPSE add
462+
try {
463+
// GRECLIPSE end
461464
if (currentClass.getNameWithoutPackage().equals(typeName)) {
462465
type.setRedirect(currentClass);
463466
return true;
@@ -469,6 +472,21 @@ protected boolean resolve(final ClassNode type, final boolean testModuleImports,
469472
(testDefaultImports && !type.hasPackageName() && resolveFromDefaultImports(type, true)) ||
470473
resolveToOuter(type) ||
471474
(testStaticInnerClasses && type.hasPackageName() && resolveFromStaticInnerClasses(type, true));
475+
// GRECLIPSE add -- GROOVY-10153: deal with "Foo<? super Bar> -> Foo<T extends Baz>"
476+
} finally {
477+
if (type.isRedirectNode()) Optional.ofNullable(type.getGenericsTypes()).ifPresent(arguments -> {
478+
for (int i = 0, n = arguments.length; i < n; i += 1) { GenericsType argument = arguments[i];
479+
if (!argument.isWildcard() || argument.getUpperBounds() != null) continue;
480+
GenericsType[] parameters = type.redirect().getGenericsTypes();
481+
if (parameters != null && i < parameters.length) {
482+
ClassNode implicitBound = parameters[i].getType();
483+
if (!isObjectType(implicitBound))
484+
argument.getType().setRedirect(implicitBound);
485+
}
486+
}
487+
});
488+
}
489+
// GRECLIPSE end
472490
}
473491

474492
protected boolean resolveNestedClass(final ClassNode type) {

0 commit comments

Comments
 (0)