Skip to content

Commit 0893dc3

Browse files
committed
Allow wildcard capture of by-name values
1 parent b439deb commit 0893dc3

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,9 +497,15 @@ object ProtoTypes {
497497
if wideFormal eq formal then targ1
498498
else targ1.tpe match
499499
case tp: AppliedType if tp.hasCaptureConversionArg =>
500-
errorTree(targ1,
501-
em"""argument for by-name parameter contains capture conversion skolem types:
502-
|$tp""")
500+
stripCast(targ1).tpe match
501+
case tp: AppliedType if tp.hasWildcardArg =>
502+
errorTree(targ1,
503+
em"""argument for by-name parameter is not a value
504+
|and contains wildcard arguments: $tp
505+
|
506+
|Assign it to a val and pass that instead.
507+
|""")
508+
case _ => targ1
503509
case _ => targ1
504510
}
505511

tests/neg/t9419.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ object Main:
1414
def onestep[T](m: () => Magic[T]): String = m().step(m().init)
1515
def unostep[T](m: => Magic[T]): String = m.step(m.init)
1616

17-
val iter: Iterator[Magic[?]] = Iterator(IntMagic, StrMagic)
17+
val iter: Iterator[Magic[?]] = Iterator.tabulate(Int.MaxValue)(i => if i % 2 == 0 then IntMagic else StrMagic)
1818

1919
// was: class java.lang.String cannot be cast to class java.lang.Integer
2020
def main(args: Array[String]): Unit =
2121
onestep(() => iter.next()) // error
2222
unostep(iter.next()) // error
23+
val m = iter.next()
24+
unostep(m) // ok, because m is a value

tests/pos/t9419.jackson.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// from failure in the community project
2+
// jackson-module-scala
3+
// in ScalaAnnotationIntrospectorModule.scala:139:12
4+
5+
import scala.language.implicitConversions
6+
7+
trait EnrichedType[X]:
8+
def value: X
9+
10+
trait ClassW extends EnrichedType[Class[_]]:
11+
def extendsScalaClass = false
12+
13+
class Test:
14+
implicit def mkClassW(c: => Class[_]): ClassW = new ClassW:
15+
lazy val value = c
16+
17+
def test1(c1: Class[_]) = c1.extendsScalaClass // ok: c1 is a value
18+
def test2(c2: Class[_]) = mkClassW(c2).extendsScalaClass // ok: c2 is a value
19+
// c1 in test1 goes throw adapting to find the extension method and gains the wildcard capture cast then
20+
// c2 in test2 goes straight to typedArg, as it's already an arg, so it never gets wildcard captured

0 commit comments

Comments
 (0)