diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 535f7c5e2952..1c0a7a52fe93 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -534,16 +534,19 @@ private BType getFiniteTypeMatchWithIntLiteral(BLangLiteral literalExpr, BFinite if (intLiteralType != symTable.noType) { return intLiteralType; } + int typeTag = getPreferredMemberTypeTag(finiteType); if (typeTag == TypeTags.NONE) { return symTable.intType; } + if (literalAssignableToFiniteType(literalExpr, finiteType, typeTag)) { BType type = symTable.getTypeFromTag(typeTag); setLiteralValueForFiniteType(literalExpr, type, data); literalExpr.value = String.valueOf(literalValue); return type; } + // Handle out of range ints if (literalValue instanceof Double) { return symTable.floatType; @@ -551,6 +554,25 @@ private BType getFiniteTypeMatchWithIntLiteral(BLangLiteral literalExpr, BFinite if (literalValue instanceof String) { return symTable.decimalType; } + + BType matchingType = null; + for (int tag = TypeTags.FLOAT; tag <= TypeTags.DECIMAL; tag++) { + BType type = symTable.getTypeFromTag(tag); + for (BLangExpression memType : finiteType.getValueSpace()) { + if (memType.getBType().tag == tag) { + matchingType = type; + break; + } + } + + if (matchingType != null) { + break; + } + } + + if (matchingType != null && matchingType != symTable.semanticError && matchingType != symTable.noType) { + return matchingType; + } return symTable.intType; } @@ -652,7 +674,36 @@ private BType getIntegerLiteralType(BLangLiteral literalExpr, Object literalValu } } - BType finiteType = getFiniteTypeWithValuesOfSingleType(expectedUnionType, symTable.intType); + BType matchingType = null; + for (int tag = TypeTags.FLOAT; tag <= TypeTags.DECIMAL; tag++) { + BType type = symTable.getTypeFromTag(tag); + for (BType memType : ((BUnionType) expectedType).getMemberTypes()) { + if (memType.tag == TypeTags.FINITE) { + for (BLangExpression finiteMemType : ((BFiniteType) memType).getValueSpace()) { + if (finiteMemType.getBType().tag == tag) { + matchingType = type; + break; + } + } + break; + } + + if (memType.tag == tag) { + matchingType = type; + break; + } + } + + if (matchingType != null) { + break; + } + } + + if (matchingType == null || matchingType == symTable.semanticError || matchingType == symTable.noType) { + matchingType = symTable.intType; + } + + BType finiteType = getFiniteTypeWithValuesOfSingleType(expectedUnionType, matchingType); if (finiteType != symTable.semanticError) { BType setType = setLiteralValueAndGetType(literalExpr, finiteType, data); if (literalExpr.isFiniteContext) { @@ -888,6 +939,27 @@ private BType getTypeMatchingFloatOrDecimal(BType finiteType, List member } } } + + BType matchingType = null; + if (finiteType.tag == TypeTags.FINITE) { + for (int tag = TypeTags.FLOAT; tag <= TypeTags.DECIMAL; tag++) { + BType type = symTable.getTypeFromTag(tag); + for (BLangExpression memType : ((BFiniteType) finiteType).getValueSpace()) { + if (memType.getBType().tag == tag) { + matchingType = type; + break; + } + } + + if (matchingType != null) { + break; + } + } + } + + if (matchingType != null && matchingType != symTable.semanticError && matchingType != symTable.noType) { + return matchingType; + } return symTable.intType; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/GreaterLessThanOperationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/GreaterLessThanOperationTest.java index ef18b00dab2a..4423b90f86bf 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/GreaterLessThanOperationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/GreaterLessThanOperationTest.java @@ -186,7 +186,7 @@ public void testSubtractStmtNegativeCases() { BAssertUtil.validateError(resultNegative, index++, "operator '>=' not defined for " + "'NumberSet[]' and 'NumberSet[]'", 158, 18); BAssertUtil.validateError(resultNegative, index++, "incompatible types: expected 'OneOrTwo', found " + - "'int'", 167, 21); + "'float'", 168, 21); BAssertUtil.validateError(resultNegative, index++, "operator '<' not defined for 'OneOrTwo[]' and " + "'OneOrTwo[]'", 169, 18); BAssertUtil.validateError(resultNegative, index++, "operator '<=' not defined for 'OneOrTwo[]' and " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/FiniteTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/FiniteTypeTest.java index c9098cdf20dd..5b4b8714928a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/FiniteTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/FiniteTypeTest.java @@ -243,8 +243,8 @@ public void testFiniteTypeWithConstants() { public void testFiniteTypeWithNumericConstants() { Object val = BRunUtil.invoke(result, "testFiniteTypeWithNumericConstants"); BArray returns = (BArray) val; - Assert.assertTrue(returns.get(0) instanceof Long, "Type mismatch"); - Assert.assertEquals(returns.get(0), 5L, "Value mismatch"); + Assert.assertTrue(returns.get(0) instanceof Double, "Type mismatch"); + Assert.assertEquals(returns.get(0), 5.0, "Value mismatch"); Assert.assertTrue(returns.get(1) instanceof Double, "Type mismatch"); Assert.assertEquals(returns.get(1), 5.0, "Value mismatch"); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/assign/AssignStmtTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/assign/AssignStmtTest.java index 75b1181418f4..36788ec2cec4 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/assign/AssignStmtTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/assign/AssignStmtTest.java @@ -215,6 +215,28 @@ public void testAssignmentNegativeCases() { "found 'table'", 138, 11); BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'int', " + "found 'table'", 141, 12); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo', " + + "found 'float'", 147, 13); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo2', " + + "found 'float'", 154, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo2', " + + "found 'float'", 157, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo2', " + + "found 'float'", 158, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo2', " + + "found 'float'", 159, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo2', " + + "found 'float'", 160, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo3', " + + "found 'float'", 166, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo3', " + + "found 'float'", 169, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo3', " + + "found 'float'", 170, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo3', " + + "found 'float'", 171, 14); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'Foo3', " + + "found 'float'", 172, 14); Assert.assertEquals(resultNegative.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java index 064f81b60b7a..74fda0793ff8 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java @@ -584,7 +584,6 @@ public Object[] finiteTypeAsBroaderTypesAndFiniteTypeFunctions() { "testFiniteTypeInUnionAsComplexFiniteTypes_4", "testFiniteTypeInUnionAsComplexFiniteTypes_5", "testFiniteTypeInUnionAsComplexFiniteTypes_6", - "testFiniteTypeInUnionAsComplexFiniteTypes_7", "testFiniteTypeAsFiniteTypeWithIntersectionPositive", "testFiniteTypeAsBroaderTypeInStructurePositive" }; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java index f0b1aa5c3252..a6cc640a7e8d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java @@ -82,19 +82,19 @@ public void testInvalidLiteralAssignment() { 102, 13); validateError(resultNegativeTwo, i++, "incompatible types: expected '(t|t2)', found 'decimal'", 107, 14); - validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo', found 'float'", 116, 14); - validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo2', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo2', found 'decimal'", 117, 15); - validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo4', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected 'Foo4', found 'float'", 118, 15); validateError(resultNegativeTwo, i++, "incompatible types: expected '\"chiran\"', found 'int'", 119, 18); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 123, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1.0f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1.0f', found 'float'", 124, 13); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1.121f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1.121f', found 'float'", 125, 15); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2e12f', found 'float'", 126, 16); @@ -104,7 +104,7 @@ public void testInvalidLiteralAssignment() { 128, 18); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2e12f', found 'decimal'", 129, 16); - validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'decimal'", 131, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2d', found 'float'", 132, 14); @@ -118,17 +118,17 @@ public void testInvalidLiteralAssignment() { 139, 22); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2e12f', found 'decimal'", 140, 20); - validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'decimal'", 142, 16); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2d', found 'float'", 143, 18); - validateError(resultNegativeTwo, i++, "incompatible types: expected 'Float1', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected 'Float1', found 'float'", 148, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 150, 8); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1.0f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1.0f', found 'float'", 151, 9); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1.121f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1.121f', found 'float'", 152, 11); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2e12f', found 'float'", 153, 12); @@ -138,7 +138,7 @@ public void testInvalidLiteralAssignment() { 155, 14); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2e12f', found 'decimal'", 156, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'decimal'", 158, 8); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.2d', found 'float'", 159, 10); @@ -148,19 +148,19 @@ public void testInvalidLiteralAssignment() { "found 'decimal'", 161, 15); validateError(resultNegativeTwo, i++, "incompatible types: expected '12.1d', found 'float'", 162, 11); - validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'decimal'", 165, 9); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 165, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '0.1219e-1f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '0.1219e-1f', found 'float'", 166, 9); - validateError(resultNegativeTwo, i++, "incompatible types: expected '0x.12p12f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '0x.12p12f', found 'float'", 166, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found '1f'", 178, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '3f', found '2d'", 179, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'int'", + validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 183, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'string'", 187, 12); @@ -242,7 +242,7 @@ public void testInvalidLiteralAssignment() { 290, 20); validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 296, 12); - validateError(resultNegativeTwo, i, "incompatible types: expected '1f', found 'int'", + validateError(resultNegativeTwo, i, "incompatible types: expected '1f', found 'float'", 297, 12); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeTest.java index f95bf7cbc004..b4112a7e3c06 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeTest.java @@ -265,8 +265,8 @@ public void testFiniteTypeWithConstants() { @Test public void testFiniteTypeWithNumericConstants() { BArray returns = (BArray) BRunUtil.invoke(result, "testFiniteTypeWithNumericConstants"); - Assert.assertTrue(returns.get(0) instanceof Long, "Type mismatch"); - Assert.assertEquals(returns.get(0), 5L, "Value mismatch"); + Assert.assertTrue(returns.get(0) instanceof Double, "Type mismatch"); + Assert.assertEquals(returns.get(0), 5.0d, "Value mismatch"); Assert.assertTrue(returns.get(1) instanceof Double, "Type mismatch"); Assert.assertEquals(returns.get(1), 5.0d, "Value mismatch"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/literals/numeric_literal_assignment.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/literals/numeric_literal_assignment.bal index 0c3496e5457a..38b2ec6a3d51 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/literals/numeric_literal_assignment.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/literals/numeric_literal_assignment.bal @@ -96,7 +96,7 @@ function testIntLiteralAsFloatInUnion() returns boolean { boolean result = x is float && f == x; Qux|float y = 12; - return result && y is float && f == y; + return result && y is decimal && d == y; } function testIntLiteralAsFloatInUnion_2() returns boolean { @@ -134,7 +134,7 @@ function testIntLiteralAsIntViaFiniteType() returns boolean { boolean result = y is int && i == y; float|Foo|Bar z = 12; - return result && z is int && i == z; + return result && z is float && f == z; } function testIntLiteralAsByteViaFiniteType() returns boolean { @@ -152,7 +152,7 @@ function testIntLiteralAsFloatViaFiniteType() returns boolean { boolean result = y is float && f == y; decimal|Bar|Qux z = 12; - return result && z is float && f == z; + return result && z is decimal && d == z; } function testIntLiteralAsDecimalViaFiniteType() returns boolean { diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/assign/assign-stmt-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/assign/assign-stmt-negative.bal index cd8e30a5eb49..e5170a71e6c9 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/assign/assign-stmt-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/assign/assign-stmt-negative.bal @@ -140,3 +140,34 @@ function assignTableCtrToIncompatibleType() { [int, string] a = [1, "a"]; a[0] = table[]; // error } + +type Foo decimal|2f; + +function assignCustomTypeToFloat() { + Foo _ = 3; // error: incompatible types: expected 'Foo', found 'float' + Foo _ = 2; +} + +type Foo2 decimal|3d|1|5d|3f|4d|2f|7d|6; + +function assignCustomTypeToFloat2() { + Foo2 _ = 1; // error: incompatible types: expected 'Foo2', found 'float' + Foo2 _ = 2; + Foo2 _ = 3; + Foo2 _ = 4; // error: incompatible types: expected 'Foo2', found 'float' + Foo2 _ = 5; // error: incompatible types: expected 'Foo2', found 'float' + Foo2 _ = 6; // error: incompatible types: expected 'Foo2', found 'float' + Foo2 _ = 7; // error: incompatible types: expected 'Foo2', found 'float' +} + +type Foo3 decimal|1|5d|3f|4d|2f|7d|6; + +function assignCustomTypeToFloat3() { + Foo3 _ = 1; // error: incompatible types: expected 'Foo3', found 'float' + Foo3 _ = 2; + Foo3 _ = 3; + Foo3 _ = 4; // error: incompatible types: expected 'Foo3', found 'float' + Foo3 _ = 5; // error: incompatible types: expected 'Foo3', found 'float' + Foo3 _ = 6; // error: incompatible types: expected 'Foo3', found 'float' + Foo3 _ = 7; // error: incompatible types: expected 'Foo3', found 'float' +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/type-guard.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/type-guard.bal index 4c4ecd5d090d..e37dd76a63c5 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/type-guard.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/type-guard.bal @@ -668,18 +668,12 @@ function testFiniteTypeInUnionAsComplexFiniteTypes_4() returns boolean { } function testFiniteTypeInUnionAsComplexFiniteTypes_5() returns boolean { - FooBarOneTwoBoolean f = 1; - [string, FooBarInt|OneTwo|boolean] [s, v] = finiteTypeAsComplexFiniteTypesHelperTwo(f); - return s == "FooBarInt" && f == v; -} - -function testFiniteTypeInUnionAsComplexFiniteTypes_6() returns boolean { FooBarOneTwoBoolean f = 2.0; [string, FooBarInt|OneTwo|boolean] [s, v] = finiteTypeAsComplexFiniteTypesHelperTwo(f); return s == "OneTwo" && f == v; } -function testFiniteTypeInUnionAsComplexFiniteTypes_7() returns boolean { +function testFiniteTypeInUnionAsComplexFiniteTypes_6() returns boolean { FooBarOneTwoBoolean f = false; [string, FooBarInt|OneTwo|boolean] [s, v] = finiteTypeAsComplexFiniteTypesHelperTwo(f); return s == "boolean" && f == v; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/finite/finite-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/finite/finite-type.bal index 9f86e7e63df2..2946b8598d2b 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/finite/finite-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/finite/finite-type.bal @@ -258,7 +258,7 @@ const decimal DCONST = 5; type Number DCONST|FCONST|ICONST|BCONST; function testFiniteTypeWithNumericConstants() returns [Number, Number] { - Number n1 = 5; + Number n1 = 5.0; Number n2 = 5.0; return [n1, n2]; }