-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Type parameters are instantiated too early in some cases #738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This may be related to #718. |
What is wrong with inferring T to Any in case two2a? That's how it is intended to work. |
Could you explain why it makes sense to infer T differently for object Test {
def twoN[T](x: T)(implicit ev: T): Nothing = ???
def twoT[T](x: T)(implicit ev: T): T = ???
def test = {
implicit val i: Int = 1
twoN(42) // dotty with #738: T=Any, implicit search fails; scalac: T=Int, implicit search succeeds
twoT(42) // dotty with #738 and scalac: T=Int, implicit search succeeds
}
} |
Also, in #739 (comment) you said:
I thought that this meant that we only instantiate a type variable when we "really need" to, but for |
@smarter No, we always interpolate if it is safe to do so. I.e. if the type variable appears co-variantly in an expression's type we interpolate it downwards, if it appears contravariantly, upwards. Only non-variant type variables are kept. But it's true that this gives an inconsistency for implicits. I'll add to PR #739 a fix that ignores |
Fixes scala#738. The previous scheme interpolated type variables according to the full variance of the result type. This means that the interpolation direction is downwards if a type varaible occurs like this: (implicit x: T)T but it is upwards if it occurs like this (implicit x: T)Unit For a normal method this makes sense, since the upper bound of T gives you the most general function. But if the method is implicit, it makes no sense, since upward instantiation means that we likely get ambiguity errors. Interestingly the fix causes a different problem (exemplified by failures in run/stream-stack-overflow.scala, and also in dotc itself), which will be fixed in the next commit.
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:
Here's how
one(42)
is typed:Here's how
two2a()(42)
is typed:And here's how
two2b()(42)
is typed:When we type
one(42)
:Test.one
toFunProto(42)
, this does not add any additional constraint or instantiate any type variable42
toT
, this adds a constraint>: Int
onT
Test.one[T](42)
to??
, this instantiatesT
toInt
, as expectedBut when we type
two2a()(42)
:Test.two2a
toFunProto()
, this does not add any additional constraint or instantiate any type variableTest.two2a[T]()
toFunProto(42)
, this interpolatesT
toAny
becauseT
appears contravariantly in the method type, which is not what we wanted!42
toAny
, this does not add any additional constraint or instantiate any type variableTest.two2a[Any]()(42)
to??
, this does not add any additional constraint or instantiate any type variableAnd when we type
two2b()(42)
:Test.two2b
toFunProto()
, this does not add any additional constraint or instantiate any type variableTest.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 type42
toT
, this adds a constraint>: Int
onT
Test.two2b[T]()(42)
to??
, this instantiatesT
toInt
, as expectedThe text was updated successfully, but these errors were encountered: