Skip to content

Commit 56e37ff

Browse files
committed
Keep track of method parameter symbols
Store the parameter symbols of a method in a `paramss` field of the method symbol. Parameter symbols are kept up-to-date until erasure.
1 parent ee19855 commit 56e37ff

File tree

6 files changed

+64
-11
lines changed

6 files changed

+64
-11
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class TreeTypeMap(
9494
val (tmap1, tparams1) = transformDefs(ddef.tparams)
9595
val (tmap2, vparamss1) = tmap1.transformVParamss(vparamss)
9696
val res = cpy.DefDef(ddef)(name, tparams1, vparamss1, tmap2.transform(tpt), tmap2.transform(ddef.rhs))
97+
res.symbol.setParamssFromDefs(tparams1, vparamss1)
9798
res.symbol.transformAnnotations {
9899
case ann: BodyAnnotation => ann.derivedAnnotation(transform(ann.tree))
99100
case ann => ann

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

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
208208

209209
def DefDef(sym: TermSymbol, tparams: List[TypeSymbol], vparamss: List[List[TermSymbol]],
210210
resultType: Type, rhs: Tree)(implicit ctx: Context): DefDef =
211+
sym.setParamss(tparams, vparamss)
211212
ta.assignType(
212213
untpd.DefDef(
213214
sym.name,
@@ -223,15 +224,27 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
223224
def DefDef(sym: TermSymbol, rhsFn: List[List[Tree]] => Tree)(implicit ctx: Context): DefDef =
224225
polyDefDef(sym, Function.const(rhsFn))
225226

227+
/** A DefDef with given method symbol `sym`.
228+
* @rhsFn A function from type parameter types and term parameter references
229+
* to the method's right-hand side.
230+
* Parameter symbols are taken from the `paramss` field of `sym`, or
231+
* are freshly generated if `paramss` is empty.
232+
*/
226233
def polyDefDef(sym: TermSymbol, rhsFn: List[Type] => List[List[Tree]] => Tree)(implicit ctx: Context): DefDef = {
227-
val (tparams, mtp) = sym.info match {
234+
235+
val (tparams, existingParamss, mtp) = sym.info match {
228236
case tp: PolyType =>
229-
val tparams = ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateParamInfos(_))
230-
(tparams, tp.instantiate(tparams map (_.typeRef)))
231-
case tp => (Nil, tp)
237+
val (tparams, existingParamss) = sym.paramss match
238+
case tparams :: vparamss =>
239+
assert(tparams.hasSameLengthAs(tp.paramNames) && tparams.head.isType)
240+
(tparams.asInstanceOf[List[TypeSymbol]], vparamss)
241+
case _ =>
242+
(ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateParamInfos(_)), Nil)
243+
(tparams, existingParamss, tp.instantiate(tparams map (_.typeRef)))
244+
case tp => (Nil, sym.paramss, tp)
232245
}
233246

234-
def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match {
247+
def valueParamss(tp: Type, existingParamss: List[List[Symbol]]): (List[List[TermSymbol]], Type) = tp match {
235248
case tp: MethodType =>
236249
val isParamDependent = tp.isParamDependent
237250
val previousParamRefs = if (isParamDependent) mutable.ListBuffer[TermRef]() else null
@@ -254,14 +267,23 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
254267
makeSym(origInfo)
255268
}
256269

257-
val params = tp.paramNames.lazyZip(tp.paramInfos).map(valueParam)
258-
val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef)))
270+
val (params, existingParamss1) =
271+
if tp.paramInfos.isEmpty then (Nil, existingParamss)
272+
else existingParamss match
273+
case vparams :: existingParamss1 =>
274+
assert(vparams.hasSameLengthAs(tp.paramNames) && vparams.head.isTerm)
275+
(vparams.asInstanceOf[List[TermSymbol]], existingParamss1)
276+
case _ =>
277+
(tp.paramNames.lazyZip(tp.paramInfos).map(valueParam), Nil)
278+
val (paramss, rtp) =
279+
valueParamss(tp.instantiate(params map (_.termRef)), existingParamss1)
259280
(params :: paramss, rtp)
260281
case tp => (Nil, tp.widenExpr)
261282
}
262-
val (vparamss, rtp) = valueParamss(mtp)
283+
val (vparamss, rtp) = valueParamss(mtp, existingParamss)
263284
val targs = tparams map (_.typeRef)
264285
val argss = vparamss.nestedMap(vparam => Ident(vparam.termRef))
286+
sym.setParamss(tparams, vparamss)
265287
DefDef(sym, tparams, vparamss, rtp, rhsFn(targs)(argss))
266288
}
267289

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Scopes.Scope
1111
import dotty.tools.io.AbstractFile
1212
import Decorators.SymbolIteratorDecorator
1313
import ast._
14-
import ast.Trees.{LambdaTypeTree, TypeBoundsTree}
14+
import ast.Trees.{LambdaTypeTree, TypeBoundsTree, ValDef, TypeDef}
1515
import Trees.Literal
1616
import Variances.Variance
1717
import annotation.tailrec
@@ -151,6 +151,7 @@ object SymDenotations {
151151
private var myFlags: FlagSet = adaptFlags(initFlags)
152152
private var myPrivateWithin: Symbol = initPrivateWithin
153153
private var myAnnotations: List[Annotation] = Nil
154+
private var myParamss: List[List[Symbol]] = Nil
154155

155156
/** The owner of the symbol; overridden in NoDenotation */
156157
def owner: Symbol = maybeOwner
@@ -373,6 +374,20 @@ object SymDenotations {
373374
case Nil => Nil
374375
}
375376

377+
/** If this is a method, the parameter symbols, by section.
378+
* Both type and value parameters are included. Empty sections are skipped.
379+
*/
380+
final def paramss: List[List[Symbol]] = myParamss
381+
final def paramss_=(pss: List[List[Symbol]]): Unit =
382+
myParamss = pss
383+
384+
final def setParamss(tparams: List[Symbol], vparamss: List[List[Symbol]])(using Context): Unit =
385+
paramss = (if tparams.isEmpty then vparamss else tparams :: vparamss)
386+
.filterConserve(!_.isEmpty)
387+
388+
final def setParamssFromDefs(tparams: List[TypeDef[?]], vparamss: List[List[ValDef[?]]])(using Context): Unit =
389+
setParamss(tparams.map(_.symbol), vparamss.map(_.map(_.symbol)))
390+
376391
/** The denotation is completed: info is not a lazy type and attributes have defined values */
377392
final def isCompleted: Boolean = !myInfo.isInstanceOf[LazyType]
378393

@@ -1447,16 +1462,20 @@ object SymDenotations {
14471462
initFlags: FlagSet = UndefinedFlags,
14481463
info: Type = null,
14491464
privateWithin: Symbol = null,
1450-
annotations: List[Annotation] = null)(implicit ctx: Context): SymDenotation = {
1465+
annotations: List[Annotation] = null,
1466+
paramss: List[List[Symbol]] = null)(
1467+
using ctx: Context): SymDenotation = {
14511468
// simulate default parameters, while also passing implicit context ctx to the default values
14521469
val initFlags1 = (if (initFlags != UndefinedFlags) initFlags else this.flags)
14531470
val info1 = if (info != null) info else this.info
14541471
if (ctx.isAfterTyper && changedClassParents(info, info1, completersMatter = false))
14551472
assert(ctx.phase.changesParents, i"undeclared parent change at ${ctx.phase} for $this, was: $info, now: $info1")
14561473
val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin
14571474
val annotations1 = if (annotations != null) annotations else this.annotations
1475+
val paramss1 = if paramss != null then paramss else this.paramss
14581476
val d = ctx.SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1)
14591477
d.annotations = annotations1
1478+
d.paramss = paramss1
14601479
d.registeredCompanion = registeredCompanion
14611480
d
14621481
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
9797
override def transformDefDef(tree: DefDef)(implicit ctx: Context): DefDef = {
9898
val sym = tree.symbol
9999
if (sym.isConstructor && sym.owner.derivesFromJavaEnum)
100-
cpy.DefDef(tree)(
100+
val tree1 = cpy.DefDef(tree)(
101101
vparamss = tree.vparamss.init :+ (tree.vparamss.last ++ addedParams(sym, Param)))
102+
sym.setParamssFromDefs(tree1.tparams, tree1.vparamss)
103+
tree1
102104
else if (sym.name == nme.DOLLAR_NEW && sym.owner.linkedClass.derivesFromJavaEnum) {
103105
val Block((tdef @ TypeDef(tpnme.ANON_CLASS, templ: Template)) :: Nil, call) = tree.rhs
104106
val args = tree.vparamss.last.takeRight(2).map(param => ref(param.symbol)).reverse

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,14 @@ class TreeChecker extends Phase with SymTransformer {
419419
}
420420

421421
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree =
422+
def defParamss =
423+
(ddef.tparams :: ddef.vparamss).filter(!_.isEmpty).map(_.map(_.symbol))
424+
def layout(symss: List[List[Symbol]]): String =
425+
symss.map(syms => i"($syms%, %)").mkString
426+
assert(ctx.erasedTypes || sym.paramss == defParamss,
427+
i"""param mismatch for ${sym.showLocated}:
428+
|defined in tree = ${layout(defParamss)}
429+
|stored in symbol = ${layout(sym.paramss)}""")
422430
withDefinedSyms(ddef.tparams) {
423431
withDefinedSyms(ddef.vparamss.flatten) {
424432
if (!sym.isClassConstructor && !(sym.name eq nme.STATIC_CONSTRUCTOR))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,7 @@ class Namer { typer: Typer =>
15531553
vparamss foreach completeParams
15541554
def typeParams = tparams map symbolOfTree
15551555
val termParamss = ctx.normalizeIfConstructor(vparamss.nestedMap(symbolOfTree), isConstructor)
1556+
sym.setParamss(typeParams, termParamss)
15561557
def wrapMethType(restpe: Type): Type = {
15571558
instantiateDependent(restpe, typeParams, termParamss)
15581559
ctx.methodType(tparams map symbolOfTree, termParamss, restpe, isJava = ddef.mods.is(JavaDefined))

0 commit comments

Comments
 (0)