Skip to content

Commit 5b15c51

Browse files
committed
Make accessing parameter symbols more convenient
Add a method `paramSymss` that mirrors the type structure of a method. Rename the old `paramss` to `rawParamss` to caution against naive uses.
1 parent 7b07414 commit 5b15c51

File tree

6 files changed

+48
-9
lines changed

6 files changed

+48
-9
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,21 +227,21 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
227227
/** A DefDef with given method symbol `sym`.
228228
* @rhsFn A function from type parameter types and term parameter references
229229
* 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.
230+
* Parameter symbols are taken from the `rawParamss` field of `sym`, or
231+
* are freshly generated if `rawParamss` is empty.
232232
*/
233233
def polyDefDef(sym: TermSymbol, rhsFn: List[Type] => List[List[Tree]] => Tree)(implicit ctx: Context): DefDef = {
234234

235235
val (tparams, existingParamss, mtp) = sym.info match {
236236
case tp: PolyType =>
237-
val (tparams, existingParamss) = sym.paramss match
237+
val (tparams, existingParamss) = sym.rawParamss match
238238
case tparams :: vparamss =>
239239
assert(tparams.hasSameLengthAs(tp.paramNames) && tparams.head.isType)
240240
(tparams.asInstanceOf[List[TypeSymbol]], vparamss)
241241
case _ =>
242242
(ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateParamInfos(_)), Nil)
243243
(tparams, existingParamss, tp.instantiate(tparams map (_.typeRef)))
244-
case tp => (Nil, sym.paramss, tp)
244+
case tp => (Nil, sym.rawParamss, tp)
245245
}
246246

247247
def valueParamss(tp: Type, existingParamss: List[List[Symbol]]): (List[List[TermSymbol]], Type) = tp match {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ object Flags {
576576
val SyntheticGivenMethod: FlagSet = Synthetic | Given | Method
577577
val SyntheticModule: FlagSet = Synthetic | Module
578578
val SyntheticOpaque: FlagSet = Synthetic | Opaque
579+
val SyntheticParam: FlagSet = Synthetic | Param
579580
val SyntheticTermParam: FlagSet = Synthetic | TermParam
580581
val SyntheticTypeParam: FlagSet = Synthetic | TypeParam
581582
}

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,44 @@ object SymDenotations {
387387
final def setParamssFromDefs(tparams: List[TypeDef[?]], vparamss: List[List[ValDef[?]]])(using Context): Unit =
388388
setParamss(tparams.map(_.symbol), vparamss.map(_.map(_.symbol)))
389389

390+
/** A pair consistsing of type paremeter symbols and value parameter symbol lists
391+
* of this method definition, or (Nil, Nil) for other symbols.
392+
* Makes use of `paramss` when present, or constructs fresh parameter symbols otherwise.
393+
* This method can be allocation-heavy.
394+
*/
395+
final def paramSymss(using ctx: Context): (List[TypeSymbol], List[List[TermSymbol]]) =
396+
397+
def recurWithParamss(info: Type, paramss: List[List[Symbol]]): List[List[Symbol]] =
398+
info match
399+
case info: LambdaType =>
400+
if info.paramNames.isEmpty then Nil :: recurWithParamss(info.resType, paramss)
401+
else paramss.head :: recurWithParamss(info.resType, paramss.tail)
402+
case _ =>
403+
Nil
404+
405+
def recurWithoutParamss(info: Type): List[List[Symbol]] = info match
406+
case info: LambdaType =>
407+
val params = info.paramNames.lazyZip(info.paramInfos).map((pname, ptype) =>
408+
ctx.newSymbol(symbol, pname, SyntheticParam, ptype))
409+
val prefs = params.map(_.namedType)
410+
for param <- params do
411+
param.info = param.info.substParams(info, prefs)
412+
params :: recurWithoutParamss(info.instantiate(prefs))
413+
case _ =>
414+
Nil
415+
416+
try
417+
val allParamss =
418+
if paramss.isEmpty then recurWithoutParamss(info)
419+
else recurWithParamss(info, paramss)
420+
info match
421+
case info: PolyType => (allParamss.head, allParamss.tail).asInstanceOf
422+
case _ => (Nil, allParamss).asInstanceOf
423+
catch case NonFatal(ex) =>
424+
println(i"paramSymss failure for $symbol, $info, $paramss")
425+
throw ex
426+
end paramSymss
427+
390428
/** The denotation is completed: info is not a lazy type and attributes have defined values */
391429
final def isCompleted: Boolean = !myInfo.isInstanceOf[LazyType]
392430

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
176176
/** A map from symbols to their associated `decls` scopes */
177177
private val symScopes = mutable.AnyRefMap[Symbol, Scope]()
178178

179-
/** A dummy buffer to pass to `readType` when no `paramss` are collected */
179+
/** A dummy buffer to pass to `readType` when no `rawParamss` are collected */
180180
private val throwAwayBuffer = new ListBuffer[List[Symbol]]
181181

182182
protected def errorBadSignature(msg: String, original: Option[RuntimeException] = None)(implicit ctx: Context): Nothing = {
@@ -581,7 +581,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
581581
if denot.is(Method) then new ListBuffer[List[Symbol]]
582582
else throwAwayBuffer
583583
val tp = at(inforef, () => readType(paramssBuf)(ctx))
584-
if denot.is(Method) then denot.paramss = paramssBuf.toList
584+
if denot.is(Method) then denot.rawParamss = paramssBuf.toList
585585

586586
denot match {
587587
case denot: ClassDenotation if !isRefinementClass(denot.symbol) =>

compiler/src/dotty/tools/dotc/reporting/Message.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ abstract class Message(val errorId: ErrorMessageID) { self =>
8989
* they look weird and are normally follow-up errors to something that was
9090
* diagnosed before.
9191
*/
92-
def isNonSensical: Boolean = { message; myIsNonSensical }
92+
def isNonSensical: Boolean = { message; myIsNonSensical }
9393

9494
/** The implicit `Context` in messages is a large thing that we don't want
9595
* persisted. This method gets around that by duplicating the message,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,10 @@ class TreeChecker extends Phase with SymTransformer {
426426
(ddef.tparams :: ddef.vparamss).filter(!_.isEmpty).map(_.map(_.symbol))
427427
def layout(symss: List[List[Symbol]]): String =
428428
symss.map(syms => i"($syms%, %)").mkString
429-
assert(ctx.erasedTypes || sym.paramss == defParamss,
429+
assert(ctx.erasedTypes || sym.rawParamss == defParamss,
430430
i"""param mismatch for ${sym.showLocated}:
431431
|defined in tree = ${layout(defParamss)}
432-
|stored in symbol = ${layout(sym.paramss)}""")
432+
|stored in symbol = ${layout(sym.rawParamss)}""")
433433
withDefinedSyms(ddef.tparams) {
434434
withDefinedSyms(ddef.vparamss.flatten) {
435435
if (!sym.isClassConstructor && !(sym.name eq nme.STATIC_CONSTRUCTOR))

0 commit comments

Comments
 (0)