Skip to content

enclosingInlineds: Clarify invariants #5009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,9 @@ object Trees {

/** A tree representing inlined code.
*
* @param call Info about the original call that was inlined
* Until PostTyper, this is the full call, afterwards only
* @param call Tree representing the original call that was inlined.
* If EmptyTree: this represents an argument actual tree.
* Otherwise: Until PostTyper, this is the full call, afterwards only
* a reference to the toplevel class from which the call was inlined.
* @param bindings Bindings for proxies to be used in the inlined code
* @param expansion The inlined tree, minus bindings.
Expand All @@ -587,6 +588,8 @@ object Trees {
* The reason to keep `bindings` separate is because they are typed in a
* different context: `bindings` represent the arguments to the inlined
* call, whereas `expansion` represents the body of the inlined function.
* Call argument trees (whether kept in `bindings` or inlined in the body)
* are typed in the caller's context.
*/
case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])
extends Tree[T] {
Expand Down
19 changes: 14 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1079,15 +1079,24 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

//inlineContext, enclosingInlineds, sourceFile and Decorators.sourcePos work closely together.

/** A key to be used in a context property that tracks enclosing inlined calls */
private val InlinedCalls = new Property.Key[List[Tree]]

/** Record an enclosing inlined call.
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
* We assume parameters are never nested inside parameters.
/** Record an enclosing inlined call in enclosingInlineds, and produces the context for visiting
* Inlined(call, ...).
*
* Invariants:
* - enclosingInlineds never contains EmptyTree nodes.
* - if enclosingInlineds.nonEmpty, the current tree comes from the file *defining* enclosingInlineds.head.symbol;
* this is exploited in e.g. Decorators.sourcePos.
*
* Arguments of inlined calls (enclosed in Inlined(EmptyTree, ...)) come instead from the call-site, so
* inlineContext(EmptyTree) pops the enclosing call.
*/
override def inlineContext(call: Tree)(implicit ctx: Context): Context = {
// We assume enclosingInlineds is already normalized, and only process the new call with the head.
// enclosingInlineds is already normalized, so we only process the new call with the head.
val oldIC = enclosingInlineds
val newIC = (call, oldIC) match {
case (t, t1 :: ts2) if t.isEmpty =>
Expand All @@ -1106,7 +1115,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
/** The source file where the symbol of the `inline` method referred to by `call`
* is defined
*/
def sourceFile(call: Tree)(implicit ctx: Context) = {
def sourceFile(call: Tree)(implicit ctx: Context): SourceFile = {
val file = call.symbol.sourceFile
val encoding = ctx.settings.encoding.value
if (file != null && file.exists) new SourceFile(file, Codec(encoding)) else NoSource
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case SeqLiteral(elems, elemtpt) =>
"[" ~ toTextGlobal(elems, ",") ~ " : " ~ toText(elemtpt) ~ "]"
case tree @ Inlined(call, bindings, body) =>
(("/* inlined from " ~ toText(call) ~ " */ ") `provided`
!call.isEmpty && !homogenizedView && !ctx.settings.YshowNoInline.value) ~
((if (!call.isEmpty) "/* inlined from " ~ toText(call) ~ " */ " else "/* inline arg */ ": Text) `provided`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should be reverted, we already do this with a slightly different logic.

!homogenizedView && !ctx.settings.YshowNoInline.value) ~
blockText(bindings :+ body)
case tpt: untpd.DerivedTypeTree =>
"<derived typetree watching " ~ summarized(toText(tpt.watched)) ~ ">"
Expand Down