ballerina-platform / ballerina-spec

Ballerina Language and Platform Specifications
Other
167 stars 53 forks source link

Infer type of `var x` from contextually expected type of reference to `x` #1208

Open hasithaa opened 1 year ago

hasithaa commented 1 year ago

Consider the following example.

Employee[] employees = check from var emp in foo->query(`SELECT * FROM employees`) select emp;

By looking at the example, it appeared to be ok and emp type should be inferred from LHS from the statement. But this generates a compile-time error (SL Update 3) saying the compiler can't infer the type for the rowType.

After analyzing the implementation and spec, We found that this behavior is compliant with spec. It says,

Iterative use. In the language syntax, this kind of use of a typed-binding-pattern is followed by the in keyword. An iterator is created from the result of evaluating an expression, and the typed-binding-pattern is matched against each value returned by the iterator. When var is used, the type is inferred to be T, where the static type of the expression is an iterable type with value type T.

So implementation tries to infer the binding pattern type from the iterator and action invocation in the iterator tries to get it from the current context, which is from the binding pattern, so both fail to infer the type.

A workaround is to use the exact type in the binding pattern. Is there anything we can do to improve this experience?

jclark commented 1 year ago

I don't think this is fundamentally an iteration issue. Consider

 decimal x = let var d = 1 in d;

This gets a compile-time-error.

Given T x = let var y = E1 in E2, the type of y is currently inferred from the type of expression E1. To make this work we would have to do something completely different.

  1. Contextually expected type of E2 comes from T (we do this already, I think)
  2. Contextually expected type of variable reference to y within E2 produces type for y.
  3. Contextually expected type for y within E2 is used to infer type for y in the variable declaration

This is quite different from anything the language does currently. Note that E2 could be arbitrarily complicated and could contain multiple references to y. There also could be multiple such variables.

This kind of type inference is "infer a type for multiple variables based on how the variables are used in a multiple expressions". This would require a much more sophisticated approach to type inference than what we have currently.