Skip to content

Commit 6655587

Browse files
authored
Merge pull request #13260 from dwijnand/wildcards-be-wild
Handle type alias in capturing wildcards
2 parents 58d1b10 + e0622ea commit 6655587

File tree

4 files changed

+52
-16
lines changed

4 files changed

+52
-16
lines changed

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

+17-15
Original file line numberDiff line numberDiff line change
@@ -499,28 +499,30 @@ object Inferencing {
499499
propagate(accu(SimpleIdentityMap.empty, tp))
500500
}
501501

502+
/** Run the transformation after dealiasing but return the original type if it was a no-op. */
503+
private def derivedOnDealias(tp: Type)(transform: Type => Type)(using Context) = {
504+
val dealiased = tp.dealias
505+
val transformed = transform(dealiased)
506+
if transformed eq dealiased then tp // return the original type, not the result of dealiasing
507+
else transformed
508+
}
509+
502510
/** Replace every top-level occurrence of a wildcard type argument by
503511
* a fresh skolem type. The skolem types are of the form $i.CAP, where
504512
* $i is a skolem of type `scala.internal.TypeBox`, and `CAP` is its
505513
* type member. See the documentation of `TypeBox` for a rationale why we do this.
506514
*/
507-
def captureWildcards(tp: Type)(using Context): Type = tp match {
515+
def captureWildcards(tp: Type)(using Context): Type = derivedOnDealias(tp) {
508516
case tp @ AppliedType(tycon, args) if tp.hasWildcardArg =>
509-
tycon.typeParams match {
510-
case tparams @ ((_: Symbol) :: _) =>
511-
val boundss = tparams.map(_.paramInfo.substApprox(tparams.asInstanceOf[List[TypeSymbol]], args))
512-
val args1 = args.zipWithConserve(boundss) { (arg, bounds) =>
513-
arg match {
514-
case TypeBounds(lo, hi) =>
515-
val skolem = SkolemType(defn.TypeBoxClass.typeRef.appliedTo(lo | bounds.loBound, hi & bounds.hiBound))
516-
TypeRef(skolem, defn.TypeBox_CAP)
517-
case arg => arg
518-
}
519-
}
520-
tp.derivedAppliedType(tycon, args1)
521-
case _ =>
522-
tp
517+
val tparams = tycon.typeParamSymbols
518+
val args1 = args.zipWithConserve(tparams.map(_.paramInfo.substApprox(tparams, args))) {
519+
case (TypeBounds(lo, hi), bounds) =>
520+
val skolem = SkolemType(defn.TypeBoxClass.typeRef.appliedTo(lo | bounds.loBound, hi & bounds.hiBound))
521+
TypeRef(skolem, defn.TypeBox_CAP)
522+
case (arg, _) =>
523+
arg
523524
}
525+
if tparams.isEmpty then tp else tp.derivedAppliedType(tycon, args1)
524526
case tp: AndOrType => tp.derivedAndOrType(captureWildcards(tp.tp1), captureWildcards(tp.tp2))
525527
case tp: RefinedType => tp.derivedRefinedType(captureWildcards(tp.parent), tp.refinedName, tp.refinedInfo)
526528
case tp: RecType => tp.derivedRecType(captureWildcards(tp.parent))

compiler/src/dotty/tools/dotc/typer/Typer.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3159,7 +3159,7 @@ class Typer extends Namer
31593159
*/
31603160
def adapt(tree: Tree, pt: Type, locked: TypeVars, tryGadtHealing: Boolean = true)(using Context): Tree =
31613161
try
3162-
trace(i"adapting $tree to $pt ${if (tryGadtHealing) "" else "(tryGadtHealing=false)" }\n", typr, show = true) {
3162+
trace(i"adapting $tree to $pt ${if (tryGadtHealing) "" else "(tryGadtHealing=false)" }", typr, show = true) {
31633163
record("adapt")
31643164
adapt1(tree, pt, locked, tryGadtHealing)
31653165
}

tests/pos/i12739-fallout.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This is a minimisation of the fallout that the original fix caused on Shapeless 3.
2+
3+
type Foo = { type Bar }
4+
5+
extension (foo: Foo)
6+
def toBar(): foo.Bar = ???
7+
8+
def test(foo: Foo): foo.Bar = foo.toBar()

tests/pos/i12739.scala

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
object X {
2+
3+
class CA[A]
4+
type C = CA[_]
5+
val c: C = ???
6+
def f[A](r: CA[A]) = ()
7+
def g(): CA[_] = CA()
8+
def h(): C = ???
9+
10+
// works
11+
f(c)
12+
13+
// works
14+
val x = c.asInstanceOf[C]
15+
f(x)
16+
17+
// was: error
18+
f(c.asInstanceOf[C])
19+
20+
// works, error in Scala 2
21+
f(c.asInstanceOf[c.type])
22+
23+
f(c.asInstanceOf[CA[_]])
24+
f(g())
25+
f(h())
26+
}

0 commit comments

Comments
 (0)