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

Commitbc2da58

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

File tree

5 files changed

+79
-30
lines changed

5 files changed

+79
-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: 39 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,30 @@ 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+
valargs= treeInfo.dissectApplied(dd.rhs).argss.head
227+
args.foreach(noApply.addOne)
228+
case _=>
229+
}
230+
case _=>
231+
}
219232
// 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),
233+
// Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident)
221234
// because we know `cbn` will already be a `Function0` thunk. When we're targeting a SAM,
222235
// 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 }
236+
if (fun.vparams.isEmpty&& isByNameRef(fun.body)&&!fun.attachments.contains[SAMFunction]) {
237+
noApply+= fun.body
238+
fun.body
239+
}
224240
elseif (forceExpandFunction|| inConstructorFlag!=0) {
225241
// Expand the function body into an anonymous class
226-
gen.expandFunction(localTyper)(fun, inConstructorFlag)
242+
gen.expandFunction(localTyper)(fun, inConstructorFlag).tap(noApplyInExpansion)
227243
}else {
228244
valmustExpand= mustExpandFunction(fun)
229245
// method definition with the same arguments, return type, and body as the original lambda
@@ -233,20 +249,23 @@ abstract class UnCurry extends InfoTransform
233249
valnewFun= deriveFunction(fun)(_=> localTyper.typedPos(fun.pos)(
234250
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol))::Nil)
235251
))
252+
deftypeNewFun= localTyper.typedPos(fun.pos)(Block(liftedMethod::Nil,super.transform(newFun)))
236253

237254
if (!mustExpand) {
238255
liftedMethod.symbol.updateAttachment(DelambdafyTarget)
239256
liftedMethod.updateAttachment(DelambdafyTarget)
257+
typeNewFun
240258
}
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
259+
else typeNewFunmatch {
260+
casetypedNewFun@Block(stats,expr:Function)=>
261+
valexpansion= gen.expandFunction(localTyper)(expr, inConstructorFlag).tap(noApplyInExpansion)
262+
//if (expr.vparams.exists(p => isByNameParamType(p.symbol.info)))
263+
// noApplyInExpansion(expansion)
264+
treeCopy.Block(typedNewFun, stats, expansion)
265+
case x=>thrownewMatchError(x)
248266
}
249267
}
268+
}
250269

251270
deftransformArgs(pos:Position,fun:Symbol,args:List[Tree],params:List[Symbol]):List[Tree]= {
252271
valisJava= fun.isJavaDefined
@@ -333,7 +352,7 @@ abstract class UnCurry extends InfoTransform
333352
}
334353
}
335354
}
336-
valargs1=ListBuffer[Tree]()
355+
valargs1=ListBuffer.empty[Tree]
337356
args1++= args.iterator.take(params.length-1)
338357
args1+= suffix setType params.last.info
339358
args1.toList
@@ -344,12 +363,14 @@ abstract class UnCurry extends InfoTransform
344363

345364
map2Conserve(args1, params) { (arg, param)=>
346365
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
366+
elseif (isByNameRef(arg)) {
367+
// thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
348368
byNameArgs+= arg
349369
arg setType functionType(Nil, arg.tpe)
350370
}else {
351371
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)
372+
defcanUseDirectly(qual:Tree)=
373+
qual.tpe.typeSymbol.isSubClass(FunctionClass(0))&& treeInfo.isExprSafeToInline(qual)
353374
argmatch {
354375
// don't add a thunk for by-name argument if argument already is an application of
355376
// a Function0. We can then remove the application and use the existing Function0.
@@ -456,7 +477,7 @@ abstract class UnCurry extends InfoTransform
456477
else translateSynchronized(tree)match {
457478
case dd@DefDef(mods, name, tparams, _, tpt, rhs)=>
458479
// Remove default argument trees from parameter ValDefs, scala/bug#4812
459-
valvparamssNoRhs= dd.vparamssmapConserve (_mapConserve {p=>
480+
valvparamssNoRhs= dd.vparamss.mapConserve(_.mapConserve {p=>
460481
treeCopy.ValDef(p, p.mods, p.name, p.tpt,EmptyTree)
461482
})
462483

@@ -546,10 +567,10 @@ abstract class UnCurry extends InfoTransform
546567
valtree1=super.transform(tree)
547568
if (isByNameRef(tree1)) {
548569
valtree2= tree1 setType functionType(Nil, tree1.tpe)
549-
return {
550-
if (noApplycontainstree2) tree2
570+
valtree3=
571+
if (noApply.contains(tree2)) tree2
551572
else localTyper.typedPos(tree1.pos)(Apply(Select(tree2, nme.apply),Nil))
552-
}
573+
return tree3
553574
}
554575
tree1
555576
}

‎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