@@ -6302,14 +6302,33 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
6302
6302
val shouldPrintTyping = printTypings&& ! phase.erasedTypes&& ! noPrintTyping(tree)
6303
6303
val shouldPopTypingStack = shouldPrintTyping&& typingStack.beforeNextTyped(tree, mode, pt, context)
6304
6304
6305
- // if already in APPSELmode, continue accumulating stabilizers, to be emitted in an enclosing block
6305
+ // After type checking an Apply/Select, e.g., `a.foo(x).b.bar(z)`, which is not part of the qualifier of some
6306
+ // outer Apply/Select, we emit stabilizers (PR #5999) and right-assoc locals (#5969 / #7741) at the end.
6307
+ // { val stab$1 = a.foo(x); val stab$2 = stab$1.b; stab$2.bar(z) }
6308
+ // Setting `APPSELmode` for typing the subexpressions along the qualifier enables accumulating stabilizers,
6309
+ // so if we're already in `APPSELmode` we don't insert them here.
6310
+ // See also doc on APPSELmode.
6306
6311
val shouldInsertStabilizers = ! phase.erasedTypes&& ! mode.in(APPSELmode )&& ! isMacroImplRef(tree)&& {
6307
6312
treematch {case _ :Select | _ :Apply | _ :TypeApply => true case _=> false }
6308
6313
}
6309
-
6310
6314
val mode1 : Mode = if (shouldInsertStabilizers) mode| APPSELmode else mode
6311
- val savedPendingStabilizer = context.pendingStabilizers
6312
- if (shouldInsertStabilizers) context.pendingStabilizers= Nil
6315
+
6316
+ // When starting to type check an outermost Apply/Select, we have to stash pending stabilizers.
6317
+ // Example: `a.b.foo(c.d.bar)`. When typing `c.d.bar`, there is a pending stabilizer for `a.b`.
6318
+ // The `typedArg` method clears the `APPSELmode` for typing `c.d.bar`, so `shouldInsertStabilizers` is true,
6319
+ // but the pending stabilizer should not be inserted here.
6320
+ // There is a corner case: the tree may be type checked already and pending stabilizers might origin in the
6321
+ // subtree, not in some outer tree. Example with adaptToMember:
6322
+ // x.#::(y).#::(z) => adaptToMember creates `conv(conv(x).#::(rassoc$1))`
6323
+ // The argument `conv(x).#::(rassoc$1)` is already typed and there's a pending rassoc. The stabilizer was
6324
+ // not emitted because the expression was part of the qualifier of an outer application.
6325
+ // But with the implicit conversion, the expression is now in argument position, so the stabilizer should be
6326
+ // inserted. The attachment is used to identify pending stabilizers belonging to already typed trees.
6327
+ val outerPendingStabilizers = if (! shouldInsertStabilizers)Nil else {
6328
+ val inner = tree.attachments.get[Stabilizers ].map(_.ts).getOrElse(Nil )
6329
+ context.pendingStabilizers= inner
6330
+ if (inner.nonEmpty) context.pendingStabilizers.diff(inner)else context.pendingStabilizers
6331
+ }
6313
6332
6314
6333
try {
6315
6334
val ptPlugins = pluginsPt(pt,this , tree, mode1)
@@ -6349,18 +6368,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
6349
6368
}else result
6350
6369
}
6351
6370
6352
- def isRassoc (t :Tree )= tmatch {
6353
- case ValDef (_, nm, _, _)=> nm.startsWith(nme.RIGHT_ASSOC_OP_PREFIX )
6354
- case _=> false
6355
- }
6356
- val shouldInsertRassocs = context.pendingStabilizers.exists(isRassoc)
6357
- // if in the midst of series of apply, possibly a qualifier was adapted, possibly an rassoc arg.
6358
- // the expression to rewrite with added stabilizers is different for each case.
6359
6371
val result = adaptedmatch {
6360
- case view@ Apply (coercion, coerced:: Nil )if view.hasAttachment[AppliedImplicitView .type ]&& shouldInsertRassocs=>
6361
- treeCopy.Apply (view, coercion, addStabilizers(coerced):: Nil )
6362
6372
case _if shouldInsertStabilizers=> addStabilizers(adapted)
6363
- case _=> adapted
6373
+ case _=>
6374
+ if (context.pendingStabilizers.nonEmpty)
6375
+ adapted.updateAttachment(Stabilizers (context.pendingStabilizers))
6376
+ adapted
6364
6377
}
6365
6378
6366
6379
if (shouldPrint)
@@ -6393,7 +6406,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
6393
6406
}finally {
6394
6407
if (shouldPopTypingStack) typingStack.pop(tree)
6395
6408
if (settings.areHotStatisticsEnabled) statistics.popTimer(byTypeStack, startByType)
6396
- if (shouldInsertStabilizers) context.pendingStabilizers= savedPendingStabilizer
6409
+ if (shouldInsertStabilizers) context.pendingStabilizers= outerPendingStabilizers
6397
6410
}
6398
6411
}
6399
6412