Skip to content

Commit 8dfed29

Browse files
authored
Merge pull request scala#6336 from hrhino/t10726
Right-associative arguments don't lose singleton type
2 parents 596f047 + 6a6efe8 commit 8dfed29

File tree

5 files changed

+78
-20
lines changed

5 files changed

+78
-20
lines changed

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,10 +848,14 @@ self =>
848848
}
849849
if (isExpr) {
850850
if (rightAssoc) {
851+
import symtab.Flags._
851852
val x = freshTermName(nme.RIGHT_ASSOC_OP_PREFIX)
853+
val liftedArg = atPos(left.pos) {
854+
ValDef(Modifiers(FINAL | SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))
855+
}
852856
Block(
853-
List(ValDef(Modifiers(symtab.Flags.SYNTHETIC | symtab.Flags.ARTIFACT), x, TypeTree(), stripParens(left))),
854-
Apply(mkSelection(right), List(Ident(x))))
857+
liftedArg :: Nil,
858+
Apply(mkSelection(right), List(Ident(x) setPos left.pos.focus)))
855859
} else {
856860
Apply(mkSelection(left), arguments)
857861
}
@@ -2275,7 +2279,7 @@ self =>
22752279
val vds = new ListBuffer[List[ValDef]]
22762280
val start = in.offset
22772281
def paramClause(): List[ValDef] = if (in.token == RPAREN) Nil else {
2278-
val implicitmod =
2282+
val implicitmod =
22792283
if (in.token == IMPLICIT) {
22802284
if (implicitOffset == -1) { implicitOffset = in.offset ; implicitSection = vds.length }
22812285
else if (warnAt == -1) warnAt = in.offset

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,13 +3639,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
36393639
case _ => tp
36403640
}
36413641

3642-
// Inline RHS of ValDef for right-associative by-value operator desugaring
3643-
val (args2, pos2) = (args1, mt.params) match {
3644-
case ((ident: Ident) :: Nil, param :: Nil) if param.isByNameParam && rightAssocValDefs.contains(ident.symbol) =>
3645-
inlinedRightAssocValDefs += ident.symbol
3646-
val rhs = rightAssocValDefs.remove(ident.symbol).get
3647-
(rhs.changeOwner(ident.symbol -> context.owner) :: Nil, wrappingPos(tree :: rhs :: Nil))
3648-
case _ => (args1, tree.pos)
3642+
// Inline RHS of ValDef for right-associative by-value operator desugaring.
3643+
// Remove the ValDef also if the argument is a constant-folded reference to it.
3644+
var (args2, pos2) = (args1, tree.pos)
3645+
args1 match {
3646+
case List(lit: Literal) =>
3647+
lit.attachments.get[OriginalTreeAttachment] match {
3648+
case Some(OriginalTreeAttachment(id: Ident)) if rightAssocValDefs.contains(id.symbol) =>
3649+
inlinedRightAssocValDefs += id.symbol
3650+
rightAssocValDefs.remove(id.symbol)
3651+
case _ =>
3652+
}
3653+
3654+
case List(id: Ident) if rightAssocValDefs.contains(id.symbol) =>
3655+
mt.params match {
3656+
case List(p) if p.isByNameParam =>
3657+
inlinedRightAssocValDefs += id.symbol
3658+
val rhs = rightAssocValDefs.remove(id.symbol).get
3659+
args2 = rhs.changeOwner(id.symbol -> context.owner) :: Nil
3660+
pos2 = wrappingPos(tree :: rhs :: Nil)
3661+
case _ =>
3662+
}
3663+
case _ =>
36493664
}
36503665

36513666
/*

test/files/pos/t10726.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
3+
def eat(foods: List["food"]): Unit = println(s"ate ${foods.size} foods")
4+
5+
eat("food" :: Nil)
6+
eat(Nil.::("food"))
7+
8+
}

test/files/run/t10751.check

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
11
[[syntax trees at end of typer]] // newSource1.scala
2-
[0:56]package [0:0]<empty> {
3-
[0:56]object Test extends [12:56][56]scala.AnyRef {
4-
[56]def <init>(): [12]Test.type = [56]{
5-
[56][56][56]Test.super.<init>();
2+
[0:201]package [0:0]<empty> {
3+
[0:201]object Test extends [12:201][201]scala.AnyRef {
4+
[201]def <init>(): [12]Test.type = [201]{
5+
[201][201][201]Test.super.<init>();
66
[12]()
77
};
8-
[20:29]{
9-
[20:29]<22:29><22:29>C.foo_:[[22]Nothing]([20:21]1)
8+
[20:43]private[this] val n: [38]Int = [42:43]1;
9+
[51:60]{
10+
[53:60]<53:60><53:60>C.foo_:[[53]Nothing]([51]1)
1011
};
11-
[36:50]{
12-
[36:50]<38:50><38:50>C.foo_:[[44:47]<type: [44:47]scala.Any>]([36:37]1)
12+
[67:81]{
13+
[69:81]<69:81><69:81>C.foo_:[[75:78]<type: [75:78]scala.Any>]([67]1)
14+
};
15+
[89:98]{
16+
[89:98]<91:98><91:98>C.foo_:[[91]Nothing]([89:90][89]Test.this.n)
17+
};
18+
[105:119]{
19+
[105:119]<107:119><107:119>C.foo_:[[113:116]<type: [113:116]scala.Any>]([105:106][105]Test.this.n)
20+
};
21+
[127:136]{
22+
[129:136]<129:136><129:136>C.bar_:[[129]Nothing]([127]1)
23+
};
24+
[143:157]{
25+
[145:157]<145:157><145:157>C.bar_:[[151:154]<type: [151:154]scala.Any>]([143]1)
26+
};
27+
[165:174]{
28+
[165:166]final <synthetic> <artifact> val rassoc$7: [165]Int = [165:166][165]Test.this.n;
29+
[167:174]<167:174><167:174>C.bar_:[[167]Nothing]([165]rassoc$7)
30+
};
31+
[181:195]{
32+
[181:182]final <synthetic> <artifact> val rassoc$8: [181]Int = [181:182][181]Test.this.n;
33+
[183:195]<183:195><183:195>C.bar_:[[189:192]<type: [189:192]scala.Any>]([181]rassoc$8)
1334
}
1435
}
1536
}

test/files/run/t10751.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,19 @@ object Test extends DirectTest {
77

88
override def code = """
99
object Test {
10+
private[this] val n = 1
11+
1012
1 foo_: C
1113
1 foo_:[Any] C
14+
15+
n foo_: C
16+
n foo_:[Any] C
17+
18+
1 bar_: C
19+
1 bar_:[Any] C
20+
21+
n bar_: C
22+
n bar_:[Any] C
1223
}
1324
""".trim
1425

@@ -21,7 +32,6 @@ object Test extends DirectTest {
2132

2233
class C {
2334
def foo_:[Dummy](i: => Int): Int = i
24-
def t(c: C) = 1 foo_: c
25-
def u(c: C) = 1 foo_:[Any] c
35+
def bar_:[Dummy](i: Int): Int = i
2636
}
2737
object C extends C

0 commit comments

Comments
 (0)