Skip to content

Update macro docs #17060

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

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/inlines/PrepareInlineable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import inlines.Inlines
import NameOps._
import Annotations._
import transform.{AccessProxies, Splicer}
import staging.PCPCheckAndHeal
import staging.CrossStageSafety
import transform.SymUtils.*
import config.Printers.inlining
import util.Property
Expand Down Expand Up @@ -294,7 +294,7 @@ object PrepareInlineable {
if (code.symbol.flags.is(Inline))
report.error("Macro cannot be implemented with an `inline` method", code.srcPos)
Splicer.checkValidMacroBody(code)
(new PCPCheckAndHeal).transform(body) // Ignore output, only check PCP
(new CrossStageSafety).transform(body) // Ignore output, only check cross-stage safety
case Block(List(stat), Literal(Constants.Constant(()))) => checkMacro(stat)
case Block(Nil, expr) => checkMacro(expr)
case Typed(expr, _) => checkMacro(expr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import dotty.tools.dotc.util.Property
import dotty.tools.dotc.util.Spans._
import dotty.tools.dotc.util.SrcPos

/** Checks that the Phase Consistency Principle (PCP) holds and heals types.
/** Checks that staging level consistency holds and heals staged types .
*
* Local term references are phase consistent if and only if they are used at the same level as their definition.
* Local term references are level consistent if and only if they are used at the same level as their definition.
*
* Local type references can be used at the level of their definition or lower. If used used at a higher level,
* it will be healed if possible, otherwise it is inconsistent.
*
* Type healing consists in transforming a phase inconsistent type `T` into `summon[Type[T]].Underlying`.
* Type healing consists in transforming a level inconsistent type `T` into `summon[Type[T]].Underlying`.
*
* As references to types do not necessarily have an associated tree it is not always possible to replace the types directly.
* Instead we always generate a type alias for it and place it at the start of the surrounding quote. This also avoids duplication.
Expand All @@ -43,7 +43,7 @@ import dotty.tools.dotc.util.SrcPos
* }
*
*/
class PCPCheckAndHeal extends TreeMapWithStages {
class CrossStageSafety extends TreeMapWithStages {
import tpd._

private val InAnnotation = Property.Key[Unit]()
Expand Down Expand Up @@ -97,7 +97,7 @@ class PCPCheckAndHeal extends TreeMapWithStages {
super.transform(tree)
}

/** Transform quoted trees while maintaining phase correctness */
/** Transform quoted trees while maintaining level correctness */
override protected def transformQuotation(body: Tree, quote: Apply)(using Context): Tree = {
val taggedTypes = new QuoteTypeTags(quote.span)

Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/staging/QuoteContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.util.Property
import dotty.tools.dotc.staging.PCPCheckAndHeal
import dotty.tools.dotc.staging.StagingLevel.*

object QuoteContext {
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/Splicing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import dotty.tools.dotc.core.Names._
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.quoted._
import dotty.tools.dotc.config.ScalaRelease.*
import dotty.tools.dotc.staging.PCPCheckAndHeal
import dotty.tools.dotc.staging.QuoteContext.*
import dotty.tools.dotc.staging.StagingLevel.*
import dotty.tools.dotc.staging.QuoteTypeTags
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/dotty/tools/dotc/transform/Staging.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import dotty.tools.dotc.util.SrcPos
import dotty.tools.dotc.transform.SymUtils._
import dotty.tools.dotc.staging.QuoteContext.*
import dotty.tools.dotc.staging.StagingLevel.*
import dotty.tools.dotc.staging.PCPCheckAndHeal
import dotty.tools.dotc.staging.CrossStageSafety
import dotty.tools.dotc.staging.HealType

/** Checks that the Phase Consistency Principle (PCP) holds and heals types.
/** Checks that staging level consistency holds and heals types used in higher levels.
*
* Type healing consists in transforming a phase inconsistent type `T` into `${ implicitly[Type[T]] }`.
* See `CrossStageSafety`
*/
class Staging extends MacroTransform {
import tpd._
Expand All @@ -32,10 +32,10 @@ class Staging extends MacroTransform {

override def checkPostCondition(tree: Tree)(using Context): Unit =
if (ctx.phase <= splicingPhase) {
// Recheck that PCP holds but do not heal any inconsistent types as they should already have been heald
// Recheck that staging level consistency holds but do not heal any inconsistent types as they should already have been heald
tree match {
case PackageDef(pid, _) if tree.symbol.owner == defn.RootClass =>
val checker = new PCPCheckAndHeal {
val checker = new CrossStageSafety {
override protected def healType(pos: SrcPos)(using Context) = new HealType(pos) {
override protected def tryHeal(sym: Symbol, tp: TypeRef, pos: SrcPos): TypeRef = {
def symStr =
Expand Down Expand Up @@ -72,7 +72,7 @@ class Staging extends MacroTransform {

protected def newTransformer(using Context): Transformer = new Transformer {
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
(new PCPCheckAndHeal).transform(tree)
(new CrossStageSafety).transform(tree)
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ object TreeChecker {
val inliningPhase = ctx.base.inliningPhase
inliningPhase.exists && ctx.phase.id > inliningPhase.id
if isAfterInlining then
// The staging phase destroys in PCPCheckAndHeal the property that
// The staging phase destroys in CrossStageSafety the property that
// tree.expr.tpe <:< pt1. A test case where this arises is run-macros/enum-nat-macro.
// We should follow up why this happens. If the problem is fixed, we can
// drop the isAfterInlining special case. To reproduce the problem, just
Expand Down
5 changes: 4 additions & 1 deletion docs/_docs/internals/overall-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,17 @@ phases. The current list of phases is specified in class [Compiler] as follows:
List(new semanticdb.ExtractSemanticDB) :: // Extract info into .semanticdb files
List(new PostTyper) :: // Additional checks and cleanups after type checking
List(new sjs.PrepJSInterop) :: // Additional checks and transformations for Scala.js (Scala.js only)
List(new Staging) :: // Check PCP, heal quoted types and expand macros
List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks
List(new SetRootTree) :: // Set the `rootTreeOrProvider` on class symbols
Nil

/** Phases dealing with TASTY tree pickling and unpickling */
protected def picklerPhases: List[List[Phase]] =
List(new Pickler) :: // Generate TASTY info
List(new Inlining) :: // Inline and execute macros
List(new PostInlining) :: // Add mirror support for inlined code
List(new Staging) :: // Check staging levels and heal staged types
List(new Splicing) :: // Replace level 1 splices with holes
List(new PickleQuotes) :: // Turn quoted trees into explicit run-time data structures
Nil

Expand Down
Loading