@@ -10,7 +10,7 @@ import Annotations.Annotation
10
10
import NameKinds .{UniqueName , ContextBoundParamName , ContextFunctionParamName , DefaultGetterName , WildcardParamName }
11
11
import typer .{Namer , Checking }
12
12
import util .{Property , SourceFile , SourcePosition , Chars }
13
- import config .Feature
13
+ import config .{ Feature , Config }
14
14
import config .SourceVersion .*
15
15
import collection .mutable .ListBuffer
16
16
import reporting .*
@@ -230,7 +230,8 @@ object desugar {
230
230
tdef : TypeDef ,
231
231
evidenceBuf : ListBuffer [ValDef ],
232
232
flags : FlagSet ,
233
- freshName : => TermName )(using Context ): TypeDef =
233
+ freshName : untpd.Tree => TermName ,
234
+ allParamss : List [ParamClause ])(using Context ): TypeDef =
234
235
235
236
val evidenceNames = ListBuffer [TermName ]()
236
237
@@ -241,11 +242,11 @@ object desugar {
241
242
val evidenceName = bound match
242
243
case ContextBoundTypeTree (_, _, ownName) if ! ownName.isEmpty =>
243
244
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 =>
245
247
tdef.name.toTermName
246
248
case _ =>
247
- if isMember then inventGivenOrExtensionName(bound)
248
- else freshName
249
+ freshName(bound)
249
250
evidenceNames += evidenceName
250
251
val evidenceParam = ValDef (evidenceName, bound, EmptyTree ).withFlags(flags)
251
252
evidenceParam.pushAttachment(ContextBoundParam , ())
@@ -257,9 +258,13 @@ object desugar {
257
258
rhs
258
259
259
260
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)
263
268
else
264
269
tdef1
265
270
end desugarContextBounds
@@ -268,7 +273,7 @@ object desugar {
268
273
val DefDef (_, paramss, tpt, rhs) = meth
269
274
val evidenceParamBuf = ListBuffer [ValDef ]()
270
275
var seenContextBounds : Int = 0
271
- def freshName =
276
+ def freshName ( unused : Tree ) =
272
277
seenContextBounds += 1 // Start at 1 like FreshNameCreator.
273
278
ContextBoundParamName (EmptyTermName , seenContextBounds)
274
279
// Just like with `makeSyntheticParameter` on nameless parameters of
@@ -280,7 +285,7 @@ object desugar {
280
285
val iflag = if Feature .sourceVersion.isAtLeast(`future`) then Given else Implicit
281
286
val flags = if isPrimaryConstructor then iflag | LocalParamAccessor else iflag | Param
282
287
mapParamss(paramss) {
283
- tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName)
288
+ tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName, paramss )
284
289
}(identity)
285
290
286
291
rhs match
@@ -326,9 +331,9 @@ object desugar {
326
331
327
332
def getterParamss (n : Int ): List [ParamClause ] =
328
333
mapParamss(takeUpTo(paramssNoRHS, n)) {
329
- tparam => dropContextBounds(toDefParam(tparam, keepAnnotations = true ))
334
+ tparam => dropContextBounds(toDefParam(tparam, KeepAnnotations . All ))
330
335
} {
331
- vparam => toDefParam(vparam, keepAnnotations = true , keepDefault = false )
336
+ vparam => toDefParam(vparam, KeepAnnotations . All , keepDefault = false )
332
337
}
333
338
334
339
def defaultGetters (paramss : List [ParamClause ], n : Int ): List [DefDef ] = paramss match
@@ -433,7 +438,14 @@ object desugar {
433
438
private def addEvidenceParams (meth : DefDef , params : List [ValDef ])(using Context ): DefDef =
434
439
if params.isEmpty then return meth
435
440
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}")
437
449
438
450
def references (vdef : ValDef ): Boolean =
439
451
vdef.tpt.existsSubTree:
@@ -464,15 +476,26 @@ object desugar {
464
476
465
477
@ sharable private val synthetic = Modifiers (Synthetic )
466
478
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)
470
495
tparam.withMods(mods & EmptyFlags | Param )
471
- }
472
496
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)
476
499
val hasDefault = if keepDefault then HasDefault else EmptyFlags
477
500
// Need to ensure that tree is duplicated since term parameters can be watched
478
501
// and cloning a term parameter will copy its watchers to the clone, which means
@@ -495,8 +518,10 @@ object desugar {
495
518
496
519
def typeDef (tdef : TypeDef )(using Context ): Tree =
497
520
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 )
500
525
if evidenceBuf.isEmpty then result else Thicket (result :: evidenceBuf.toList)
501
526
502
527
/** The expansion of a class definition. See inline comments for what is involved */
@@ -571,7 +596,7 @@ object desugar {
571
596
// Annotations on class _type_ parameters are set on the derived parameters
572
597
// but not on the constructor parameters. The reverse is true for
573
598
// annotations on class _value_ parameters.
574
- val constrTparams = impliedTparams.map(toDefParam(_, keepAnnotations = false ))
599
+ val constrTparams = impliedTparams.map(toDefParam(_, KeepAnnotations . WitnessOnly ))
575
600
def defVparamss =
576
601
if (originalVparamss.isEmpty) { // ensure parameter list is non-empty
577
602
if (isCaseClass)
@@ -582,7 +607,7 @@ object desugar {
582
607
report.error(CaseClassMissingNonImplicitParamList (cdef), namePos)
583
608
ListOfNil
584
609
}
585
- else originalVparamss.nestedMap(toDefParam(_, keepAnnotations = true , keepDefault = true ))
610
+ else originalVparamss.nestedMap(toDefParam(_, KeepAnnotations . All , keepDefault = true ))
586
611
val constrVparamss = defVparamss
587
612
// defVparamss also needed as separate tree nodes in implicitWrappers below.
588
613
// Need to be separate because they are `watch`ed in addParamRefinements.
@@ -608,7 +633,7 @@ object desugar {
608
633
defDef(
609
634
addEvidenceParams(
610
635
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 )))))
612
637
case stat =>
613
638
stat
614
639
}
@@ -914,9 +939,9 @@ object desugar {
914
939
}
915
940
else {
916
941
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
918
943
// 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 )
920
945
then param.withFlags(param.mods.flags | Tracked )
921
946
else param
922
947
match
0 commit comments