Skip to content

Commit df3f391

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 ad7da2f commit df3f391

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
@@ -150,6 +150,7 @@ object SymDenotations {
150150
private var myFlags: FlagSet = adaptFlags(initFlags)
151151
private var myPrivateWithin: Symbol = initPrivateWithin
152152
private var myAnnotations: List[Annotation] = Nil
153+
private var myParamss: List[List[Symbol]] = Nil
153154

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

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

@@ -1450,16 +1465,20 @@ object SymDenotations {
14501465
initFlags: FlagSet = UndefinedFlags,
14511466
info: Type = null,
14521467
privateWithin: Symbol = null,
1453-
annotations: List[Annotation] = null)(implicit ctx: Context): SymDenotation = {
1468+
annotations: List[Annotation] = null,
1469+
paramss: List[List[Symbol]] = null)(
1470+
using ctx: Context): SymDenotation = {
14541471
// simulate default parameters, while also passing implicit context ctx to the default values
14551472
val initFlags1 = (if (initFlags != UndefinedFlags) initFlags else this.flags)
14561473
val info1 = if (info != null) info else this.info
14571474
if (ctx.isAfterTyper && changedClassParents(info, info1, completersMatter = false))
14581475
assert(ctx.phase.changesParents, i"undeclared parent change at ${ctx.phase} for $this, was: $info, now: $info1")
14591476
val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin
14601477
val annotations1 = if (annotations != null) annotations else this.annotations
1478+
val paramss1 = if paramss != null then paramss else this.paramss
14611479
val d = ctx.SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1)
14621480
d.annotations = annotations1
1481+
d.paramss = paramss1
14631482
d.registeredCompanion = registeredCompanion
14641483
d
14651484
}

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
@@ -422,6 +422,14 @@ class TreeChecker extends Phase with SymTransformer {
422422
}
423423

424424
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree =
425+
def defParamss =
426+
(ddef.tparams :: ddef.vparamss).filter(!_.isEmpty).map(_.map(_.symbol))
427+
def layout(symss: List[List[Symbol]]): String =
428+
symss.map(syms => i"($syms%, %)").mkString
429+
assert(ctx.erasedTypes || sym.paramss == defParamss,
430+
i"""param mismatch for ${sym.showLocated}:
431+
|defined in tree = ${layout(defParamss)}
432+
|stored in symbol = ${layout(sym.paramss)}""")
425433
withDefinedSyms(ddef.tparams) {
426434
withDefinedSyms(ddef.vparamss.flatten) {
427435
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)