diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java index 5f7750575fa..5c00ceed4f0 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java @@ -32,20 +32,23 @@ * type information from node metadata generated by the static type checker. */ public class StaticTypesTypeChooser extends StatementMetaTypeChooser { + @Override public ClassNode resolveType(final Expression exp, final ClassNode current) { - ASTNode target = getTarget(exp); // see GROOVY-9344, GROOVY-9607 - - ClassNode inferredType = target.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE); + ClassNode inferredType = exp.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE); + if (inferredType == null) { + inferredType = exp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); + } if (inferredType == null) { - inferredType = target.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); + ASTNode node = getTarget(exp); // GROOVY-9344, GROOVY-9607 + inferredType = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); } if (inferredType != null && !isPrimitiveVoid(inferredType)) { return inferredType; } - // AsmClassGenerator may create "this" expressions that the type checker knows nothing about - if (target instanceof VariableExpression && ((VariableExpression) target).isThisExpression()) { + // AsmClassGenerator creates "this" expressions that the type checker knows nothing about + if (exp instanceof VariableExpression && ((VariableExpression) exp).isThisExpression()) { return current; } diff --git a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy index 91b14bd590f..129501a9c31 100644 --- a/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy +++ b/src/test/groovy/groovy/transform/stc/STCAssignmentTest.groovy @@ -645,6 +645,21 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase { ''' } + void testCastObjectToInterface() { + assertScript ''' + List m(object) { + if (object == null) return new ArrayList<>() + if (object instanceof Collection) return new ArrayList((Collection) object) + return [object] + } + def item = 0 + def list = [1,2] + assert m(null).size() == 0 + assert m(item).size() == 1 + assert m(list).size() == 2 + ''' + } + void testIfElseBranch() { shouldFailWithMessages ''' def x diff --git a/src/test/groovy/groovy/transform/stc/STCnAryExpressionTest.groovy b/src/test/groovy/groovy/transform/stc/STCnAryExpressionTest.groovy index bff8c0a82ad..7bb95c1ad69 100644 --- a/src/test/groovy/groovy/transform/stc/STCnAryExpressionTest.groovy +++ b/src/test/groovy/groovy/transform/stc/STCnAryExpressionTest.groovy @@ -132,6 +132,26 @@ class STCnAryExpressionTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-11375 + void testShiftOnPrimitivesVariableFlowType() { + assertScript ''' + def x = "--" + x = x.size() + def y = x << x + assert y === 8 + ''' + } + + // GROOVY-11375 + void testPowerOnPrimitivesVariableFlowType() { + assertScript ''' + def x = "--" + x = x.size() + def y = x ** x + assert y === 4 + ''' + } + // GROOVY-5644 void testSpaceshipOperatorNoAmbiguousError() { assertScript ''' diff --git a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy index 538589f10db..7eead72ade1 100644 --- a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy +++ b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy @@ -31,4 +31,12 @@ final class AssignmentsStaticCompileTest extends STCAssignmentTest implements St String bytecode = astTrees['C'][1] assert !bytecode.contains('ScriptBytecodeAdapter.setGroovyObjectProperty') : '"c.i += 10" should use setter, not dynamic property' } + + @Override // GROOVY-11769 + void testCastObjectToInterface() { + super.testCastObjectToInterface() + String bytecode = astTrees.values()[0][1] + bytecode = bytecode.substring(bytecode.indexOf('m(Ljava/lang/Object;)')) + assert bytecode.count('CHECKCAST') == 1 // guarded typecast isn't groovy + } }