Eric Milles created GROOVY-8337: ----------------------------------- Summary: STC: instanceof in ternary expression not propagating type info to true expression Key: GROOVY-8337 URL: https://issues.apache.org/jira/browse/GROOVY-8337 Project: Groovy Issue Type: Bug Components: Static Type Checker Reporter: Eric Milles Priority: Minor
{code} @CompileStatic class Static { Number n BigDecimal meth() { return n == null || n instanceof BigDecimal ? n : new BigDecimal(n.toString()) } } {code} StaticTypeCheckingVisitor is missing the temporary type of the true expression part of the ternary expression because it pops before accessing the type. One possible solution: {code} @Override public void visitTernaryExpression(final TernaryExpression expression) { Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking(); // create a new temporary element in the if-then-else type info typeCheckingContext.pushTemporaryTypeInfo(); expression.getBooleanExpression().visit(this); Expression trueExpression = expression.getTrueExpression(); Expression falseExpression = expression.getFalseExpression(); trueExpression.visit(this); // GRECLIPSE add final ClassNode typeOfTrue = findCurrentInstanceOfClass(trueExpression, getType(trueExpression)); // GRECLIPSE end // pop if-then-else temporary type info typeCheckingContext.popTemporaryTypeInfo(); falseExpression.visit(this); ClassNode resultType; if (isNullConstant(trueExpression) || isNullConstant(falseExpression)) { BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression(); if (enclosingBinaryExpression != null && enclosingBinaryExpression.getRightExpression()==expression) { resultType = getType(enclosingBinaryExpression.getLeftExpression()); } else if (isNullConstant(trueExpression) && isNullConstant(falseExpression)) { resultType = OBJECT_TYPE; } else if (isNullConstant(trueExpression)) { resultType = wrapTypeIfNecessary(getType(falseExpression)); } else { resultType = wrapTypeIfNecessary(getType(trueExpression)); } } else { // store type information // GRECLIPSE edit //final ClassNode typeOfTrue = getType(trueExpression); // GRECLIPSE end final ClassNode typeOfFalse = getType(falseExpression); resultType = lowestUpperBound(typeOfTrue, typeOfFalse); } storeType(expression, resultType); popAssignmentTracking(oldTracker); } {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)