Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5381be8

Browse files
committed
Always just forward args in function expansion
1 parent 52b2013 commit 5381be8

File tree

4 files changed

+53
-16
lines changed

4 files changed

+53
-16
lines changed

src/compiler/scala/tools/nsc/transform/UnCurry.scala

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ abstract class UnCurry extends InfoTransform
220220
// Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident),
221221
// because we know `cbn` will already be a `Function0` thunk. When we're targeting a SAM,
222222
// the types don't align and we must preserve the function wrapper.
223-
if (fun.vparams.isEmpty && isByNameRef(fun.body) && fun.attachments.get[SAMFunction].isEmpty) { noApply += fun.body ; fun.body }
223+
if (fun.vparams.isEmpty && isByNameRef(fun.body) && !fun.attachments.contains[SAMFunction]) {
224+
noApply += fun.body
225+
fun.body
226+
}
224227
else if (forceExpandFunction || inConstructorFlag != 0) {
225228
// Expand the function body into an anonymous class
226229
gen.expandFunction(localTyper)(fun, inConstructorFlag)
@@ -233,18 +236,26 @@ abstract class UnCurry extends InfoTransform
233236
val newFun = deriveFunction(fun)(_ => localTyper.typedPos(fun.pos)(
234237
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol)) :: Nil)
235238
))
239+
def typeNewFun = localTyper.typedPos(fun.pos)(Block(liftedMethod :: Nil, super.transform(newFun)))
236240

237241
if (!mustExpand) {
238242
liftedMethod.symbol.updateAttachment(DelambdafyTarget)
239243
liftedMethod.updateAttachment(DelambdafyTarget)
244+
typeNewFun
240245
}
241-
242-
val typedNewFun = localTyper.typedPos(fun.pos)(Block(liftedMethod :: Nil, super.transform(newFun)))
243-
if (mustExpand) {
244-
val Block(stats, expr : Function) = typedNewFun: @unchecked
245-
treeCopy.Block(typedNewFun, stats, gen.expandFunction(localTyper)(expr, inConstructorFlag))
246-
} else {
247-
typedNewFun
246+
else typeNewFun match {
247+
case typedNewFun @ Block(stats, expr: Function) =>
248+
val expansion = gen.expandFunction(localTyper)(expr, inConstructorFlag)
249+
expansion match {
250+
case Block(ClassDef(_, _, _, Template(_, _, body)) :: Nil, _) =>
251+
body.last match {
252+
case DefDef(_, _, _, _, _, Apply(_, args)) => noApply.addAll(args) // samDef args are pass-thru
253+
case _ =>
254+
}
255+
case _ =>
256+
}
257+
treeCopy.Block(typedNewFun, stats, expansion)
258+
case x => throw new MatchError(x)
248259
}
249260
}
250261

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,10 +3069,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
30693069
if (samTp eq NoType) false
30703070
else {
30713071
/* Make a synthetic class symbol to represent the synthetic class that
3072-
* will be spun up by LMF for this function. This is necessary because
3073-
* it's possible that the SAM method might need bridges, and they have
3074-
* to go somewhere. Erasure knows to compute bridges for these classes
3075-
* just as if they were real templates extending the SAM type. */
3072+
* will be spun up by LMF for this function. This is necessary because
3073+
* it's possible that the SAM method might need bridges, and they have
3074+
* to go somewhere. Erasure knows to compute bridges for these classes
3075+
* just as if they were real templates extending the SAM type. */
30763076
val synthCls = fun.symbol.owner.newClassWithInfo(
30773077
name = tpnme.ANON_CLASS_NAME,
30783078
parents = ObjectTpe :: samTp :: Nil,
@@ -3089,8 +3089,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
30893089
fun.setType(samTp)
30903090

30913091
/* Arguably I should do `fun.setSymbol(samCls)` rather than leaning
3092-
* on an attachment, but doing that confounds lambdalift's free var
3093-
* analysis in a way which does not seem to be trivially reparable. */
3092+
* on an attachment, but doing that confounds lambdalift's free var
3093+
* analysis in a way which does not seem to be trivially reparable. */
30943094
fun.updateAttachment(SAMFunction(samTp, sam, synthCls))
30953095

30963096
true

src/reflect/scala/reflect/macros/Attachments.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,15 @@ abstract class Attachments { self =>
6666
}
6767

6868
/** Check underlying payload contains an instance of type `T`. */
69-
def contains[T: ClassTag]: Boolean =
70-
!isEmpty && (all exists matchesTag[T])
69+
def contains[T: ClassTag]: Boolean = !isEmpty && {
70+
val it = all.iterator
71+
val matchesTagFn = matchesTag[T]
72+
while (it.hasNext) { // OPT: hotspot, hand roll `Set.exists`.
73+
val datum = it.next()
74+
if (matchesTagFn(datum)) return true
75+
}
76+
false
77+
}
7178

7279
/** Creates a copy of this attachment with the payload slot of T added/updated with the provided value.
7380
* Replaces an existing payload of the same type, if exists.

test/files/run/t11237.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//> abusing options -Vprint:~uncurry
2+
trait Semigroup[F] { self =>
3+
def append(f1: F, f2: => F): F
4+
val z = 10
5+
}
6+
7+
case class Box(i: Int)
8+
9+
class R extends Runnable {
10+
def run() = {
11+
val boxSemigroup: Semigroup[Box] = (x1, x2) => Box(x1.i + x2.i)
12+
//val boxSemigroup: Semigroup[Box] = (x1: Box, x2: Box) => Box(Math.max(x1.i, x2.i)) // disallowed, by-name must be inferred
13+
assert(boxSemigroup.append(Box(1), Box(2)) == Box(3))
14+
}
15+
}
16+
17+
object Test extends App {
18+
new R().run()
19+
}

0 commit comments

Comments
 (0)