title: Kotlin suspend modifier changes function signature, but compiler reports overload error
body: <h1>Introduction</h1>
  
  <p>Given two functions, <code>foo()</code> and <code>foo()</code>, the first one is standard and the second is suspendible</p>
  
  <pre><code>fun foo(x: Int): Int {
      return 2*x
  }
  
  suspend fun foo(x: Int): Int {
      return 4*x
  }
  </code></pre>
  
  <p>The following code does not compile, because two functions with the same signature are conflicting.</p>
  
  <blockquote>
    <p>conflicting overloads: public fun foo(x: Int): Int defined in file t.kt, public suspend fun foo(x: Int): Int defined in file t.kt</p>
  </blockquote>
  
  <h1>Suspending Functions</h1>
  
  <p>If my understanding of suspending function is correct, then:</p>
  
  <ol>
  <li>A <code>Continuation</code> parameter is added to a suspending function, used by the state machine to stop and start the suspending code</li>
  <li>The return type used under the hood for suspend-marked functions is <code>Any</code> (Thus <code>Object</code> for java)</li>
  </ol>
  
  <p>Those two side effects in theory should be enough to alter the second <code>foo()</code> function signature, hence to view the suspend-marked functions differently from the first one.</p>
  
  <h1>Analysis</h1>
  
  <p>At first, I have supposed that the function signature check may be performed before actually compiling the code into bytecode.
  However, having the two presented functions turned into actual bytecode actually results in 2 methods having 2 <em>different</em> signatures.</p>
  
  <h3>Java: t.kt -> t.decompiled.java</h3>
  
  <pre><code>@Metadata(
      mv = {1, 1, 16},
      bv = {1, 0, 3},
      k = 2,
      d1 = {"\u0000\n\n\u0000\n\u0002\u0010\b\n\u0002\b\u0003\u001a\u000e\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0001\u001a\u0019\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0001H\u0086@ø\u0001\u0000¢\u0006\u0002\u0010\u0003\u0082\u0002\u0004\n\u0002\b\u0019¨\u0006\u0004"},
      d2 = {"foo", "", "x", "(ILkotlin/coroutines/Continuation;)Ljava/lang/Object;", "app"}
  )
  
  public final class TKt {
      public static final int foo(int x) {
          return 2 * x;
      }
  
      @Nullable
      public static final Object foo(int x, @NotNull Continuation $completion) {
         return Boxing.boxInt(4 * x);
      }
  }
  </code></pre>
  
  <h3>KB: fun foo(x: Int): Int</h3>
  
  <pre><code>// access flags 0x19
  public final static foo(I)I
     // annotable parameter count: 1 (visible)
     // annotable parameter count: 1 (invisible)
     L0
      LINENUMBER 4 L0
      ICONST_2
      ILOAD 0
      IMUL
      IRETURN
     L1
      LOCALVARIABLE x I L0 L1 0
      MAXSTACK = 2
      MAXLOCALS = 1
  </code></pre>
  
  <h3>KB: suspend fun foo(x: Int): Int</h3>
  
  <pre><code>  // access flags 0x19
    // signature (ILkotlin/coroutines/Continuation&lt;-Ljava/lang/Integer;&gt;;)Ljava/lang/Object;
    // declaration:  foo(int, kotlin.coroutines.Continuation&lt;? super java.lang.Integer&gt;)
    public final static foo(ILkotlin/coroutines/Continuation;)Ljava/lang/Object; @Lorg/jetbrains/annotations/Nullable;() // invisible
     // annotable parameter count: 2 (visible)
     // annotable parameter count: 2 (invisible)
     @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1
     L0
      LINENUMBER 8 L0
      ICONST_4
      ILOAD 0
      IMUL
      INVOKESTATIC kotlin/coroutines/jvm/internal/Boxing.boxInt (I)Ljava/lang/Integer;
      ARETURN
     L1
      LOCALVARIABLE x I L0 L1 0
      LOCALVARIABLE $completion Lkotlin/coroutines/Continuation; L0 L1 1
      MAXSTACK = 2
      MAXLOCALS = 2
  </code></pre>
  
  <h1>Scoped Calls</h1>
  
  <p>At this point I thought that it is not always possible for kotlin to decide which function to call. 
  Sure, these two functions are completely different and separate, their signature has not even a partial match (Different return type and arguments)</p>
  
  <p>The point is that in the kotlin word, the suspending function can only be called from inside a coroutine scope, but the normal function can be called from both places.
  The following table can serve as a great example to graphically analyse the situation.</p>
  
  <pre><code>+---------------+---------------+-----------------+
  |               | Default Scope | Coroutine Scope |
  +---------------+---------------+-----------------+
  | foo()         | ✓             | ✓               |
  +---------------+---------------+-----------------+
  | suspend foo() | ✘             | ✓               |
  +---------------+---------------+-----------------+
  </code></pre>
  
  <p>The only scenario that may involve a definition collision between these two entities is the following.</p>
  
  <pre><code>fun foo(x: Int): Int {
      return 2*x
  }
  
  suspend fun foo(x: Int): Int {
      return 4*x
  }
  
  GlobalScope.launch {
      println(foo(7))
  }
  </code></pre>
  
  <p>In this case, without an hypothetical (a.k.a. Existing only in my head) operator letting Kotlin know which function to invoke, if the suspendible one or the standard one, you can't be sure about which function you are invoking.</p>
  
  <p>Is this analysis correct or am i missing something in between?</p>
  
  <h1>Conclusion</h1>
  
  <p>This question will be linked in a YouTrack issue with a similar content, and this may be the starting point for a compiler improvement (Maybe differentiating overload errors from suspendible clashing with standard function error), or for a new Kotlin feature, expanding the suspendible functions interoperability with normal functions (I'm imagining a sort of spread-like operator which is prefixed to the function call, and the presence of the operator differentiates one call from another).</p>