Inline functions affecting flow typing?


#1

Would it be possible for inlined functions to cause type narrowing as if the code really was copy/pasted into the call site? This would allow for some things like don’t work today but should to work properly, e.g. calling check(foo is Bar).


#2

One possible way to achieve it is to take into account @Contract annotations (KT-8889). Having contract of function expressed in the annotation would make it possible to make some assumptions in data-flow typing even for non-inlined functions.


#3

Yes, both things would be good.


#4

One reason I’m asking for inlined functions to affect flow typing specifically is because they can affect more than just nullability, which the @Contract annotation cannot do.

Consider the following code that would approximate linear types:

https://gist.github.com/mikehearn/ad97d716d4fefac0f78e

It’s conceptually simple but it requires data flow through inlined functions to work. And, of course, it is kind of hacky:

  • It relies on @Deprecated(ERROR). Well I already had a rant about cleaning up this @Deprecated overloading :slight_smile:
  • It has this ugly __dupe thing because inlined functions cannot access private members. This is again a problem of over-strict visibilities hurting the developer more than they are helping.

But it would work:

val x = LinearVal.of(15) val y = x() + 10 val z = x.move() println("result is " + x()) // ERROR HERE

You have to manually inline the move() call by hand to see this in action.

Rust is showing that linear types can be helpful in certain cases, like trying to ensure no two threads can ever access the same data simultaneously.