eclipse-archived/ceylon

imprecise type arg inference calling function with spread operator

Closed this issue · 7 comments

Type inference for zip's Head type arg is imprecise when using the spread operator.

"Good" inference is:

{[String, Integer, Integer]+} a = zip({"a"}, {[1,1]});

where Head is inferred to be ceylon.language::String . But when spreading the args, Head is ceylon.language::String|ceylon.language::Tuple<ceylon.language::Integer,ceylon.language::Integer,ceylon.language::Tuple<ceylon.language::Integer,ceylon.language::Integer,ceylon.language::Empty>>

{[String|Integer[2], Integer, Integer]+} b = zip(*[{"a"}, {[1,1]}]);

we can explicitly provide the desired value for Head:

{[String, Integer, Integer]+} c = zip<String|Integer,String,Integer[2],Nothing,Nothing>({"a"}, {[1,1]});

Is this expected?

It's probably because tuple-ized, we're matching the types:

[{String+}, {Integer[2]+}]

And:

[Iterable<Head,HeadAbsent>, Iterable<Tail,TailAbsent>]

Where you have, after expanding out the tuple type, {String+}|{Integer[2]+} assigned to Iterable<Head,HeadAbsent>|Iterable<Tail,TailAbsent> via the Element type parameter.

I wonder if we should have a special case to just ignore Tuple.Element for the purposes of type inference.

I wonder if we should have a special case to just ignore Tuple.Element for the purposes of type inference.

Indeed, that seems to work rather nicely. AFAICT, it will pretty-much always result in more accurate types inferred... am I wrong?

854282d implements that solution. A bit adhoc, but seems reasonable to me. WDYT, @jvasileff?

WDYT

Yeah, it does sound adhoc, and a bit surprising too since considering more information reduces precision? But given that given First satisfies Element, it does seem fine to ignore Element, IIUC.

WDYT

(take two) I suppose I'll have to read the code to actually come up with an intelligent response.

I have reverted this change because, as noticed by @FroMage, it broke some tests for the curry() function.

A better solution might be to unpack the argument tuple, instead of packing the parameter types as a tuple.

A better solution might be to unpack the argument tuple, instead of packing the parameter types as a tuple.

Yep, done.

HTH @jvasileff.