finos / legend-pure

Legend Pure module
https://legend.finos.org
Apache License 2.0
66 stars 136 forks source link

Fix contravariant type inference with type parameters #781

Closed kevin-m-knight-gs closed 6 months ago

kevin-m-knight-gs commented 6 months ago

Fix a bug with contravariant type inference with non-concrete generic types. This can occur with function expressions that return function types where one of the parameter types might be non-concrete. For example, consider this function:

function collectionToStrings<T|m>(col:T[m], func:Function<{T[1]->String[1]}>[0..1]):String[m]
{
    let toStringFunc = if($func->isEmpty(), |{x:T[1] | $x->toString()}, |$func->toOne());
    $col->map(x | $toStringFunc->eval($x));
}

The issue would occur in computing the type for the if expression. Before the fix, the type would be computed as Function<Nil[1]->String[1]>, whereas it should be Function<T[1]->String[1]>.

This also improves how generic types are hashed when finding the best common generic type. The previous hashing strategy was not fully correct for the case where the raw type was a function type. That is, it might return different hash codes for function types that were equal. The historical reason for this was that the cost of figuring out whether something was a function type outweighed the benefits of having a fully correct hashing strategy. However, now the cost of figuring out whether something is a function type is significantly less, so the benefits now outweigh the costs. The hashing strategy is now fully correct.

In passing, do some clean ups, bug fixes, and other improvements that came up while investigating the issue in question.

github-actions[bot] commented 6 months ago

Test Results

   541 files     541 suites   24m 7s :stopwatch: 4 005 tests 3 973 :heavy_check_mark: 32 :zzz: 0 :x: 5 371 runs  5 339 :heavy_check_mark: 32 :zzz: 0 :x:

Results for commit fc5180cf.