Skip to content

Fix #6146: Fix bounds check involving wildcards and f-bounds #6147

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

Merged
merged 5 commits into from
Mar 25, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
def checkOverlapsBounds(lo: Type, hi: Type): Unit = {
//println(i"instantiating ${bounds.hi} with $argTypes")
//println(i" = ${instantiate(bounds.hi, argTypes)}")
val hiBound = instantiate(bounds.hi, argTypes.mapConserve(_.bounds.hi))
val loBound = instantiate(bounds.lo, argTypes.mapConserve(_.bounds.lo))
// Note that argTypes can contain a TypeBounds type for arguments that are
// not fully determined. In that case we need to check against the hi bound of the argument.
val hiBound = instantiate(bounds.hi, argTypes)
val loBound = instantiate(bounds.lo, argTypes)
if (!(lo <:< hiBound)) violations += ((arg, "upper", hiBound))
if (!(loBound <:< hi)) violations += ((arg, "lower", bounds.lo))
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ object Checking {
}.getOrElse(TypeTree(tparam.paramRef))
val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args
val bounds = tparams.map(_.paramInfoAsSeenFrom(tree.tpe).bounds)
def instantiate(bound: Type, args: List[Type]) =
HKTypeLambda.fromParams(tparams, bound).appliedTo(args)
def instantiate(bound: Type, args: List[Type]) = tparams match {
case (_: Symbol) :: _ if args.exists(_.isInstanceOf[TypeBounds]) =>
bound.substApprox(tparams.asInstanceOf[List[Symbol]], args)
case _ =>
HKTypeLambda.fromParams(tparams, bound).appliedTo(args)
}
if (boundsCheck) checkBounds(orderedArgs, bounds, instantiate)

def checkWildcardApply(tp: Type): Unit = tp match {
Expand Down
13 changes: 13 additions & 0 deletions tests/pos/i6146.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait BS[T, S <: BS[T, S]]
trait IS extends BS[Int, IS]

sealed trait BSElem[T, S <: BS[_, S]]
// old error: Type argument S does not conform to upper bound BS[Any, LazyRef(S)]

object BSElem {
implicit val intStreamShape: BSElem[Int, IS] = ???
}
class Ops[A] {
def asJavaSeqStream[S <: BS[_, S]](implicit s: BSElem[A, S]): S = ???
// old error: Type argument S does not conform to upper bound BS[Any, LazyRef(S)]
}