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

Skip to content

Commit 4bb452f

Browse files
committed
pending stabilizers for already typed trees
1 parent 15b6afb commit 4bb452f

File tree

4 files changed

+33
-15
lines changed

4 files changed

+33
-15
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ trait Contexts { self: Analyzer with ImportTracking =>
256256
/** A root import is never unused and always bumps context depth. (e.g scala._ / Predef._ and magic REPL imports) */
257257
def isRootImport: Boolean = false
258258

259+
/** Accumulate stabilizers (PR #5999) and right-assoc locals (#5969 / #7741). See APPSELmode. */
259260
var pendingStabilizers: List[Tree] = Nil
260261

261262
/** Types for which implicit arguments are currently searched */

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

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6302,14 +6302,34 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
63026302
val shouldPrintTyping = printTypings && !phase.erasedTypes && !noPrintTyping(tree)
63036303
val shouldPopTypingStack = shouldPrintTyping && typingStack.beforeNextTyped(tree, mode, pt, context)
63046304

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.
63066311
val shouldInsertStabilizers = !phase.erasedTypes && !mode.in(APPSELmode) && !isMacroImplRef(tree) && {
63076312
tree match { case _: Select | _: Apply | _: TypeApply => true case _ => false }
63086313
}
6309-
63106314
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+
val outer = if (inner.nonEmpty) context.pendingStabilizers.diff(inner) else context.pendingStabilizers
6330+
context.pendingStabilizers = inner
6331+
outer
6332+
}
63136333

63146334
try {
63156335
val ptPlugins = pluginsPt(pt, this, tree, mode1)
@@ -6349,18 +6369,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
63496369
} else result
63506370
}
63516371

6352-
def isRassoc(t: Tree) = t match {
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.
63596372
val result = adapted match {
6360-
case view @ Apply(coercion, coerced :: Nil) if view.hasAttachment[AppliedImplicitView.type] && shouldInsertRassocs =>
6361-
treeCopy.Apply(view, coercion, addStabilizers(coerced) :: Nil)
63626373
case _ if shouldInsertStabilizers => addStabilizers(adapted)
6363-
case _ => adapted
6374+
case _ =>
6375+
if (mode1.in(APPSELmode) && context.pendingStabilizers.nonEmpty)
6376+
adapted.updateAttachment(Stabilizers(context.pendingStabilizers))
6377+
adapted
63646378
}
63656379

63666380
if (shouldPrint)
@@ -6393,7 +6407,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
63936407
} finally {
63946408
if (shouldPopTypingStack) typingStack.pop(tree)
63956409
if (settings.areHotStatisticsEnabled) statistics.popTimer(byTypeStack, startByType)
6396-
if (shouldInsertStabilizers) context.pendingStabilizers = savedPendingStabilizer
6410+
if (shouldInsertStabilizers) context.pendingStabilizers = outerPendingStabilizers
63976411
}
63986412
}
63996413

src/reflect/scala/reflect/internal/StdAttachments.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,6 @@ trait StdAttachments {
193193
case object AppliedImplicitView extends PlainAttachment
194194

195195
case object AppliedToImplicitArgs extends PlainAttachment
196+
197+
case class Stabilizers(ts: List[Tree]) extends PlainAttachment
196198
}

src/reflect/scala/reflect/runtime/JavaUniverseForce.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
9595
this.RightAssociativeArg
9696
this.AppliedImplicitView
9797
this.AppliedToImplicitArgs
98+
this.Stabilizers
9899
this.noPrint
99100
this.typeDebug
100101
// inaccessible: this.posAssigner

0 commit comments

Comments
 (0)