Skip to content

Commit aec028c

Browse files
committed
GROOVY-11375, GROOVY-11769: SC: lookup type of variable before target
see also GROOVY-7971, GROOVY-9344, GROOVY-9607 4_0_X backport
1 parent 3f57258 commit aec028c

File tree

5 files changed

+70
-19
lines changed

5 files changed

+70
-19
lines changed

src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,23 @@
3232
* type information from node metadata generated by the static type checker.
3333
*/
3434
public class StaticTypesTypeChooser extends StatementMetaTypeChooser {
35+
3536
@Override
3637
public ClassNode resolveType(final Expression exp, final ClassNode current) {
37-
ASTNode target = getTarget(exp); // see GROOVY-9344, GROOVY-9607
38-
39-
ClassNode inferredType = target.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE);
38+
ClassNode inferredType = exp.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE);
39+
if (inferredType == null) {
40+
inferredType = exp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
41+
}
4042
if (inferredType == null) {
41-
inferredType = target.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
43+
ASTNode node = getTarget(exp); // GROOVY-9344, GROOVY-9607
44+
inferredType = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
4245
}
4346
if (inferredType != null && !isPrimitiveVoid(inferredType)) {
4447
return inferredType;
4548
}
4649

47-
// AsmClassGenerator may create "this" expressions that the type checker knows nothing about
48-
if (target instanceof VariableExpression && ((VariableExpression) target).isThisExpression()) {
50+
// AsmClassGenerator creates "this" expressions that the type checker knows nothing about
51+
if (exp instanceof VariableExpression && ((VariableExpression) exp).isThisExpression()) {
4952
return current;
5053
}
5154

src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,21 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
645645
'''
646646
}
647647

648+
void testCastObjectToInterface() {
649+
assertScript '''
650+
List<Object> m(object) {
651+
if (object == null) return new ArrayList<>()
652+
if (object instanceof Collection) return new ArrayList<Object>((Collection) object)
653+
return [object]
654+
}
655+
def item = 0
656+
def list = [1,2]
657+
assert m(null).size() == 0
658+
assert m(item).size() == 1
659+
assert m(list).size() == 2
660+
'''
661+
}
662+
648663
void testIfElseBranch() {
649664
shouldFailWithMessages '''
650665
def x

src/test/groovy/groovy/transform/stc/STCnAryExpressionTest.groovy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,26 @@ class STCnAryExpressionTest extends StaticTypeCheckingTestCase {
132132
'''
133133
}
134134

135+
// GROOVY-11375
136+
void testShiftOnPrimitivesVariableFlowType() {
137+
assertScript '''
138+
def x = "--"
139+
x = x.size()
140+
def y = x << x
141+
assert y === 8
142+
'''
143+
}
144+
145+
// GROOVY-11375
146+
void testPowerOnPrimitivesVariableFlowType() {
147+
assertScript '''
148+
def x = "--"
149+
x = x.size()
150+
def y = x ** x
151+
assert y === 4
152+
'''
153+
}
154+
135155
// GROOVY-5644
136156
void testSpaceshipOperatorNoAmbiguousError() {
137157
assertScript '''

src/test/groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
package groovy.transform.stc
2020

21-
import groovy.test.NotYetImplemented
2221
import org.codehaus.groovy.ast.ClassHelper
2322
import org.codehaus.groovy.ast.ClassNode
2423
import org.codehaus.groovy.ast.MethodNode
@@ -242,23 +241,29 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
242241
'''
243242
}
244243

245-
// GROOVY-10096
246-
@NotYetImplemented
244+
// GROOVY-11769
247245
void testInstanceOf10() {
248-
shouldFailWithMessages '''
249-
class Foo {
250-
void foo() {
251-
}
246+
assertScript '''
247+
abstract class Foo {
248+
abstract boolean isBaz()
252249
}
253250
class Bar extends Foo {
254-
void bar() {
255-
}
251+
final boolean baz = false
256252
}
257-
static Bar baz(Foo foo) {
258-
(false || foo instanceof Bar) ? foo : new Bar()
253+
class Baz extends Foo {
254+
final boolean baz = true
259255
}
260-
''',
261-
'Cannot return value of type Foo for method returning Bar'
256+
257+
void test(Foo foo) {
258+
if (foo instanceof Bar || foo.isBaz()) {
259+
foo.toString()
260+
}
261+
}
262+
263+
test(new Bar())
264+
test(new Baz())
265+
test(new Foo(){ boolean isBaz() { false } })
266+
'''
262267
}
263268

264269
// GROOVY-11007

src/test/groovy/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ final class AssignmentsStaticCompileTest extends STCAssignmentTest implements St
3131
String bytecode = astTrees['C'][1]
3232
assert !bytecode.contains('ScriptBytecodeAdapter.setGroovyObjectProperty') : '"c.i += 10" should use setter, not dynamic property'
3333
}
34+
35+
@Override // GROOVY-11769
36+
void testCastObjectToInterface() {
37+
super.testCastObjectToInterface()
38+
String bytecode = astTrees.values()[0][1]
39+
bytecode = bytecode.substring(bytecode.indexOf('m(Ljava/lang/Object;)'))
40+
assert bytecode.count('CHECKCAST') == 1 // guarded typecast isn't groovy
41+
}
3442
}

0 commit comments

Comments
 (0)