[ https://issues.apache.org/jira/browse/GROOVY-9058?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16808751#comment-16808751 ]
Eric Milles commented on GROOVY-9058: ------------------------------------- In order to preserve the type checking of assignments, I think it best to make some kind of change after {{typeCheckAssignment}} in {{StaticTypeCheckingVisitor.visitBinaryExpression}}. Here is the current code for handling assignments: {code:java} if (!isEmptyDeclaration && isAssignment(op)) { if (rightExpression instanceof ConstructorCallExpression) { inferDiamondType((ConstructorCallExpression) rightExpression, lType); } ClassNode originType = getOriginalDeclarationType(leftExpression); typeCheckAssignment(expression, leftExpression, originType, rightExpression, resultType); // if assignment succeeds but result type is not a subtype of original type, then we are in a special cast handling // and we must update the result type if (!implementsInterfaceOrIsSubclassOf(getWrapper(resultType), getWrapper(originType))) { resultType = originType; } else if (lType.isUsingGenerics() && !lType.isEnum() && hasRHSIncompleteGenericTypeInfo(resultType)) { // for example, LHS is List<ConcreteClass> and RHS is List<T> where T is a placeholder resultType = lType; } // make sure we keep primitive types if (isPrimitiveType(originType) && resultType.equals(getWrapper(originType))) { resultType = originType; } // if we are in an if/else branch, keep track of assignment if (typeCheckingContext.ifElseForWhileAssignmentTracker != null && leftExpression instanceof VariableExpression && !isNullConstant(rightExpression)) { Variable accessedVariable = ((VariableExpression) leftExpression).getAccessedVariable(); if (accessedVariable instanceof Parameter) { accessedVariable = new ParameterVariableExpression((Parameter) accessedVariable); } if (accessedVariable instanceof VariableExpression) { VariableExpression var = (VariableExpression) accessedVariable; List<ClassNode> types = typeCheckingContext.ifElseForWhileAssignmentTracker.get(var); if (types == null) { types = new LinkedList<ClassNode>(); ClassNode type = var.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); types.add(type); typeCheckingContext.ifElseForWhileAssignmentTracker.put(var, types); } types.add(resultType); } } storeType(leftExpression, resultType); {code} To preserve the declared type of a variable, another check should be added after typeCheckAssignment. Does it seem sensible that the inferred type of both the variable and the binary expression as a whole should both be the declared type (that is {{Type}} in {{Type var = value}} and not whatever {{value}} infers to)? If yes, {{resultType}} needs to be set to {{originType}} or {{lType}} under some condition. > each parameter type not correctly inferenced > -------------------------------------------- > > Key: GROOVY-9058 > URL: https://issues.apache.org/jira/browse/GROOVY-9058 > Project: Groovy > Issue Type: Bug > Components: Static compilation > Affects Versions: 2.5.6 > Reporter: Mauro Molinari > Priority: Major > > Consider this Java class: > {code:java} > package test51; > import java.util.List; > public class Foo { > public List<Object[]> bar() { return null; } > }{code} > and this Groovy class: > {code:java} > package test51 > import groovy.transform.CompileStatic > @CompileStatic > class Test51 { > protected void foo() { > List<Object[]> foo = new Foo().bar() > foo.each { row -> > def o = row[0] > } > } > > List bar() { > } > }{code} > This produces a compiler error because {{row}} is resolved as {{Object}} > rather than {{Object[]}}. > A workaround is to declare {{row}} as {{Object[] row}} in the closure > parameter list. -- This message was sent by Atlassian JIRA (v7.6.3#76005)