[ https://issues.apache.org/jira/browse/GROOVY-9064?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16810046#comment-16810046 ]
Eric Milles edited comment on GROOVY-9064 at 4/4/19 4:37 PM: ------------------------------------------------------------- In order to maintain the declared type in the face of conditional assignments, like this: {code:groovy} @groovy.transform.CompileStatic void meth() { Map map = getMapFromSomewhere() if (!map) { map = [a:1, b:'2'] } // map infers to LinkedHashMap<String, Serializable<?>> without extra guard condition } {code} A guard condition also needs to be added to {{StaticTypeCheckingVisitor.popAssignmentTracking}}. {code:java} protected Map<VariableExpression, ClassNode> popAssignmentTracking(final Map<VariableExpression, List<ClassNode>> oldTracker) { Map<VariableExpression, ClassNode> assignments = new HashMap<VariableExpression, ClassNode>(); if (!typeCheckingContext.ifElseForWhileAssignmentTracker.isEmpty()) { for (Map.Entry<VariableExpression, List<ClassNode>> entry : typeCheckingContext.ifElseForWhileAssignmentTracker.entrySet()) { VariableExpression key = entry.getKey(); List<ClassNode> allValues = entry.getValue(); // GROOVY-6099: First element of the list may be null, if no assignment was made before the branch List<ClassNode> nonNullValues = new ArrayList<ClassNode>(allValues.size()); for (ClassNode value : allValues) { if (value != null) nonNullValues.add(value); } ClassNode cn = lowestUpperBound(nonNullValues); // GRECLIPSE add if (key.isDynamicTyped()) // GRECLIPSE end storeType(key, cn); assignments.put(key, cn); } } typeCheckingContext.ifElseForWhileAssignmentTracker = oldTracker; return assignments; } {code} was (Author: emilles): In order to maintain the declared type in the face of conditional assignments, like this: {code:groovy} @groovy.transform.CompileStatic void meth() { Map map = getMapFromSomewhere() if (!map) { map = [a:1, b:'2'] } // map infers to LinkedHashMap<String, Serializable<?>> without extra guard condition } {code} A guard condition also needs to be added to {{StaticTypeCheckingVisitor.popAssignmentTracking}}. {code:java} protected Map<VariableExpression, ClassNode> popAssignmentTracking(final Map<VariableExpression, List<ClassNode>> oldTracker) { Map<VariableExpression, ClassNode> assignments = new HashMap<VariableExpression, ClassNode>(); if (!typeCheckingContext.ifElseForWhileAssignmentTracker.isEmpty()) { for (Map.Entry<VariableExpression, List<ClassNode>> entry : typeCheckingContext.ifElseForWhileAssignmentTracker.entrySet()) { VariableExpression key = entry.getKey(); List<ClassNode> allValues = entry.getValue(); // GROOVY-6099: First element of the list may be null, if no assignment was made before the branch List<ClassNode> nonNullValues = new ArrayList<ClassNode>(allValues.size()); for (ClassNode value : allValues) { if (value != null) nonNullValues.add(value); } ClassNode cn = lowestUpperBound(nonNullValues); // GRECLIPSE add -- GROOVY-9064 if (key.isDynamicTyped()) // GRECLIPSE end storeType(key, cn); assignments.put(key, cn); } } typeCheckingContext.ifElseForWhileAssignmentTracker = oldTracker; return assignments; } {code} > STC: explicit declared variable type ignored in favor of assigned value > type(s) > ------------------------------------------------------------------------------- > > Key: GROOVY-9064 > URL: https://issues.apache.org/jira/browse/GROOVY-9064 > Project: Groovy > Issue Type: Bug > Reporter: Eric Milles > Priority: Major > > Follow up to GROOVY-9058. Consider the following: > {code:groovy} > List getSomeRows() { ... } > @groovy.transform.CompileStatic > void meth() { > List<Object[]> rows = getSomeRows() > rows.each { row -> > def col = row[0] > } > } > {code} > The inferred type of {{rows}} is {{List}} and not {{List<Object[]>}} even > though the assignment cleared type checking. This causes the inferred type > of {{row}} to be {{Object}} instead of {{Object[]}}. > Similarly, {{List<String> list = []}} infers as {{ArrayList<String>}} instead > of the explicit declared type, and {{Map<String, ?> map = [:]}} infers to > {{LinkedHasMap<...>}} instead of the declared type. In general, I think as > long as the assignment is compatible, the variable should retain its > explicitly declared type regardless of assignments. -- This message was sent by Atlassian JIRA (v7.6.3#76005)