-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
See commit: 2b50770 in jsInference
Three errors of the form: 'No best common type exists among return expressions.'
Are reported in src\services\inference.ts
The reason for this is the class method 'equals' which we write as:
class PrimitiveTypeInformation implements TypeInforation {
...
public equals(o: TypeInformation) {
return this === o;
}
The cause of the BCT errors is that we are inferring the return type of 'PrimitiveTypeInformation.equals' to be 'any'. Because it is inferred to be 'any', it no longer matches the 'equals' methods in TypeInformation.equals.
Now, why are we inferring the return type of 'PrimitiveTypeInformation.equals' to be any? Based on the spec for return type inference, it appears like it should be boolean. Namely:
A function implementation without a return type annotation is said to be an implicitly typed function. The return type of an implicitly typed function f is inferred from its function body as follows:
• If there are no return statements with expressions in f's function body, the inferred return type is Void.
• Otherwise, if f's function body directly references f or references any implicitly typed functions that through this same analysis reference f, the inferred return type is Any.
• Otherwise, if f is a contextually typed function expression (section 4.9.3), the inferred return type is the union type (section 3.4) of the types of the return statement expressions in the function body, ignoring return statements with no expressions.
• Otherwise, the inferred return type is the first of the types of the return statement expressions in the function body that is a supertype (section 3.10.3) of each of the others, ignoring return statements with no expressions. A compile-time error occurs if no return statement expression has a type that is a supertype of each of the others.
The first three clauses do not apply. The first does not apply because 'equals' does have a return statement. The second does not apply because neither 'equals' nor any functions referenced by it reference 'equals'. The third does not apply because it is not contextually typed.
The fourth does apply. So the return type should be "first of the types of the return statement expressions" (the part about supertypes is not relevant as we only have a single return statement. So we need the type of return statement expression we have. Namely 'this === o'.
The spec states this about === :
The result is always of the Boolean primitive type.
As such, the type of the 'equals' function should be 'boolean' and there should be no BCT error.
Now, i believe this is happening because as we are trying to figure out the type of the return expression, we are also validating/type-checking the entire binary expression. This entails us trying to find the types of both sides of the expression, and then trying to decide if they can be compared against each other. Because we need to check both sides, we end up trying to figure out what type 'this' has. This causes us to go and try to determine the signature for 'equals' which causes us to need its return type. We see that we're already computing that, and we force the return type ot be 'any'.
I think this is incorrect as per the spec.