-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[WIP] Separate the namer out from the typer. #13762
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ import ast.{tpd, untpd} | |
import tpd.{Tree, TreeTraverser} | ||
import typer.PrepareInlineable.InlineAccessors | ||
import typer.Nullables | ||
import transform.AccessProxies | ||
import transform.SymUtils._ | ||
import core.Decorators._ | ||
import config.SourceVersion | ||
|
@@ -62,7 +63,7 @@ class CompilationUnit protected (val source: SourceFile) { | |
/** Can this compilation unit be suspended */ | ||
def isSuspendable: Boolean = true | ||
|
||
/** Suspends the compilation unit by thowing a SuspendException | ||
/** Suspends the compilation unit by throwing a SuspendException | ||
* and recording the suspended compilation unit | ||
*/ | ||
def suspend()(using Context): Nothing = | ||
|
@@ -85,6 +86,9 @@ class CompilationUnit protected (val source: SourceFile) { | |
def assignmentSpans(using Context): Map[Int, List[Span]] = | ||
if myAssignmentSpans == null then myAssignmentSpans = Nullables.assignmentSpans | ||
myAssignmentSpans | ||
|
||
private[dotc] var inlineAccessors: InlineAccessors = null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the new unpleasant state. |
||
private[dotc] var protectedAccessors: AccessProxies = null | ||
} | ||
|
||
object CompilationUnit { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1410,29 +1410,6 @@ object desugar { | |
FunctionWithMods(params, body, Modifiers(mods)) | ||
} | ||
|
||
/** Add annotation to tree: | ||
* tree @fullName | ||
* | ||
* The annotation is usually represented as a TypeTree referring to the class | ||
* with the given name `fullName`. However, if the annotation matches a file name | ||
* that is still to be entered, the annotation is represented as a cascade of `Selects` | ||
* following `fullName`. This is necessary so that we avoid reading an annotation from | ||
* the classpath that is also compiled from source. | ||
*/ | ||
def makeAnnotated(fullName: String, tree: Tree)(using Context): Annotated = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused. |
||
val parts = fullName.split('.') | ||
val ttree = typerPhase match { | ||
case phase: TyperPhase if phase.stillToBeEntered(parts.last) => | ||
val prefix = | ||
parts.init.foldLeft(Ident(nme.ROOTPKG): Tree)((qual, name) => | ||
Select(qual, name.toTermName)) | ||
Select(prefix, parts.last.toTypeName) | ||
case _ => | ||
TypeTree(requiredClass(fullName).typeRef) | ||
} | ||
Annotated(tree, New(ttree, Nil)) | ||
} | ||
|
||
private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(using Context) = { | ||
val vdef = ValDef(named.name.asTermName, tpt, rhs) | ||
.withMods(mods) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,7 +57,11 @@ class ProtectedAccessors extends MiniPhase { | |
ctx.property(AccessorsKey).get | ||
|
||
override def prepareForUnit(tree: Tree)(using Context): Context = | ||
ctx.fresh.setProperty(AccessorsKey, new Accessors) | ||
var acc = ctx.compilationUnit.protectedAccessors.asInstanceOf[Accessors] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could make this a little cleaner but I wanted to wait for feedback on the right place to put the state. |
||
if (acc == null) | ||
acc = new Accessors() | ||
ctx.compilationUnit.protectedAccessors = acc | ||
ctx.fresh.setProperty(AccessorsKey, acc) | ||
|
||
private class Accessors extends AccessProxies { | ||
val insert: Insert = new Insert { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package dotty.tools | ||
package dotc | ||
package typer | ||
|
||
import core.* | ||
import Phases.* | ||
import Contexts.* | ||
import Symbols.* | ||
import Decorators.* | ||
import ImportInfo.withRootImports | ||
import parsing.JavaParsers.JavaParser | ||
import parsing.Parsers.Parser | ||
import parsing.Parser as ParserPhase | ||
import config.Config | ||
import config.Printers.{ default, typr } | ||
import util.Stats.* | ||
import util.{ NoSourcePosition, SourcePosition } | ||
import scala.util.control.NonFatal | ||
|
||
import ast.Trees.* | ||
import dotty.tools.dotc.core.Denotations.SingleDenotation | ||
|
||
/** | ||
* | ||
* @param addRootImports Set to false in the REPL. Calling [[ImportInfo.withRootImports]] on the [[Context]] | ||
* for each [[CompilationUnit]] causes dotty.tools.repl.ScriptedTests to fail. | ||
*/ | ||
class NamerPhase(addRootImports: Boolean = true) extends Phase { | ||
|
||
override def phaseName: String = NamerPhase.name | ||
override def isTyper: Boolean = true | ||
|
||
// We run TreeChecker only after type checking | ||
override def isCheckable: Boolean = false | ||
|
||
override def allowsImplicitSearch: Boolean = true | ||
|
||
// Run regardless of parsing errors | ||
override def isRunnable(implicit ctx: Context): Boolean = true | ||
|
||
def enterSyms(using Context): Unit = monitor("indexing") { | ||
val unit = ctx.compilationUnit | ||
ctx.typer.index(unit.untpdTree) | ||
typr.println("entered: " + unit.source) | ||
} | ||
|
||
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = | ||
val unitContexts = | ||
for unit <- units yield | ||
val newCtx0 = ctx.fresh.setPhase(this.start).setCompilationUnit(unit) | ||
val newCtx = PrepareInlineable.initContext(newCtx0) | ||
report.inform(s"naming ${unit.source}") | ||
if (addRootImports) | ||
newCtx.withRootImports | ||
else | ||
newCtx | ||
|
||
unitContexts.foreach(enterSyms(using _)) | ||
|
||
ctx.base.parserPhase match { | ||
case p: ParserPhase => | ||
if p.firstXmlPos.exists && !defn.ScalaXmlPackageClass.exists then | ||
report.error( | ||
"""To support XML literals, your project must depend on scala-xml. | ||
|See https://github.com/scala/scala-xml for more information.""".stripMargin, | ||
p.firstXmlPos) | ||
case _ => | ||
} | ||
|
||
|
||
unitContexts.map(_.compilationUnit) | ||
|
||
def run(using Context): Unit = unsupported("run") | ||
} | ||
|
||
object NamerPhase { | ||
val name: String = "namer" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,11 @@ object PrepareInlineable { | |
private val InlineAccessorsKey = new Property.Key[InlineAccessors] | ||
|
||
def initContext(ctx: Context): Context = | ||
ctx.fresh.setProperty(InlineAccessorsKey, new InlineAccessors) | ||
var acc = ctx.compilationUnit.inlineAccessors | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as above. |
||
if (acc == null) | ||
ctx.compilationUnit.inlineAccessors = new InlineAccessors() | ||
acc = ctx.compilationUnit.inlineAccessors | ||
ctx.fresh.setProperty(InlineAccessorsKey, acc) | ||
|
||
def makeInlineable(tree: Tree)(using Context): Tree = | ||
ctx.property(InlineAccessorsKey).get.makeInlineable(tree) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo