-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #4032: Fix direction of instantiation. #4059
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -313,6 +313,29 @@ object Inferencing { | |
|
||
propagate(accu(SimpleIdentityMap.Empty, tp)) | ||
} | ||
|
||
private def varianceInContext(tvar: TypeVar)(implicit ctx: Context): FlagSet = { | ||
object accu extends TypeAccumulator[FlagSet] { | ||
def apply(fs: FlagSet, t: Type): FlagSet = | ||
if (fs == EmptyFlags) fs | ||
else if (t eq tvar) | ||
if (variance > 0) fs &~ Contravariant | ||
else if (variance < 0) fs &~ Covariant | ||
else EmptyFlags | ||
else foldOver(fs, t) | ||
} | ||
val constraint = ctx.typerState.constraint | ||
val tparam = tvar.origin | ||
(VarianceFlags /: constraint.uninstVars) { (fs, tv) => | ||
if ((tv `eq` tvar) || (fs == EmptyFlags)) fs | ||
else { | ||
val otherParam = tv.origin | ||
val fs1 = if (constraint.isLess(tparam, otherParam)) fs &~ Covariant else fs | ||
val fs2 = if (constraint.isLess(otherParam, tparam)) fs1 &~ Contravariant else fs1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @odersky We were wondering about
Are you trying to give the biggest type to the typing context? If so, do you know the variance of |
||
accu(fs2, constraint.entry(otherParam)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
trait Inferencing { this: Typer => | ||
|
@@ -389,7 +412,8 @@ trait Inferencing { this: Typer => | |
if (!(vs contains tvar) && qualifies(tvar)) { | ||
typr.println(s"instantiating non-occurring ${tvar.show} in ${tp.show} / $tp") | ||
ensureConstrained() | ||
tvar.instantiate(fromBelow = tvar.hasLowerBound) | ||
tvar.instantiate( | ||
fromBelow = tvar.hasLowerBound || !varianceInContext(tvar).is(Covariant)) | ||
} | ||
} | ||
if (constraint.uninstVars exists qualifies) interpolate() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import scala.concurrent.Future | ||
|
||
class Gen[+T] { | ||
def map[U](f: T => U): Gen[U] = ??? | ||
} | ||
|
||
object Gen { | ||
def oneOf[T](t0: T, t1: T): Gen[T] = ??? // Compile with this line commented | ||
def oneOf[T](g0: Gen[T], g1: Gen[T]): Gen[T] = ??? | ||
} | ||
|
||
class Arbitrary[T] | ||
|
||
object Arbitrary { | ||
def arbitrary[T]: Gen[T] = ??? | ||
|
||
def arbFuture[X]: Gen[Future[X]] = | ||
Gen.oneOf(arbitrary[Future[X]], arbitrary[Throwable].map(Future.failed)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add documentation for this method