Skip to content

Commit ff8659e

Browse files
committed
Don't allow wildcard types in constraints
Fixes #12677
1 parent 55762c6 commit ff8659e

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

+8-2
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,21 @@ trait ConstraintHandling {
9797
constraint = constraint.replace(param, bound)
9898
true
9999
else
100+
val dropWildcards = new ApproximatingTypeMap:
101+
if !isUpper then variance = -1
102+
def apply(t: Type): Type = t match
103+
case WildcardType => range(param.underlying.loBound, param.underlying.hiBound)
104+
case _ => mapOver(t)
100105
// Narrow one of the bounds of type parameter `param`
101106
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
102107
// that `param >: bound`.
108+
val bound1 = dropWildcards(bound)
103109
val narrowedBounds =
104110
val saved = homogenizeArgs
105111
homogenizeArgs = Config.alignArgsInAnd
106112
try
107-
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound)
108-
else oldBounds.derivedTypeBounds(lo | bound, hi)
113+
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound1)
114+
else oldBounds.derivedTypeBounds(lo | bound1, hi)
109115
finally homogenizeArgs = saved
110116
val c1 = constraint.updateEntry(param, narrowedBounds)
111117
(c1 eq constraint)

Diff for: tests/pos/i12677.scala

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class F[A]
2+
object F {
3+
def apply[A](a: => A) = new F[A]
4+
}
5+
6+
trait TC[A] { type Out }
7+
object TC {
8+
implicit def tc[A]: TC[A] { type Out = String } = ???
9+
}
10+
11+
// ====================================================================================
12+
object Bug {
13+
final class CustomHook[A] {
14+
def blah(implicit tc: TC[A]): CustomHook[tc.Out] = ???
15+
}
16+
17+
def i: CustomHook[Int] = ???
18+
val f = F(i.blah)
19+
f: F[CustomHook[String]] // error
20+
}
21+
22+
// ====================================================================================
23+
object Workaround {
24+
final class CustomHook[A] {
25+
def blah[B](implicit tc: TC[A] { type Out = B }): CustomHook[B] = ??? // raise type
26+
}
27+
28+
def i: CustomHook[Int] = ???
29+
val f = F(i.blah)
30+
f: F[CustomHook[String]] // works
31+
}

0 commit comments

Comments
 (0)