@@ -10,7 +10,7 @@ import Annotations.Annotation
1010import NameKinds .{UniqueName , ContextBoundParamName , ContextFunctionParamName , DefaultGetterName , WildcardParamName }
1111import typer .{Namer , Checking }
1212import util .{Property , SourceFile , SourcePosition , Chars }
13- import config .Feature
13+ import config .{ Feature , Config }
1414import config .SourceVersion .*
1515import collection .mutable .ListBuffer
1616import reporting .*
@@ -230,7 +230,8 @@ object desugar {
230230 tdef : TypeDef ,
231231 evidenceBuf : ListBuffer [ValDef ],
232232 flags : FlagSet ,
233- freshName : => TermName )(using Context ): TypeDef =
233+ freshName : untpd.Tree => TermName ,
234+ allParamss : List [ParamClause ])(using Context ): TypeDef =
234235
235236 val evidenceNames = ListBuffer [TermName ]()
236237
@@ -241,11 +242,11 @@ object desugar {
241242 val evidenceName = bound match
242243 case ContextBoundTypeTree (_, _, ownName) if ! ownName.isEmpty =>
243244 ownName
244- case _ if ! isMember && cxbounds.tail.isEmpty && Feature .enabled(Feature .modularity) =>
245+ case _ if ! isMember && cxbounds.tail.isEmpty
246+ && Feature .enabled(Feature .modularity) && Config .nameSingleContextBounds =>
245247 tdef.name.toTermName
246248 case _ =>
247- if isMember then inventGivenOrExtensionName(bound)
248- else freshName
249+ freshName(bound)
249250 evidenceNames += evidenceName
250251 val evidenceParam = ValDef (evidenceName, bound, EmptyTree ).withFlags(flags)
251252 evidenceParam.pushAttachment(ContextBoundParam , ())
@@ -257,9 +258,13 @@ object desugar {
257258 rhs
258259
259260 val tdef1 = cpy.TypeDef (tdef)(rhs = desugarRhs(tdef.rhs))
260- if evidenceNames.nonEmpty && ! evidenceNames.contains(tdef.name.toTermName) then
261- val witnessNamesAnnot = WitnessNamesAnnot (evidenceNames.toList).withSpan(tdef.span)
262- tdef1.withAddedAnnotation(witnessNamesAnnot)
261+ if Feature .enabled(Feature .modularity)
262+ && evidenceNames.nonEmpty
263+ && ! evidenceNames.contains(tdef.name.toTermName)
264+ && ! allParamss.nestedExists(_.name == tdef.name.toTermName)
265+ then
266+ tdef1.withAddedAnnotation:
267+ WitnessNamesAnnot (evidenceNames.toList).withSpan(tdef.span)
263268 else
264269 tdef1
265270 end desugarContextBounds
@@ -268,7 +273,7 @@ object desugar {
268273 val DefDef (_, paramss, tpt, rhs) = meth
269274 val evidenceParamBuf = ListBuffer [ValDef ]()
270275 var seenContextBounds : Int = 0
271- def freshName =
276+ def freshName ( unused : Tree ) =
272277 seenContextBounds += 1 // Start at 1 like FreshNameCreator.
273278 ContextBoundParamName (EmptyTermName , seenContextBounds)
274279 // Just like with `makeSyntheticParameter` on nameless parameters of
@@ -280,7 +285,7 @@ object desugar {
280285 val iflag = if Feature .sourceVersion.isAtLeast(`future`) then Given else Implicit
281286 val flags = if isPrimaryConstructor then iflag | LocalParamAccessor else iflag | Param
282287 mapParamss(paramss) {
283- tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName)
288+ tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName, paramss )
284289 }(identity)
285290
286291 rhs match
@@ -326,9 +331,9 @@ object desugar {
326331
327332 def getterParamss (n : Int ): List [ParamClause ] =
328333 mapParamss(takeUpTo(paramssNoRHS, n)) {
329- tparam => dropContextBounds(toDefParam(tparam, keepAnnotations = true ))
334+ tparam => dropContextBounds(toDefParam(tparam, KeepAnnotations . All ))
330335 } {
331- vparam => toDefParam(vparam, keepAnnotations = true , keepDefault = false )
336+ vparam => toDefParam(vparam, KeepAnnotations . All , keepDefault = false )
332337 }
333338
334339 def defaultGetters (paramss : List [ParamClause ], n : Int ): List [DefDef ] = paramss match
@@ -433,7 +438,14 @@ object desugar {
433438 private def addEvidenceParams (meth : DefDef , params : List [ValDef ])(using Context ): DefDef =
434439 if params.isEmpty then return meth
435440
436- val boundNames = params.map(_.name).toSet
441+ var boundNames = params.map(_.name).toSet
442+ for mparams <- meth.paramss; mparam <- mparams do
443+ mparam match
444+ case tparam : TypeDef if tparam.mods.annotations.exists(WitnessNamesAnnot .unapply(_).isDefined) =>
445+ boundNames += tparam.name.toTermName
446+ case _ =>
447+
448+ // println(i"add ev params ${meth.name}, ${boundNames.toList}")
437449
438450 def references (vdef : ValDef ): Boolean =
439451 vdef.tpt.existsSubTree:
@@ -464,15 +476,26 @@ object desugar {
464476
465477 @ sharable private val synthetic = Modifiers (Synthetic )
466478
467- private def toDefParam (tparam : TypeDef , keepAnnotations : Boolean ): TypeDef = {
468- var mods = tparam.rawMods
469- if (! keepAnnotations) mods = mods.withAnnotations(Nil )
479+ /** Which annotations to keep in derived parameters */
480+ private enum KeepAnnotations :
481+ case None , All , WitnessOnly
482+
483+ /** Filter annotations in `mods` according to `keep` */
484+ private def filterAnnots (mods : Modifiers , keep : KeepAnnotations )(using Context ) = keep match
485+ case KeepAnnotations .None => mods.withAnnotations(Nil )
486+ case KeepAnnotations .All => mods
487+ case KeepAnnotations .WitnessOnly =>
488+ mods.withAnnotations:
489+ mods.annotations.filter:
490+ case WitnessNamesAnnot (_) => true
491+ case _ => false
492+
493+ private def toDefParam (tparam : TypeDef , keep : KeepAnnotations )(using Context ): TypeDef =
494+ val mods = filterAnnots(tparam.rawMods, keep)
470495 tparam.withMods(mods & EmptyFlags | Param )
471- }
472496
473- private def toDefParam (vparam : ValDef , keepAnnotations : Boolean , keepDefault : Boolean )(using Context ): ValDef = {
474- var mods = vparam.rawMods
475- if (! keepAnnotations) mods = mods.withAnnotations(Nil )
497+ private def toDefParam (vparam : ValDef , keep : KeepAnnotations , keepDefault : Boolean )(using Context ): ValDef = {
498+ val mods = filterAnnots(vparam.rawMods, keep)
476499 val hasDefault = if keepDefault then HasDefault else EmptyFlags
477500 // Need to ensure that tree is duplicated since term parameters can be watched
478501 // and cloning a term parameter will copy its watchers to the clone, which means
@@ -495,8 +518,10 @@ object desugar {
495518
496519 def typeDef (tdef : TypeDef )(using Context ): Tree =
497520 val evidenceBuf = new ListBuffer [ValDef ]
498- val result = desugarContextBounds(tdef, evidenceBuf,
499- (tdef.mods.flags.toTermFlags & AccessFlags ) | Lazy | DeferredGivenFlags , EmptyTermName )
521+ val result = desugarContextBounds(
522+ tdef, evidenceBuf,
523+ (tdef.mods.flags.toTermFlags & AccessFlags ) | Lazy | DeferredGivenFlags ,
524+ inventGivenOrExtensionName, Nil )
500525 if evidenceBuf.isEmpty then result else Thicket (result :: evidenceBuf.toList)
501526
502527 /** The expansion of a class definition. See inline comments for what is involved */
@@ -571,7 +596,7 @@ object desugar {
571596 // Annotations on class _type_ parameters are set on the derived parameters
572597 // but not on the constructor parameters. The reverse is true for
573598 // annotations on class _value_ parameters.
574- val constrTparams = impliedTparams.map(toDefParam(_, keepAnnotations = false ))
599+ val constrTparams = impliedTparams.map(toDefParam(_, KeepAnnotations . WitnessOnly ))
575600 def defVparamss =
576601 if (originalVparamss.isEmpty) { // ensure parameter list is non-empty
577602 if (isCaseClass)
@@ -582,7 +607,7 @@ object desugar {
582607 report.error(CaseClassMissingNonImplicitParamList (cdef), namePos)
583608 ListOfNil
584609 }
585- else originalVparamss.nestedMap(toDefParam(_, keepAnnotations = true , keepDefault = true ))
610+ else originalVparamss.nestedMap(toDefParam(_, KeepAnnotations . All , keepDefault = true ))
586611 val constrVparamss = defVparamss
587612 // defVparamss also needed as separate tree nodes in implicitWrappers below.
588613 // Need to be separate because they are `watch`ed in addParamRefinements.
@@ -608,7 +633,7 @@ object desugar {
608633 defDef(
609634 addEvidenceParams(
610635 cpy.DefDef (ddef)(paramss = joinParams(constrTparams, ddef.paramss)),
611- evidenceParams(constr1).map(toDefParam(_, keepAnnotations = false , keepDefault = false )))))
636+ evidenceParams(constr1).map(toDefParam(_, KeepAnnotations . None , keepDefault = false )))))
612637 case stat =>
613638 stat
614639 }
@@ -914,9 +939,9 @@ object desugar {
914939 }
915940 else {
916941 val defParamss = defVparamss.nestedMapConserve: param =>
917- // for named context bound parameters, we assume that they might have embedded types
942+ // for context bound parameters, we assume that they might have embedded types
918943 // so they should be treated as tracked.
919- if param.hasAttachment(ContextBoundParam ) && ! param.name.is( ContextBoundParamName )
944+ if param.hasAttachment(ContextBoundParam ) && Feature .enabled( Feature .modularity )
920945 then param.withFlags(param.mods.flags | Tracked )
921946 else param
922947 match
0 commit comments