@@ -1483,6 +1483,30 @@ class Namer { typer: Typer =>
1483
1483
case _ =>
1484
1484
NoType
1485
1485
1486
+ /** The expected type for a default argument. This is normally the `defaultParamType`
1487
+ * with references to internal parameters replaced by wildcards. This replacement
1488
+ * makes it possible that the default argument can have a more specific type than the
1489
+ * parameter. For instance, we allow
1490
+ *
1491
+ * class C[A](a: A) { def copy[B](x: B = a): C[B] = C(x) }
1492
+ *
1493
+ * However, if the default parameter type is a context function type, we
1494
+ * have to make sure that wildcard types do not leak into the implicitly
1495
+ * generated closure's result type. Test case is pos/i12019.scala. If there
1496
+ * would be a leakage with the wildcard approximation, we pick the original
1497
+ * default parameter type as expected type.
1498
+ */
1499
+ def expectedDefaultArgType =
1500
+ val originalTp = defaultParamType
1501
+ val approxTp = wildApprox(originalTp)
1502
+ approxTp.stripPoly match
1503
+ case atp @ defn.ContextFunctionType (_, resType, _)
1504
+ if ! defn.isNonRefinedFunction(atp) // in this case `resType` is lying, gives us only the non-dependent upper bound
1505
+ || resType.existsPart(_.isInstanceOf [WildcardType ], stopAtStatic = true , forceLazy = false ) =>
1506
+ originalTp
1507
+ case _ =>
1508
+ approxTp
1509
+
1486
1510
// println(s"final inherited for $sym: ${inherited.toString}") !!!
1487
1511
// println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}")
1488
1512
// TODO Scala 3.1: only check for inline vals (no final ones)
@@ -1509,7 +1533,7 @@ class Namer { typer: Typer =>
1509
1533
// expected type but we run it through `wildApprox` to allow default
1510
1534
// parameters like in `def mkList[T](value: T = 1): List[T]`.
1511
1535
val defaultTp = defaultParamType
1512
- val pt = inherited.orElse(wildApprox(defaultTp) ).orElse(WildcardType ).widenExpr
1536
+ val pt = inherited.orElse(expectedDefaultArgType ).orElse(WildcardType ).widenExpr
1513
1537
val tp = typedAheadRhs(pt).tpe
1514
1538
if (defaultTp eq pt) && (tp frozen_<:< defaultTp) then
1515
1539
// When possible, widen to the default getter parameter type to permit a
0 commit comments