Skip to content

Commit 904bb93

Browse files
committed
GROOVY-10295
1 parent 32933fa commit 904bb93

File tree

4 files changed

+64
-46
lines changed

4 files changed

+64
-46
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+21
Original file line numberDiff line numberDiff line change
@@ -4042,4 +4042,25 @@ public void testTypeChecked10283() {
40424042

40434043
runConformTest(sources);
40444044
}
4045+
4046+
@Test
4047+
public void testTypeChecked10295() {
4048+
//@formatter:off
4049+
String[] sources = {
4050+
"Main.groovy",
4051+
"@groovy.transform.TypeChecked\n" +
4052+
"List<Number> foo() {\n" +
4053+
" return [1,2,3]\n" +
4054+
"}\n" +
4055+
"@groovy.transform.TypeChecked\n" +
4056+
"Map<String, Object> bar() {\n" +
4057+
" return [date: new Date(), string: '']\n" +
4058+
"}\n" +
4059+
"foo()\n" +
4060+
"bar()\n",
4061+
};
4062+
//@formatter:on
4063+
4064+
runConformTest(sources);
4065+
}
40454066
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+19-11
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@
215215
import static org.codehaus.groovy.syntax.Types.COMPARE_TO;
216216
import static org.codehaus.groovy.syntax.Types.DIVIDE;
217217
import static org.codehaus.groovy.syntax.Types.DIVIDE_EQUAL;
218-
import static org.codehaus.groovy.syntax.Types.EQUAL;
219218
import static org.codehaus.groovy.syntax.Types.FIND_REGEX;
220219
import static org.codehaus.groovy.syntax.Types.INTDIV;
221220
import static org.codehaus.groovy.syntax.Types.INTDIV_EQUAL;
@@ -1625,9 +1624,8 @@ protected void checkGroovyConstructorMap(final Expression receiver, final ClassN
16251624
if (!isAssignableTo(valueType, toBeAssignedTo)
16261625
*/
16271626
Expression valueExpression = entryExpression.getValueExpression();
1628-
BinaryExpression assign = new BinaryExpression(keyExpr, GeneralUtils.ASSIGN, valueExpression);
1629-
assign.setSourcePosition(entryExpression);
1630-
ClassNode resultType = getResultType(toBeAssignedTo, ASSIGN, valueType, assign);
1627+
BinaryExpression dummy = assignX(keyExpr, valueExpression, entryExpression);
1628+
ClassNode resultType = getResultType(toBeAssignedTo, ASSIGN, valueType, dummy);
16311629
if (!checkCompatibleAssignmentTypes(toBeAssignedTo, resultType, valueExpression)
16321630
// GRECLIPSE end
16331631
&& !extension.handleIncompatibleAssignment(toBeAssignedTo, valueType, entryExpression)) {
@@ -2707,6 +2705,7 @@ public void visitReturnStatement(ReturnStatement statement) {
27072705
}
27082706
}
27092707

2708+
/* GRECLIPSE edit
27102709
private ClassNode infer(ClassNode target, ClassNode source) {
27112710
DeclarationExpression virtualDecl = new DeclarationExpression(
27122711
varX("{target}", target),
@@ -2718,6 +2717,7 @@ private ClassNode infer(ClassNode target, ClassNode source) {
27182717
27192718
return !missesGenericsTypes(newlyInferred) ? newlyInferred : null;
27202719
}
2720+
*/
27212721

27222722
protected ClassNode checkReturnType(final ReturnStatement statement) {
27232723
Expression expression = statement.getExpression();
@@ -2753,16 +2753,17 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
27532753
}
27542754
// GRECLIPSE end
27552755
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
2756-
if (enclosingMethod != null) {
2757-
if (!enclosingMethod.isVoidMethod()
2758-
&& !type.equals(void_WRAPPER_TYPE)
2756+
if (enclosingMethod != null && !enclosingMethod.isVoidMethod()) {
2757+
ClassNode returnType = enclosingMethod.getReturnType();
2758+
if (!isNullConstant(expression)
27592759
&& !type.equals(VOID_TYPE)
2760-
&& !checkCompatibleAssignmentTypes(enclosingMethod.getReturnType(), type, null, false)
2761-
&& !(isNullConstant(expression))) {
2760+
&& !type.equals(void_WRAPPER_TYPE)
2761+
&& !checkCompatibleAssignmentTypes(returnType, type, null, false)) {
27622762
if (!extension.handleIncompatibleReturnType(statement, type)) {
2763-
addStaticTypeError("Cannot return value of type " + type.toString(false) + " on method returning type " + enclosingMethod.getReturnType().toString(false), expression);
2763+
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " on method returning type " + prettyPrintType(returnType), expression);
27642764
}
2765-
} else if (!enclosingMethod.isVoidMethod()) {
2765+
} else {
2766+
/* GRECLIPSE edit -- GROOVY-10295
27662767
ClassNode previousType = getInferredReturnType(enclosingMethod);
27672768
ClassNode inferred = previousType == null ? type : lowestUpperBound(type, previousType);
27682769
if (implementsInterfaceOrIsSubclassOf(inferred, enclosingMethod.getReturnType())) {
@@ -2779,6 +2780,13 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
27792780
} else {
27802781
return enclosingMethod.getReturnType();
27812782
}
2783+
*/
2784+
if (implementsInterfaceOrIsSubclassOf(type, returnType)) {
2785+
BinaryExpression dummy = assignX(varX("{target}", returnType), expression, statement);
2786+
ClassNode resultType = getResultType(returnType, ASSIGN, type, dummy);
2787+
checkTypeGenerics(returnType, resultType, expression);
2788+
}
2789+
// GRECLIPSE end
27822790
}
27832791
}
27842792
return type;

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,7 @@ public void visitReturnStatement(final ReturnStatement statement) {
24392439
returnListener.returnStatementAdded(statement);
24402440
}
24412441

2442+
/* GRECLIPSE edit
24422443
private ClassNode infer(final ClassNode target, final ClassNode source) {
24432444
DeclarationExpression virtualDecl = new DeclarationExpression(
24442445
varX("{target}", target),
@@ -2450,6 +2451,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) {
24502451
24512452
return !missesGenericsTypes(newlyInferred) ? newlyInferred : null;
24522453
}
2454+
*/
24532455

24542456
protected ClassNode checkReturnType(final ReturnStatement statement) {
24552457
Expression expression = statement.getExpression();
@@ -2479,14 +2481,16 @@ else if (inferredReturnType != null && !GenericsUtils.hasUnresolvedGenerics(infe
24792481
}
24802482
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
24812483
if (enclosingMethod != null && !enclosingMethod.isVoidMethod()) {
2484+
ClassNode returnType = enclosingMethod.getReturnType();
24822485
if (!isNullConstant(expression)
24832486
&& !type.equals(VOID_TYPE)
24842487
&& !type.equals(void_WRAPPER_TYPE)
2485-
&& !checkCompatibleAssignmentTypes(enclosingMethod.getReturnType(), type, null, false)) {
2488+
&& !checkCompatibleAssignmentTypes(returnType, type, null, false)) {
24862489
if (!extension.handleIncompatibleReturnType(statement, type)) {
2487-
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " on method returning type " + prettyPrintType(enclosingMethod.getReturnType()), expression);
2490+
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " on method returning type " + prettyPrintType(returnType), expression);
24882491
}
24892492
} else {
2493+
/* GRECLIPSE edit -- GROOVY-10295
24902494
ClassNode previousType = getInferredReturnType(enclosingMethod);
24912495
ClassNode inferred = previousType == null ? type : lowestUpperBound(type, previousType);
24922496
if (implementsInterfaceOrIsSubclassOf(inferred, enclosingMethod.getReturnType())) {
@@ -2501,6 +2505,13 @@ else if (inferredReturnType != null && !GenericsUtils.hasUnresolvedGenerics(infe
25012505
} else {
25022506
return enclosingMethod.getReturnType();
25032507
}
2508+
*/
2509+
if (implementsInterfaceOrIsSubclassOf(type, returnType)) {
2510+
BinaryExpression dummy = assignX(varX("{target}", returnType), expression, statement);
2511+
ClassNode resultType = getResultType(returnType, ASSIGN, type, dummy);
2512+
checkTypeGenerics(returnType, resultType, expression);
2513+
}
2514+
// GRECLIPSE end
25042515
}
25052516
}
25062517
return type;

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+11-33
Original file line numberDiff line numberDiff line change
@@ -2245,18 +2245,6 @@ public void visitReturnStatement(final ReturnStatement statement) {
22452245
returnListener.returnStatementAdded(statement);
22462246
}
22472247

2248-
private ClassNode infer(final ClassNode target, final ClassNode source) {
2249-
DeclarationExpression virtualDecl = new DeclarationExpression(
2250-
varX("{target}", target),
2251-
Token.newSymbol(EQUAL, -1, -1),
2252-
varX("{source}", source)
2253-
);
2254-
virtualDecl.visit(this);
2255-
ClassNode newlyInferred = virtualDecl.getNodeMetaData(INFERRED_TYPE);
2256-
2257-
return !missesGenericsTypes(newlyInferred) ? newlyInferred : null;
2258-
}
2259-
22602248
protected ClassNode checkReturnType(final ReturnStatement statement) {
22612249
Expression expression = statement.getExpression();
22622250
ClassNode type;
@@ -2280,31 +2268,21 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
22802268
}
22812269
return type;
22822270
}
2271+
22832272
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
2284-
if (enclosingMethod != null && !enclosingMethod.isVoidMethod()) {
2285-
if (!isNullConstant(expression) && !isPrimitiveVoid(getUnwrapper(type))
2286-
&& !checkCompatibleAssignmentTypes(enclosingMethod.getReturnType(), type, null, false)) {
2273+
if (enclosingMethod != null && !enclosingMethod.isVoidMethod() && !enclosingMethod.isDynamicReturnType()) {
2274+
ClassNode returnType = enclosingMethod.getReturnType();
2275+
if (!isPrimitiveVoid(getUnwrapper(type)) && !checkCompatibleAssignmentTypes(returnType, type, null, false)) {
22872276
if (!extension.handleIncompatibleReturnType(statement, type)) {
2288-
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " on method returning type " + prettyPrintType(enclosingMethod.getReturnType()), expression);
2289-
}
2290-
} else {
2291-
ClassNode previousType = getInferredReturnType(enclosingMethod);
2292-
ClassNode inferred = previousType == null ? type : lowestUpperBound(type, previousType);
2293-
if (implementsInterfaceOrIsSubclassOf(inferred, enclosingMethod.getReturnType())) {
2294-
if (missesGenericsTypes(inferred)) {
2295-
ClassNode newlyInferred = infer(enclosingMethod.getReturnType(), type);
2296-
if (newlyInferred != null) {
2297-
type = newlyInferred;
2298-
}
2299-
} else {
2300-
checkTypeGenerics(enclosingMethod.getReturnType(), inferred, expression);
2301-
}
2302-
} else {
2303-
return enclosingMethod.getReturnType();
2277+
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " on method returning type " + prettyPrintType(returnType), expression);
23042278
}
2279+
} else if (implementsInterfaceOrIsSubclassOf(type, returnType)) {
2280+
BinaryExpression dummy = assignX(varX("{target}", returnType), expression, statement);
2281+
ClassNode resultType = getResultType(returnType, ASSIGN, type, dummy); // GROOVY-10295
2282+
checkTypeGenerics(returnType, resultType, expression);
23052283
}
23062284
}
2307-
return type;
2285+
return null;
23082286
}
23092287

23102288
protected void addClosureReturnType(final ClassNode returnType) {
@@ -4577,7 +4555,7 @@ protected ClassNode getResultType(ClassNode left, final int op, final ClassNode
45774555
if (leftExpression instanceof VariableExpression) {
45784556
ClassNode initialType = getOriginalDeclarationType(leftExpression);
45794557

4580-
if (isPrimitiveType(right) && initialType.isDerivedFrom(Number_TYPE)) {
4558+
if (isPrimitiveType(rightRedirect) && initialType.isDerivedFrom(Number_TYPE)) {
45814559
return getWrapper(right);
45824560
}
45834561

0 commit comments

Comments
 (0)