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)

Reply via email to