Skip to content

Commit fedd8f2

Browse files
committed
Change result type of by-name closures
Make it the formal type rather than the actual one. This avoids messing up capture annotations.
1 parent 4cc8ff0 commit fedd8f2

File tree

4 files changed

+26
-19
lines changed

4 files changed

+26
-19
lines changed

compiler/src/dotty/tools/dotc/transform/ElimByName.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class ElimByName extends MiniPhase, InfoTransformer:
9292
sym.is(Method) || exprBecomesFunction(sym)
9393

9494
def byNameClosure(arg: Tree, argType: Type)(using Context): Tree =
95+
report.log(i"creating by name closure for $argType")
9596
val meth = newAnonFun(ctx.owner, MethodType(Nil, argType), coord = arg.span)
9697
Closure(meth,
9798
_ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase),
@@ -135,12 +136,8 @@ class ElimByName extends MiniPhase, InfoTransformer:
135136
if isByNameRef(qual) && (isPureExpr(qual) || qual.symbol.isAllOf(InlineParam)) =>
136137
qual
137138
case _ =>
138-
if isByNameRef(arg) || arg.symbol.name.is(SuperArgName)
139-
then arg
140-
else
141-
var argType = arg.tpe.widenIfUnstable
142-
if argType.isBottomType then argType = formalResult
143-
byNameClosure(arg, argType)
139+
if isByNameRef(arg) || arg.symbol.name.is(SuperArgName) then arg
140+
else byNameClosure(arg, formalResult)
144141
case _ =>
145142
arg
146143

tests/neg-custom-args/captures/byname.check

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
-- Warning: tests/neg-custom-args/captures/byname.scala:14:18 ----------------------------------------------------------
2-
14 | def h(x: {cap1} -> I) = x // warning
1+
-- Warning: tests/neg-custom-args/captures/byname.scala:17:18 ----------------------------------------------------------
2+
17 | def h(x: {cap1} -> I) = x // warning
33
| ^
44
| Style: by-name `->` should immediately follow closing `}` of capture set
55
| to avoid confusion with function type.
66
| That is, `{c}-> T` instead of `{c} -> T`.
7-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/byname.scala:7:5 -----------------------------------------
8-
7 | h(f()) // error
9-
| ^^^
10-
| Found: {cap2} (x$0: Int) -> Int
11-
| Required: Int -> Int
7+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/byname.scala:10:6 ----------------------------------------
8+
10 | h(f2()) // error
9+
| ^^^^
10+
| Found: {cap1} (x$0: Int) -> Int
11+
| Required: {cap2} Int -> Int
1212

1313
longer explanation available when compiling with `-explain`
14-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/byname.scala:16:5 ----------------------------------------
15-
16 | h(g()) // error
14+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/byname.scala:19:5 ----------------------------------------
15+
19 | h(g()) // error
1616
| ^^^
1717
| Found: {cap2} () ?-> I
1818
| Required: {cap1} () ?-> I

tests/neg-custom-args/captures/byname.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
def test(cap1: Cap, cap2: Cap) =
44
def f() = if cap1 == cap1 then g else g
55
def g(x: Int) = if cap2 == cap2 then 1 else x
6+
def g2(x: Int) = if cap1 == cap1 then 1 else x
7+
def f2() = if cap1 == cap1 then g2 else g2
68
def h(ff: => {cap2} Int -> Int) = ff
7-
h(f()) // error
9+
h(f()) // ok
10+
h(f2()) // error
811

912
class I
1013

tests/pos-custom-args/captures/lazylists-exceptions.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,26 @@ extension [A](xs: {*} LazyList[A])
3737

3838
def filter(p: A => Boolean): {xs, p} LazyList[A] =
3939
if xs.isEmpty then LazyNil
40-
else if p(xs.head) then LazyCons(xs.head, () => xs.tail.filter(p))
40+
else if p(xs.head) then lazyCons(xs.head, xs.tail.filter(p))
4141
else xs.tail.filter(p)
4242

4343
def concat(ys: {*} LazyList[A]): {xs, ys} LazyList[A] =
4444
if xs.isEmpty then ys
45-
else LazyCons(xs.head, () => xs.tail.concat(ys))
45+
else xs.head #: xs.tail.concat(ys)
4646
end extension
4747

48+
extension [A](x: A)
49+
def #:(xs1: => {*} LazyList[A]): {xs1} LazyList[A] =
50+
LazyCons(x, () => xs1)
51+
52+
def lazyCons[A](x: A, xs1: => {*} LazyList[A]): {xs1} LazyList[A] =
53+
LazyCons(x, () => xs1)
54+
4855
class Ex1 extends Exception
4956
class Ex2 extends Exception
5057

5158
def test(using cap1: CanThrow[Ex1], cap2: CanThrow[Ex2]) =
52-
val xs = LazyCons(1, () => LazyNil)
59+
val xs = 1 #: LazyNil
5360

5461
def f(x: Int): Int throws Ex1 =
5562
if x < 0 then throw Ex1()

0 commit comments

Comments
 (0)