title: Swift: Specialize method of generic class for function types
body: <p>For generic free functions I can use overloading,
  to essentially specialize the function for function types, like this:</p>
  
  <pre><code>func foo&lt;T&gt;(_ t: T.Type) { print("T is unknown") }
  func foo&lt;P&gt;(_ t: ((P) -&gt; Void).Type) { print("T is a function with one parameter") }
  
  let f: (String) -&gt; Void = { print($0) }    
  foo(type(of: f))   //  prints "T is a function with one parameter"
  </code></pre>
  
  <p>Note the second version of <code>foo()</code> is <em>not</em> protocol-constrained,
  mainly because as far as I know, we can't make function types conform to protocols
  (we can't extend non-nominal types). I could create a <code>OneParamFunction</code> protocol,
  and could use that in a constrained <code>foo()</code>, but I couldn't make all one-parameter
  function types conform to that protocol.</p>
  
  <p>But the above overload works without protocol constraints.</p>
  
  <p>Is something like this possible for an instance method of a generic class?</p>
  
  <p>To me, this syntax would seem most natural, but it's not supported:</p>
  
  <pre><code>class Generic1&lt;T&gt; { init(_ t: T.Type) {} }
  extension Generic1 { func foo() { print("T is unknown") } }
  
  extension Generic1&lt;P&gt;
      where T == ((P) -&gt; Void) {
      func foo() { print("T is a function with one parameter") }
  }
  </code></pre>
  
  <p>The "normal" way of creating protocol-constrained extensions on the Generic class
  would look like this:</p>
  
  <pre><code>extension Generic1 where T: OneParamFunction { ... }
  </code></pre>
  
  <p>but as discussed above, I can't make function types conform to the OneParamFunction protocol.</p>
  
  <p>I also can't just create a single (no overloads / specializations) instance method
  and then forward to the free function, this doesn't work:</p>
  
  <pre><code>class Generic2&lt;T&gt; {
      init(_ t: T.Type) {}
      func foo() { myModule.foo(T.self) }
  }
  
  let f: (String) -&gt; Void = { print($0) }
  Generic2(type(of: f)).foo()   //  prints "unknown T"
  </code></pre>
  
  <p>Compiles, but always calls the unknown-T version, I think because of type erasure.
  Inside Generic2, the compiler doesn't really know what T is.
  Generic2 doesn't define any protocol constraints on T that would help the compiler
  properly dispatch the <code>myModule.foo()</code> call (and it can't have such constraints, see above).</p>
  
  <p>Using method overloading inside the generic class compiles and seems close,
  but still doesn't work, although in this case I'm not sure why.</p>
  
  <pre><code>class Generic3&lt;T&gt; {
      init(_ t: T.Type) {}
      func foo() { print("T is unknown") }
      func foo&lt;P&gt;() where T == ((P) -&gt; Void) { print("T is a function with one parameter") }
  }
  
  let f: (String) -&gt; Void = { print($0) }
  Generic3(type(of: f)).foo()   //  prints "unknown T"
  </code></pre>
  
  <p>Here at the site of calling <code>foo()</code> the type parameter of Generic3 is fully known,
  so it seems to me that the compiler would have all the necessary type information
  to correctly dispatch the call, but that's not what happens, it still prints "unknown T".</p>
  
  <p>Not even repeating the type as a parameter to <code>foo()</code> helps (wouldn't be ideal anyway):</p>
  
  <pre><code>class Generic4&lt;T&gt; {
      init(_ t: T.Type) {}
      func foo(_ t: T.Type) { print("T is unknown") }
      func foo&lt;P&gt;(_ t: T.Type) where T == ((P) -&gt; Void) { print("T is a function with one parameter") }
  }
  
  let f: (String) -&gt; Void = { print($0) }
  Generic4(type(of: f)).foo(type(of: f))   //  still prints "unknown T"
  </code></pre>
  
  <p>Do I have any further options?</p>
  
  <hr>
  
  <p><strong>Update</strong>, in response to Rob Napier's answer. </p>
  
  <p>I think what I wish for here isn't really dynamic dispatch, I'd like to have static dispatch, but based on all the type information known at the <em>call site</em>, rather than based on the type-erased value for <code>T</code> previously inferred during <code>Generic.init()</code>. And that does work with free functions, but not with member functions. </p>
  
  <p>Try this: </p>
  
  <pre><code>func foo&lt;T&gt;(_ t: T.Type) { print("T is unknown") }
  func foo&lt;P&gt;(_ t: ((P) -&gt; Void).Type) { print("T is a function with one parameter") }
  
  func g&lt;T&gt;(_ x: T.Type) -&gt; T.Type { return x }
  let f: (String) -&gt; Void = { print($0) }
  foo(g(type(of: f)))   //  prints "T is a function"
  </code></pre>
  
  <p>This does call the "T is function" version of <code>foo</code>, even though <code>T</code> gets type-erased inside <code>g()</code> too. And I think this is more similar to  <code>Generic(type(of: f)).foo()</code> than Rob's example with <code>g&lt;T&gt;()</code> calling <code>foo()</code> (which is more analogous to calling <code>Generic.foo()</code> from some other member of <code>Generic</code> -- in this case I do understand why <code>T</code> is unknown).  </p>
  
  <p>In both cases (<code>Generic(type(of: f)).foo()</code> vs <code>foo(g(type(of: f)))</code>) there are two types: </p>
  
  <ol>
  <li>the original type of <code>f</code>, and </li>
  <li>the type returned from the first call (<code>Generic.init()</code> / <code>g()</code>). </li>
  </ol>
  
  <p>But apparently the subsequent call to <code>foo()</code> is dispatched based on type #1 when calling the free function <code>foo()</code>, while type #2 is used for dispatching to member function <code>Generic.foo()</code>. </p>
  
  <p>First I thought that the difference has to do with how in the above example <code>g()</code> returns <code>T.Type</code>, while the result of <code>Generic.init()</code> is a <code>Generic&lt;T&gt;</code>, but no: </p>
  
  <pre><code>class Generic_&lt;T&gt; {
      init(_ t: T.Type) {}
      func member_foo() { print("T is unknown") }
      func member_foo&lt;P&gt;() where T == ((P) -&gt; Void) { print("T is a function with one parameter") }
  }
  
  func free_foo&lt;T&gt;(_ g: Generic_&lt;T&gt;) { print("T is unknown") }
  func free_foo&lt;P&gt;(_ t: Generic_&lt;(P) -&gt; Void&gt;) { print("T is a function with one parameter") }
  
  func g_&lt;T&gt;(_ t: T.Type) -&gt; Generic_&lt;T&gt; { return Generic_(t) }
  
  free_foo(g_(type(of: f)))   //  T is function
  Generic_(type(of: f)).member_foo()   //  T is unknown
  </code></pre>
  
  <p>In this case both <code>Generic.init</code> and <code>g()</code> return <code>Generic&lt;T&gt;</code>. And yet, the <code>free_foo()</code> call seems to get dispatched based on the full original type of <code>f</code>, while the <code>member_foo()</code> call does not. I still wonder why. </p>