@@ -11,7 +11,7 @@ import Scopes.Scope
1111import dotty .tools .io .AbstractFile
1212import Decorators .SymbolIteratorDecorator
1313import ast ._
14- import ast .Trees .{LambdaTypeTree , TypeBoundsTree }
14+ import ast .Trees .{LambdaTypeTree , TypeBoundsTree , ValDef , TypeDef }
1515import Trees .Literal
1616import Variances .Variance
1717import 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,59 @@ 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 rawParamss : List [List [Symbol ]] = myParamss
380+ final def rawParamss_= (pss : List [List [Symbol ]]): Unit =
381+ myParamss = pss
382+
383+ final def setParamss (tparams : List [Symbol ], vparamss : List [List [Symbol ]])(using Context ): Unit =
384+ rawParamss = (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+
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 `rawParamss` 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 rawParamss.isEmpty then recurWithoutParamss(info)
419+ else recurWithParamss(info, rawParamss)
420+ val result = info match
421+ case info : PolyType => (allParamss.head, allParamss.tail)
422+ case _ => (Nil , allParamss)
423+ result.asInstanceOf [(List [TypeSymbol ], List [List [TermSymbol ]])]
424+ catch case NonFatal (ex) =>
425+ println(i " paramSymss failure for $symbol, $info, $rawParamss" )
426+ throw ex
427+ end paramSymss
428+
375429 /** The denotation is completed: info is not a lazy type and attributes have defined values */
376430 final def isCompleted : Boolean = ! myInfo.isInstanceOf [LazyType ]
377431
@@ -916,15 +970,19 @@ object SymDenotations {
916970 def isAsConcrete (that : Symbol )(implicit ctx : Context ): Boolean =
917971 ! this .is(Deferred ) || that.is(Deferred )
918972
919- /** Does this symbol have defined or inherited default parameters? */
973+ /** Does this symbol have defined or inherited default parameters?
974+ * Default parameters are recognized until erasure.
975+ */
920976 def hasDefaultParams (implicit ctx : Context ): Boolean =
921- if (this .isOneOf(HasDefaultParamsFlags )) true
922- else if (this .is(NoDefaultParams )) false
923- else {
924- val result = allOverriddenSymbols exists (_.hasDefaultParams)
925- setFlag(if (result) InheritedDefaultParams else NoDefaultParams )
977+ if ctx.erasedTypes then false
978+ else if is(HasDefaultParams ) then true
979+ else if is(NoDefaultParams ) then false
980+ else
981+ val result =
982+ rawParamss.exists(_.exists(_.is(HasDefault )))
983+ || allOverriddenSymbols.exists(_.hasDefaultParams)
984+ setFlag(if result then HasDefaultParams else NoDefaultParams )
926985 result
927- }
928986
929987 /** Symbol is an owner that would be skipped by effectiveOwner. Skipped are
930988 * - package objects
@@ -1452,16 +1510,20 @@ object SymDenotations {
14521510 initFlags : FlagSet = UndefinedFlags ,
14531511 info : Type = null ,
14541512 privateWithin : Symbol = null ,
1455- annotations : List [Annotation ] = null )(implicit ctx : Context ): SymDenotation = {
1513+ annotations : List [Annotation ] = null ,
1514+ rawParamss : List [List [Symbol ]] = null )(
1515+ using ctx : Context ): SymDenotation = {
14561516 // simulate default parameters, while also passing implicit context ctx to the default values
14571517 val initFlags1 = (if (initFlags != UndefinedFlags ) initFlags else this .flags)
14581518 val info1 = if (info != null ) info else this .info
14591519 if (ctx.isAfterTyper && changedClassParents(info, info1, completersMatter = false ))
14601520 assert(ctx.phase.changesParents, i " undeclared parent change at ${ctx.phase} for $this, was: $info, now: $info1" )
14611521 val privateWithin1 = if (privateWithin != null ) privateWithin else this .privateWithin
14621522 val annotations1 = if (annotations != null ) annotations else this .annotations
1523+ val rawParamss1 = if rawParamss != null then rawParamss else this .rawParamss
14631524 val d = ctx.SymDenotation (symbol, owner, name, initFlags1, info1, privateWithin1)
14641525 d.annotations = annotations1
1526+ d.rawParamss = rawParamss1
14651527 d.registeredCompanion = registeredCompanion
14661528 d
14671529 }
0 commit comments