Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Generic parameter 'T' could not be inferred" error when overloading methods

I have this small enum with 2 constructors. I am getting a "Generic parameter 'T' could not be inferred" error when I try to initialise using an Int argument.

import UIKit

public enum Result<T> {

case Success(T)
case Failure(Int)

   init( any: T) {
       self  = .Success(any)
   }

   init( number: Int) {
       self  = .Failure(number)
   }
}

let a = Result(any: "A String")
print(a)

let b = Result(number: 1)
print(b)

Is there any way to exclude Int from T or somehow give priority to the second initialiser?

Tested on XCode 7.3.1.

like image 528
Foti Dim Avatar asked May 06 '16 14:05

Foti Dim


2 Answers

The issue is not that it's mistaking which constructor to use, the issue is that it needs to know right then when you're typing Result(number: 1) what type T will be. It cannot leave it as a wildcard T for runtime, it must be resolved at compile time.

So you may do this:

let b = Result<String>(number: 1) //letting it know that T would be a String.

The reason this is important is because -- say you wanted to put a bunch of Result in an array... Well... you can't put Result-Int in the same array as a Result-String (unless that array is of type Any), because it's very similar to putting an Int and a String inside an Array. In short, Result is not just one type, it's a set of a bunch of types.

like image 155
Ethan Avatar answered Sep 25 '22 16:09

Ethan


Actually, in your example it's impossible to infer type-parameter T from expression Result(number: 1).

You need to give all the necessary information to the compiler. Take a look at this slightly modified example:

public enum Result<T> {

    case Success(T)
    case Failure(Int)

}

let a = Result.Success("A String")
print(a)

let b: Result<String> = .Failure(1)
print(b)
like image 36
werediver Avatar answered Sep 21 '22 16:09

werediver