Skip to content

Commit 70ce24f

Browse files
committed
Dissolve NamerContxtOps
Move operations to ContextOps (extension methods) and NamerOps (normal methods)
1 parent a7db8c2 commit 70ce24f

File tree

12 files changed

+173
-164
lines changed

12 files changed

+173
-164
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package ast
44

55
import core._
66
import util.Spans._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
7-
import Symbols._, StdNames._, Trees._, Phases._
7+
import Symbols._, StdNames._, Trees._, Phases._, ContextOps._
88
import Decorators.{given _}, transform.SymUtils._
99
import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName}
1010
import typer.{FrontEnd, Namer}

compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc.ast
22

33
import dotty.tools.dotc.ast.Trees._
44
import dotty.tools.dotc.core.Contexts._
5+
import dotty.tools.dotc.core.ContextOps.enter
56
import dotty.tools.dotc.core.Flags._
67
import dotty.tools.dotc.core.Symbols._
78
import dotty.tools.dotc.core.TypeError
@@ -72,7 +73,8 @@ class TreeMapWithImplicits extends tpd.TreeMap {
7273
new TreeTraverser {
7374
def traverse(tree: Tree)(using Context): Unit = {
7475
tree match {
75-
case d: DefTree if d.symbol.isOneOf(GivenOrImplicit) => nestedCtx.enter(d.symbol)
76+
case d: DefTree if d.symbol.isOneOf(GivenOrImplicit) =>
77+
nestedCtx.enter(d.symbol)
7678
case _ =>
7779
}
7880
traverseChildren(tree)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package dotty.tools.dotc
2+
package core
3+
4+
import Contexts._, Symbols._, Types._, Flags._, Scopes._, Decorators._, NameOps._
5+
import Denotations._
6+
import SymDenotations.LazyType, Names.Name, StdNames.nme
7+
import ast.untpd
8+
9+
/** Operations that are shared between Namer nand TreeUnpickler */
10+
object ContextOps:
11+
12+
extension (ctx: Context):
13+
14+
/** Enter symbol into current class, if current class is owner of current context,
15+
* or into current scope, if not. Should always be called instead of scope.enter
16+
* in order to make sure that updates to class members are reflected in
17+
* finger prints.
18+
*/
19+
def enter(sym: Symbol): Symbol = inContext(ctx) {
20+
ctx.owner match
21+
case cls: ClassSymbol => cls.classDenot.enter(sym)
22+
case _ => scope.openForMutations.enter(sym)
23+
sym
24+
}
25+
26+
/** The denotation with the given `name` and all `required` flags in current context
27+
*/
28+
def denotNamed(name: Name, required: FlagSet = EmptyFlags): Denotation = inContext(ctx) {
29+
if (owner.isClass)
30+
if (outer.owner == owner) { // inner class scope; check whether we are referring to self
31+
if (scope.size == 1) {
32+
val elem = scope.lastEntry
33+
if (elem.name == name) return elem.sym.denot // return self
34+
}
35+
val pre = owner.thisType
36+
pre.findMember(name, pre, required, EmptyFlags)
37+
}
38+
else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext.
39+
owner.findMember(name, owner.thisType, required, EmptyFlags)
40+
else
41+
scope.denotsNamed(name).filterWithFlags(required, EmptyFlags).toDenot(NoPrefix)
42+
}
43+
44+
/** A fresh local context with given tree and owner.
45+
* Owner might not exist (can happen for self valdefs), in which case
46+
* no owner is set in result context
47+
*/
48+
def localContext(tree: untpd.Tree, owner: Symbol): FreshContext = inContext(ctx) {
49+
val freshCtx = fresh.setTree(tree)
50+
if (owner.exists) freshCtx.setOwner(owner) else freshCtx
51+
}
52+
53+
/** Context where `sym` is defined, assuming we are in a nested context. */
54+
def defContext(sym: Symbol): Context = inContext(ctx) {
55+
outersIterator
56+
.dropWhile(_.owner != sym)
57+
.dropWhile(_.owner == sym)
58+
.next()
59+
}
60+
61+
/** A new context for the interior of a class */
62+
def inClassContext(selfInfo: TypeOrSymbol): Context = inContext(ctx) {
63+
val localCtx: Context = fresh.setNewScope
64+
selfInfo match {
65+
case sym: Symbol if sym.exists && sym.name != nme.WILDCARD => localCtx.scope.openForMutations.enter(sym)
66+
case _ =>
67+
}
68+
localCtx
69+
}
70+
71+
def packageContext(tree: untpd.PackageDef, pkg: Symbol): Context = inContext(ctx) {
72+
if (pkg.is(Package)) fresh.setOwner(pkg.moduleClass).setTree(tree)
73+
else ctx
74+
}
75+
end ContextOps

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import ast.Trees._
1515
import ast.untpd
1616
import Flags.GivenOrImplicit
1717
import util.{NoSource, SimpleIdentityMap, SourceFile}
18-
import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer, Nullables}
18+
import typer.{Implicits, ImportInfo, Inliner, SearchHistory, SearchRoot, TypeAssigner, Typer, Nullables}
1919
import Nullables.{NotNullInfo, given _}
2020
import Implicits.ContextualImplicits
2121
import config.Settings._
@@ -98,8 +98,7 @@ object Contexts {
9898
extends Periods
9999
with Phases
100100
with Printers
101-
with Reporting
102-
with NamerContextOps { thiscontext =>
101+
with Reporting { thiscontext =>
103102

104103
given Context = this
105104

@@ -252,6 +251,13 @@ object Contexts {
252251
implicitsCache
253252
}
254253

254+
/** Either the current scope, or, if the current context owner is a class,
255+
* the declarations of the current class.
256+
*/
257+
def effectiveScope(using Context): Scope =
258+
if owner != null && owner.isClass then owner.asClass.unforcedDecls
259+
else scope
260+
255261
/** Sourcefile corresponding to given abstract file, memoized */
256262
def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = {
257263
util.Stats.record("getSource")
@@ -507,6 +513,11 @@ object Contexts {
507513
case None => fresh.dropProperty(key)
508514
}
509515

516+
def typer: Typer = this.typeAssigner match {
517+
case typer: Typer => typer
518+
case _ => new Typer
519+
}
520+
510521
override def toString: String = {
511522
def iinfo(using Context) = if (ctx.importInfo == null) "" else i"${ctx.importInfo.selectors}%, %"
512523
"Context(\n" +
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package dotty.tools.dotc
2+
package core
3+
4+
import Contexts._, Symbols._, Types._, Flags._, Scopes._, Decorators._, NameOps._
5+
import Denotations._
6+
import SymDenotations.LazyType, Names.Name, StdNames.nme
7+
8+
/** Operations that are shared between Namer nand TreeUnpickler */
9+
object NamerOps:
10+
11+
/** The given type, unless `sym` is a constructor, in which case the
12+
* type of the constructed instance is returned
13+
*/
14+
def effectiveResultType(sym: Symbol, typeParams: List[Symbol], givenTp: Type)(using Context): Type =
15+
if (sym.name == nme.CONSTRUCTOR) sym.owner.typeRef.appliedTo(typeParams.map(_.typeRef))
16+
else givenTp
17+
18+
/** if isConstructor, make sure it has one non-implicit parameter list */
19+
def normalizeIfConstructor(termParamss: List[List[Symbol]], isConstructor: Boolean)(using Context): List[List[Symbol]] =
20+
if (isConstructor &&
21+
(termParamss.isEmpty || termParamss.head.nonEmpty && termParamss.head.head.isOneOf(GivenOrImplicit)))
22+
Nil :: termParamss
23+
else
24+
termParamss
25+
26+
/** The method type corresponding to given parameters and result type */
27+
def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(using Context): Type =
28+
val monotpe =
29+
valueParamss.foldRight(resultType) { (params, resultType) =>
30+
val (isContextual, isImplicit, isErased) =
31+
if params.isEmpty then (false, false, false)
32+
else (params.head.is(Given), params.head.is(Implicit), params.head.is(Erased))
33+
val make = MethodType.companion(isJava = isJava, isContextual = isContextual, isImplicit = isImplicit, isErased = isErased)
34+
if isJava then
35+
for param <- params do
36+
if param.info.isDirectRef(defn.ObjectClass) then param.info = defn.AnyType
37+
make.fromSymbols(params, resultType)
38+
}
39+
if typeParams.nonEmpty then PolyType.fromParams(typeParams.asInstanceOf[List[TypeSymbol]], monotpe)
40+
else if valueParamss.isEmpty then ExprType(monotpe)
41+
else monotpe
42+
43+
/** Add moduleClass or sourceModule functionality to completer
44+
* for a module or module class
45+
*/
46+
def adjustModuleCompleter(completer: LazyType, name: Name)(using Context): LazyType =
47+
val scope = ctx.effectiveScope
48+
if name.isTermName then
49+
completer.withModuleClass(implicit ctx => findModuleBuddy(name.moduleClassName, scope))
50+
else
51+
completer.withSourceModule(implicit ctx => findModuleBuddy(name.sourceModuleName, scope))
52+
53+
/** Find moduleClass/sourceModule in effective scope */
54+
private def findModuleBuddy(name: Name, scope: Scope)(using Context) = {
55+
val it = scope.lookupAll(name).filter(_.is(Module))
56+
if (it.hasNext) it.next()
57+
else NoSymbol.assertingErrorsReported(s"no companion $name in $scope")
58+
}
59+
60+
end NamerOps

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import Flags._
1818
import Constants._
1919
import Annotations._
2020
import NameKinds._
21+
import NamerOps._
22+
import ContextOps._
2123
import Variances.Invariant
2224
import typer.ConstFold
2325
import typer.Checking.checkNonCyclic
@@ -559,7 +561,7 @@ class TreeUnpickler(reader: TastyReader,
559561
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
560562
val flags = normalizeFlags(tag, givenFlags, name, isAbsType, rhsIsEmpty)
561563
def adjustIfModule(completer: LazyType) =
562-
if (flags.is(Module)) ctx.adjustModuleCompleter(completer, name) else completer
564+
if (flags.is(Module)) adjustModuleCompleter(completer, name) else completer
563565
val coord = coordAt(start)
564566
val sym =
565567
roots.find(root => (root.owner eq ctx.owner) && root.name == name) match {
@@ -815,10 +817,10 @@ class TreeUnpickler(reader: TastyReader,
815817
val vparamss = readParamss(using localCtx)
816818
val tpt = readTpt()(using localCtx)
817819
val typeParams = tparams.map(_.symbol)
818-
val valueParamss = ctx.normalizeIfConstructor(
820+
val valueParamss = normalizeIfConstructor(
819821
vparamss.nestedMap(_.symbol), name == nme.CONSTRUCTOR)
820-
val resType = ctx.effectiveResultType(sym, typeParams, tpt.tpe)
821-
sym.info = ctx.methodType(typeParams, valueParamss, resType)
822+
val resType = effectiveResultType(sym, typeParams, tpt.tpe)
823+
sym.info = methodType(typeParams, valueParamss, resType)
822824
DefDef(tparams, vparamss, tpt)
823825
case VALDEF =>
824826
val tpt = readTpt()(using localCtx)

compiler/src/dotty/tools/dotc/interactive/Interactive.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import scala.annotation.tailrec
66
import scala.collection._
77

88
import ast.{NavigateAST, Trees, tpd, untpd}
9-
import core._, core.Decorators._
9+
import core._
10+
import Decorators._, ContextOps._
1011
import Contexts._, Flags._, Names._, NameOps._, Symbols._, Trees._, Types._
1112
import transform.SymUtils.decorateSymbol
1213
import util.Spans._, util.SourceFile, util.SourcePosition

compiler/src/dotty/tools/dotc/transform/CookComments.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc.transform
22

33
import dotty.tools.dotc.ast.tpd
44
import dotty.tools.dotc.core.Contexts.{Context, ctx}
5+
import dotty.tools.dotc.core.ContextOps._
56
import dotty.tools.dotc.typer.Docstrings
67

78
class CookComments extends MegaPhase.MiniPhase {

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import Trees._
1919
import Names._
2020
import StdNames._
2121
import NameOps._
22+
import ContextOps._
2223
import NameKinds.DefaultGetterName
2324
import ProtoTypes._
2425
import Inferencing._

compiler/src/dotty/tools/dotc/typer/Deriving.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import ast._
77
import ast.Trees._
88
import StdNames._
99
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
10-
import ProtoTypes._
10+
import ProtoTypes._, ContextOps._
1111
import util.Spans._
1212
import util.SourcePosition
1313
import collection.mutable
@@ -272,8 +272,8 @@ trait Deriving {
272272
(tparamRefs: List[Type]) => (paramRefss: List[List[tpd.Tree]]) =>
273273
val tparams = tparamRefs.map(_.typeSymbol.asType)
274274
val params = if (paramRefss.isEmpty) Nil else paramRefss.head.map(_.symbol.asTerm)
275-
tparams.foreach(ctx.enter)
276-
params.foreach(ctx.enter)
275+
tparams.foreach(sym => ctx.enter(sym))
276+
params.foreach(sym => ctx.enter(sym))
277277
def instantiated(info: Type): Type = info match {
278278
case info: PolyType => instantiated(info.instantiate(tparamRefs))
279279
case info: MethodType => info.instantiate(params.map(_.termRef))

0 commit comments

Comments
 (0)