Skip to content
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

Incorrect inferred type in contravariant position #4881

Open
scabug opened this issue Aug 6, 2011 · 10 comments
Open

Incorrect inferred type in contravariant position #4881

scabug opened this issue Aug 6, 2011 · 10 comments
Labels
Milestone

Comments

@scabug
Copy link

@scabug scabug commented Aug 6, 2011

class Contra[-T]
trait A
trait B extends A
trait C extends B
def contraLBUB[a >: C <: A](): Contra[a] = null
def contraLB[a >: C](): Contra[a] = null
contraLBUB() //inferred Contra[C] instead of Contra[A]
contraLB() //inferred Contra[C] instead of Contra[Any]

According to Language specification (6.26.4 Case 2):
If several substitutions exist,
local-type inference will choose for each type variable ai a minimal or maximal type
Ti of the solution space. A maximal type Ti will be chosen if the type parameter ai
appears contravariantly (§4.5) in the type T of the expression. A minimal type Ti
will be chosen in all other situations, i.e. if the variable appears covariantly, nonvariantly
or not at all in the type T.

What we can see here. Value has Type Contra[a]. So position of a is contravariant. There is no covariant or invariant positions of a => maximal solution should be chosen.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Aug 6, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4881?orig=1
Reporter: @Alefas
Affected Versions: 2.9.0-1

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Aug 6, 2011

@retronym said:
Actually, it works as expected as a Value (Case 2)

scala> contraLBUB
res9: Contra[A] = null

scala> contraLB
res10: Contra[Any] = null

So the question is, does "Case 3: Methods" explain these?

scala> contraLBUB()
res11: Contra[C] = null

scala> contraLB()
res12: Contra[C] = null
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Aug 7, 2011

@Alefas said:
I'm sure this is wrong if it's different:

foo
foo()
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Aug 7, 2011

@paulp said:
Yeah, that's a bit hard to defend:


scala> contraLBUB
res1: Contra[A] = null

scala> contraLBUB()
res2: Contra[C] = null

scala> (contraLBUB _)()
res3: Contra[A] = null
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Jun 21, 2012

@retronym said:
Without having checked the consequences (sky falling, etc), but this is enough to restore consistency between inference for the value and method application:

diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.s
index 688dcd9..a34b93d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -575,8 +575,9 @@ trait Infer {
             "argument expression's type is not compatible with formal parameter type" + foundReqMsg(tp1, pt1))
         }
       }
       val targs = solvedTypes(
-        tvars, tparams, tparams map varianceInTypes(formals),
+        tvars, tparams, tparams map varianceInTypes(restpe +: formals),
         false, lubDepth(formals) max lubDepth(argtpes)
       )
       adjustTypeArgs(tparams, tvars, targs, restpe)

Compare with:

https://github.com/scala/scala/blob/039d826e/src/compiler/scala/tools/nsc/typechecker/Infer.scala#L384

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Jun 21, 2012

@adriaanm said (edited on Jun 21, 2012 8:09:59 AM UTC):
I think that needs to be adjusted slightly since the variance in formals should be flipped (arguments = contravariant), whereas restpe is in covariant position (the flipping is achieved by the up=false argument to solvedTypes, off the top of my head)

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Jul 23, 2012

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 29, 2012

@paulp said:
This is being reverted for causing #6311.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 30, 2012

@Blaisorblade said:
Fixing this means that Coll would be inferred differently for these two signatures, which look instead equivalent:

def f[T, Coll <: Traversable[T]](p0: String)(p1: Traversable[T]): (Coll => Traversable[T]) = ??? //Here Coll would be maximized.
def f[T, Coll <: Traversable[T]](p0: String)(p1: Traversable[T])(p2: Coll): Traversable[T] = ??? //Here Coll would be minimized.

This is if I get the new expected behavior right, which says that (ignoring mixed variance) a type argument must be minimized (made most specific) if it appears either:
(a) covariantly in the result type (per 4881), hence covariantly in the method type or
(b) covariantly in argument types, hence contravariantly in the method type.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Oct 15, 2013

@gkossakowski said:
Unassigning and rescheduling to M7 as previous deadline was missed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.