Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc17d9cc

Browse files
committed
Always just forward args in function expansion
Notice args of forwarder when generating it
1 parent5e63e4d commitc17d9cc

File tree

5 files changed

+81
-30
lines changed

5 files changed

+81
-30
lines changed

‎src/compiler/scala/tools/nsc/ast/TreeGen.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,9 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
309309
resTp:Type= functionResultType(fun.tpe),
310310
additionalFlags:FlagSet=NoFlags):DefDef= {
311311
valmethSym= owner.newMethod(name, fun.pos,FINAL| additionalFlags)
312-
// for sams, methParamProtos is the parameter symbols for the sam's method, so that we generate the correct override (based on parameter types)
313-
valmethParamSyms= methParamProtos.map { param=> methSym.newSyntheticValueParam(param.tpe, param.name.toTermName) }
312+
// for sams, methParamProtos is the parameter symbols for the sam's method,
313+
// so that we generate the correct override (based on parameter types)
314+
valmethParamSyms= methParamProtos.map(param=> methSym.newSyntheticValueParam(param.tpe, param.name.toTermName))
314315
methSym setInfoMethodType(methParamSyms, resTp)
315316

316317
// we must rewire reference to the function's param symbols -- and not methParamProtos -- to methParamSyms
@@ -326,8 +327,8 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
326327
valenclosingStaticModules= owner.ownersIterator.filter(x=>!x.hasPackageFlag&& x.isModuleClass&& x.isStatic)
327328
enclosingStaticModules.foldLeft(tree)((tree, moduleClass)=> tree.substituteThis(moduleClass, gen.mkAttributedIdent(moduleClass.sourceModule)) )
328329
}
329-
330-
newDefDef(methSym,substThisForModule(moveToMethod(useMethodParams(fun.body))))(tpt=TypeTree(resTp))
330+
valbody= substThisForModule(moveToMethod(useMethodParams(fun.body)))
331+
newDefDef(methSym, body)(tpt=TypeTree(resTp))
331332
}
332333

333334
/**

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

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import scala.collection.mutable.ListBuffer
2121
importscala.reflect.internal.util.ListOfNil
2222
importscala.tools.nsc.Reporting.WarningCategory
2323
importscala.tools.nsc.symtab.Flags._
24+
importscala.util.chaining._
2425

2526
/** - uncurry all symbol and tree types (@see UnCurryPhase) -- this includes normalizing all proper types.
2627
* - for every curried parameter list: (ps_1) ... (ps_n) ==> (ps_1, ..., ps_n)
@@ -215,15 +216,32 @@ abstract class UnCurry extends InfoTransform
215216
* new \$anon()
216217
*
217218
*/
218-
deftransformFunction(fun:Function):Tree=
219+
deftransformFunction(fun:Function):Tree= {
220+
// in the forwarding expansion def f(ps) = lifted_f(ps) ensure ps never applied
221+
defnoApplyInExpansion(expansion:Tree):Unit=
222+
expansionmatch {
223+
caseBlock(ClassDef(_, _, _,Template(_, _, body))::Nil, _)=>
224+
body.lastmatch {
225+
casedd:DefDef=>
226+
treeInfo.dissectApplied(dd.rhs).argssmatch {
227+
case args:: _=> args.foreach(noApply.addOne)
228+
case _=>
229+
}
230+
case _=>
231+
}
232+
case _=>
233+
}
219234
// Undo eta expansion for parameterless and nullary methods, EXCEPT if `fun` targets a SAM.
220-
// Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident),
235+
// Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident)
221236
// because we know `cbn` will already be a `Function0` thunk. When we're targeting a SAM,
222237
// 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 }
238+
if (fun.vparams.isEmpty&& isByNameRef(fun.body)&&!fun.attachments.contains[SAMFunction]) {
239+
noApply+= fun.body
240+
fun.body
241+
}
224242
elseif (forceExpandFunction|| inConstructorFlag!=0) {
225243
// Expand the function body into an anonymous class
226-
gen.expandFunction(localTyper)(fun, inConstructorFlag)
244+
gen.expandFunction(localTyper)(fun, inConstructorFlag).tap(noApplyInExpansion)
227245
}else {
228246
valmustExpand= mustExpandFunction(fun)
229247
// method definition with the same arguments, return type, and body as the original lambda
@@ -233,20 +251,23 @@ abstract class UnCurry extends InfoTransform
233251
valnewFun= deriveFunction(fun)(_=> localTyper.typedPos(fun.pos)(
234252
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol))::Nil)
235253
))
254+
deftypeNewFun= localTyper.typedPos(fun.pos)(Block(liftedMethod::Nil,super.transform(newFun)))
236255

237256
if (!mustExpand) {
238257
liftedMethod.symbol.updateAttachment(DelambdafyTarget)
239258
liftedMethod.updateAttachment(DelambdafyTarget)
259+
typeNewFun
240260
}
241-
242-
valtypedNewFun= localTyper.typedPos(fun.pos)(Block(liftedMethod::Nil,super.transform(newFun)))
243-
if (mustExpand) {
244-
valBlock(stats,expr :Function)=typedNewFun:@unchecked
245-
treeCopy.Block(typedNewFun, stats, gen.expandFunction(localTyper)(expr, inConstructorFlag))
246-
}else {
247-
typedNewFun
261+
else typeNewFunmatch {
262+
casetypedNewFun@Block(stats,expr:Function)=>
263+
valexpansion= gen.expandFunction(localTyper)(expr, inConstructorFlag).tap(noApplyInExpansion)
264+
//if (expr.vparams.exists(p => isByNameParamType(p.symbol.info)))
265+
// noApplyInExpansion(expansion)
266+
treeCopy.Block(typedNewFun, stats, expansion)
267+
case x=>thrownewMatchError(x)
248268
}
249269
}
270+
}
250271

