Skip to content

Commit

Permalink
Don't allow wildcard types in constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky authored and smarter committed Jun 8, 2021
1 parent d7d4a9f commit 175433c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
10 changes: 8 additions & 2 deletions compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,21 @@ trait ConstraintHandling {
constraint = constraint.replace(param, bound)
true
else
val dropWildcards = new ApproximatingTypeMap:
if !isUpper then variance = -1
def apply(t: Type): Type = t match
case WildcardType => range(param.underlying.loBound, param.underlying.hiBound)
case _ => mapOver(t)
// Narrow one of the bounds of type parameter `param`
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
// that `param >: bound`.
val bound1 = dropWildcards(bound)
val narrowedBounds =
val saved = homogenizeArgs
homogenizeArgs = Config.alignArgsInAnd
try
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound)
else oldBounds.derivedTypeBounds(lo | bound, hi)
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound1)
else oldBounds.derivedTypeBounds(lo | bound1, hi)
finally homogenizeArgs = saved
val c1 = constraint.updateEntry(param, narrowedBounds)
(c1 eq constraint)
Expand Down
31 changes: 31 additions & 0 deletions tests/pos/i12677.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class F[A]
object F {
def apply[A](a: => A) = new F[A]
}

trait TC[A] { type Out }
object TC {
implicit def tc[A]: TC[A] { type Out = String } = ???
}

// ====================================================================================
object Bug {
final class CustomHook[A] {
def blah(implicit tc: TC[A]): CustomHook[tc.Out] = ???
}

def i: CustomHook[Int] = ???
val f = F(i.blah)
f: F[CustomHook[String]] // error
}

// ====================================================================================
object Workaround {
final class CustomHook[A] {
def blah[B](implicit tc: TC[A] { type Out = B }): CustomHook[B] = ??? // raise type
}

def i: CustomHook[Int] = ???
val f = F(i.blah)
f: F[CustomHook[String]] // works
}

0 comments on commit 175433c

Please sign in to comment.