Closed
Description
When a type parameter is used in the second parameter list of a method, the inference is not precise enough, unless it also part of the return type:
object Test {
def one[T](ev: T): Nothing = ???
def two1[T](ev: T)(): Nothing = ???
def two2a[T]()(ev: T): Nothing = ???
def two2b[T]()(ev: T): T = ???
def two3a[T](ev: T)(ev2: T): Nothing = ???
def two3b[T](ev: T)(ev2: T): T = ???
def test = {
one(42) // Correct: Infer T=Int
two1(42)() // Correct: Infer T=Int
two2a()(42) // Wrong: Infer T=Any
two2b()(42) // Correct: Infer T=Int
two3a(42)(42) // Wrong: Infer T=Any
two3b(42)(42) // Correct: Infer T=Int
}
}
Here's how one(42)
is typed:
[log frontend] ==> typing one(42)?
[log frontend] ==> typing one?
typed ident one in method test
[log frontend] ==> adapting Test.one of type ([T](ev: T)Nothing)(Test.one) to FunProto(42):??
[log frontend] <== adapting Test.one of type ([T](ev: T)Nothing)(Test.one) to FunProto(42):? = Test.one[(T?)]
[log frontend] <== typing Test.one = Test.one[(T?)]
[log frontend] ==> adapting 42 of type Int(42) to (T?)?
adding constraint T >: Int(42) to
Constraint(
uninstVars = (T?);
constrained types = [T](ev: T)Nothing
bounds =
T
ordering =
)
added constraint T >: Int(42) to
Constraint(
uninstVars = (T? >: Int(42));
constrained types = [T](ev: T)Nothing
bounds =
T >: Int(42)
ordering =
) = true
[log frontend] <== adapting 42 of type Int(42) to (T? >: Int(42)) = 42
[log frontend] ==> adapting Test.one[(T? >: Int(42))](42) of type Nothing to ??
interpolate undet vars in Nothing, pos = [263..266..270], mode = Mode(ImplicitsEnabled,InferringReturnType), undets = ArrayBuffer((T? >: Int(42))@[263..266])
qualifying undet vars: ArrayBuffer(TypeVar(PolyParam(T)) / (T? >: Int(42))), constraint: Constraint(
uninstVars = (T? >: Int(42));
constrained types = [T](ev: T)Nothing
bounds =
T >: Int(42)
ordering =
)
instantiating non-occurring (T? >: Int(42)) in Nothing
approx T, from below = true, bound = Int(42), inst = Int(42)
instantiating (T? >: Int(42)) with Int
[log frontend] <== adapting Test.one[Int'](42) of type Nothing to ? = Test.one[Int'](42)
[log frontend] <== typing Test.one(42) = Test.one[Int'](42)
Here's how two2a()(42)
is typed:
[log frontend] ==> typing two2a()(42)?
[log frontend] ==> typing two2a()?
[log frontend] ==> typing two2a?
typed ident two2a in method test
[log frontend] ==> adapting Test.two2a of type ([T]()(ev: T)Nothing)(Test.two2a) to FunProto():??
[log frontend] <== adapting Test.two2a of type ([T]()(ev: T)Nothing)(Test.two2a) to FunProto():? = Test.two2a[(T?)]
[log frontend] <== typing Test.two2a = Test.two2a[(T?)]
[log frontend] ==> adapting Test.two2a[(T?)]() of type (ev: (T?))Nothing to FunProto(42):??
interpolate undet vars in (ev: (T?))Nothing, pos = [334..339..341], mode = Mode(ImplicitsEnabled,InferringReturnType), undets = ArrayBuffer((T?)@[334..339])
qualifying undet vars: ArrayBuffer(TypeVar(PolyParam(T)) / (T?)), constraint: Constraint(
uninstVars = (T?);
constrained types = [T]()(ev: T)Nothing
bounds =
T
ordering =
)
interpolate contravariant (T?) in (ev: (T?))Nothing
approx T, from below = false, bound = Any, inst = Any
instantiating (T?) with Any
[log frontend] <== adapting Test.two2a[Any']() of type (ev: Any)Nothing to FunProto(42):? = Test.two2a[Any']()
[log frontend] <== typing Test.two2a() = Test.two2a[Any']()
[log frontend] ==> adapting 42 of type Int(42) to Any?
[log frontend] <== adapting 42 of type Int(42) to Any = 42
[log frontend] ==> adapting Test.two2a[Any']()(42) of type Nothing to ??
[log frontend] <== adapting Test.two2a[Any']()(42) of type Nothing to ? = Test.two2a[Any']()(42)
[log frontend] <== typing Test.two2a()(42) = Test.two2a[Any']()(42)
And here's how two2b()(42)
is typed:
[error] [log frontend] ==> typing two2b()(42)?
[error] [log frontend] ==> typing two2b()?
[error] [log frontend] ==> typing two2b?
[info] typed ident two2b in method test
[error] [log frontend] ==> adapting Test.two2b of type ([T]()(ev: T)T)(Test.two2b) to FunProto():??
[error] [log frontend] <== adapting Test.two2b of type ([T]()(ev: T)T)(Test.two2b) to FunProto():? = Test.two2b[(T?)]
[error] [log frontend] <== typing Test.two2b = Test.two2b[(T?)]
[error] [log frontend] ==> adapting Test.two2b[(T?)]() of type (ev: (T?))(T?) to FunProto(42):??
[info] interpolate undet vars in (ev: (T?))(T?), pos = [370..375..377], mode = Mode(ImplicitsEnabled,InferringReturnType), undets = ArrayBuffer((T?)@[370..375])
[info] qualifying undet vars: ArrayBuffer(TypeVar(PolyParam(T)) / (T?)), constraint: Constraint(
[info] uninstVars = (T?);
[info] constrained types = [T]()(ev: T)T
[info] bounds =
[info] T
[info] ordering =
[info] )
[error] [log frontend] <== adapting Test.two2b[(T?)]() of type (ev: (T?))(T?) to FunProto(42):? = Test.two2b[(T?)]()
[error] [log frontend] <== typing Test.two2b() = Test.two2b[(T?)]()
[error] [log frontend] ==> adapting 42 of type Int(42) to (T?)?
[info] adding constraint T >: Int(42) to
[info] Constraint(
[info] uninstVars = (T?);
[info] constrained types = [T]()(ev: T)T
[info] bounds =
[info] T
[info] ordering =
[info] )
[info] added constraint T >: Int(42) to
[info] Constraint(
[info] uninstVars = (T? >: Int(42));
[info] constrained types = [T]()(ev: T)T
[info] bounds =
[info] T >: Int(42)
[info] ordering =
[info] ) = true
[error] [log frontend] <== adapting 42 of type Int(42) to (T? >: Int(42)) = 42
[error] [log frontend] ==> adapting Test.two2b[(T? >: Int(42))]()(42) of type (T? >: Int(42)) to ??
[info] interpolate undet vars in (T? >: Int(42)), pos = [370..377..381], mode = Mode(ImplicitsEnabled,InferringReturnType), undets = ArrayBuffer((T? >: Int(42))@[370..375])
[info] qualifying undet vars: ArrayBuffer(TypeVar(PolyParam(T)) / (T? >: Int(42))), constraint: Constraint(
[info] uninstVars = (T? >: Int(42));
[info] constrained types = [T]()(ev: T)T
[info] bounds =
[info] T >: Int(42)
[info] ordering =
[info] )
[info] interpolate covariant (T? >: Int(42)) in (T? >: Int(42))
[info] approx T, from below = true, bound = Int(42), inst = Int(42)
[info] instantiating (T? >: Int(42)) with Int
[error] [log frontend] <== adapting Test.two2b[Int']()(42) of type Int to ? = Test.two2b[Int']()(42)
[error] [log frontend] <== typing Test.two2b()(42) = Test.two2b[Int']()(42)
When we type one(42)
:
- First we adapt
Test.one
toFunProto(42)
, this does not add any additional constraint or instantiate any type variable - Then we adapt
42
toT
, this adds a constraint>: Int
onT
- Then we adapt
Test.one[T](42)
to??
, this instantiatesT
toInt
, as expected
But when we type two2a()(42)
:
- First we adapt
Test.two2a
toFunProto()
, this does not add any additional constraint or instantiate any type variable - Then we adapt
Test.two2a[T]()
toFunProto(42)
, this interpolatesT
toAny
becauseT
appears contravariantly in the method type, which is not what we wanted! - Then we adapt
42
toAny
, this does not add any additional constraint or instantiate any type variable - Then we adapt
Test.two2a[Any]()(42)
to??
, this does not add any additional constraint or instantiate any type variable
And when we type two2b()(42)
:
- First we adapt
Test.two2b
toFunProto()
, this does not add any additional constraint or instantiate any type variable - Then we adapt
Test.two2b[T]()
toFunProto(42)
, this does not add any additional constraint or instantiate any type variable becauseT
appears both contravariantly and covariantly in the method type - Then we adapt
42
toT
, this adds a constraint>: Int
onT
- Then we adapt
Test.two2b[T]()(42)
to??
, this instantiatesT
toInt
, as expected