251272
deftransformArgs(pos:Position,fun:Symbol,args:List[Tree],params:List[Symbol]):List[Tree]= {
252273
valisJava= fun.isJavaDefined
@@ -333,7 +354,7 @@ abstract class UnCurry extends InfoTransform
333354
}
334355
}
335356
}
336-
valargs1=ListBuffer[Tree]()
357+
valargs1=ListBuffer.empty[Tree]
337358
args1++= args.iterator.take(params.length-1)
338359
args1+= suffix setType params.last.info
339360
args1.toList
@@ -344,12 +365,14 @@ abstract class UnCurry extends InfoTransform
344365

345366
map2Conserve(args1, params) { (arg, param)=>
346367
if (!isByNameParamType(param.info)) arg
347-
elseif (isByNameRef(arg)) {// thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
368+
elseif (isByNameRef(arg)) {
369+
// thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
348370
byNameArgs+= arg
349371
arg setType functionType(Nil, arg.tpe)
350372
}else {
351373
log(s"Argument '$arg' at line${arg.pos.line} is${param.info} from${fun.fullName}")
352-
defcanUseDirectly(qual:Tree)= qual.tpe.typeSymbol.isSubClass(FunctionClass(0))&& treeInfo.isExprSafeToInline(qual)
374+
defcanUseDirectly(qual:Tree)=
375+
qual.tpe.typeSymbol.isSubClass(FunctionClass(0))&& treeInfo.isExprSafeToInline(qual)
353376
argmatch {
354377
// don't add a thunk for by-name argument if argument already is an application of
355378
// a Function0. We can then remove the application and use the existing Function0.
@@ -456,7 +479,7 @@ abstract class UnCurry extends InfoTransform
456479
else translateSynchronized(tree)match {
457480
case dd@DefDef(mods, name, tparams, _, tpt, rhs)=>
458481
// Remove default argument trees from parameter ValDefs, scala/bug#4812
459-
valvparamssNoRhs= dd.vparamssmapConserve (_mapConserve {p=>
482+
valvparamssNoRhs= dd.vparamss.mapConserve(_.mapConserve {p=>
460483
treeCopy.ValDef(p, p.mods, p.name, p.tpt,EmptyTree)
461484
})
462485

@@ -546,10 +569,10 @@ abstract class UnCurry extends InfoTransform
546569
valtree1=super.transform(tree)
547570
if (isByNameRef(tree1)) {
548571
valtree2= tree1 setType functionType(Nil, tree1.tpe)
549-
return {
550-
if (noApplycontainstree2) tree2
572+
valtree3=
573+
if (noApply.contains(tree2)) tree2
551574
else localTyper.typedPos(tree1.pos)(Apply(Select(tree2, nme.apply),Nil))
552-
}
575+
return tree3
553576
}
554577
tree1
555578
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,10 +3045,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
30453045
if (samTp eqNoType)false
30463046
else {
30473047
/* Make a synthetic class symbol to represent the synthetic class that
3048-
* will be spun up by LMF for this function. This is necessary because
3049-
* it's possible that the SAM method might need bridges, and they have
3050-
* to go somewhere. Erasure knows to compute bridges for these classes
3051-
* just as if they were real templates extending the SAM type.*/
3048+
* will be spun up by LMF for this function. This is necessary because
3049+
* it's possible that the SAM method might need bridges, and they have
3050+
* to go somewhere. Erasure knows to compute bridges for these classes
3051+
* just as if they were real templates extending the SAM type.*/
30523052
valsynthCls= fun.symbol.owner.newClassWithInfo(
30533053
name= tpnme.ANON_CLASS_NAME,
30543054
parents=ObjectTpe:: samTp::Nil,
@@ -3065,8 +3065,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
30653065
fun.setType(samTp)
30663066

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

30723072
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-
defcontains[T:ClassTag]:Boolean=
70-
!isEmpty&& (all exists matchesTag[T])
69+
defcontains[T:ClassTag]:Boolean=!isEmpty&& {
70+
valit= all.iterator
71+
valmatchesTagFn= matchesTag[T]
72+
while (it.hasNext) {// OPT: hotspot, hand roll `Set.exists`.
73+
valdatum= it.next()
74+
if (matchesTagFn(datum))returntrue
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
traitSemigroup[F] { self=>
3+
defappend(f1:F,f2:=>F):F
4+
valz=10
5+
}
6+
7+
caseclassBox(i:Int)
8+
9+
classRextendsRunnable {
10+
defrun()= {
11+
valboxSemigroup:Semigroup[Box]= (x1, x2)=>Box(x1.i+ x2.i)
12+
// disallowed, by-name must be inferred
13+
//val boxSemigroup: Semigroup[Box] = (x1: Box, x2: Box) => Box(Math.max(x1.i, x2.i))
14+
assert(boxSemigroup.append(Box(1),Box(2))==Box(3))
15+
}
16+
}
17+
18+
objectTestextendsApp {
19+
newR().run()
20+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp