Skip to content

Commit c3029e6

Browse files
committed
More proper way to detect if context bound is used
1 parent 6f8e56d commit c3029e6

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

scaladoc-testcases/src/tests/contextBounds.scala

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class A:
77
def basic[A : ClassTag]: A
88
= ???
99

10+
def basic2[A : ClassTag, B : List]: A
11+
= ???
12+
1013
trait Build[X, Y]
1114
trait From[A, B]
1215
def b[T : ([T] =>> Build[From[T, T], T])](t: T): T
@@ -20,4 +23,17 @@ class A:
2023

2124
// Tests not support multiline signatures
2225
def a[T <: String | Int : ([T] =>> T match { case String => A case Int => B })](t: T): T
23-
= t
26+
= t
27+
28+
def falsePositive[T](evidence$1: ClassTag[T]): Int
29+
= 1
30+
31+
// Scala spec stats that behaviour of names with `$` is undefined.
32+
// Scaladoc documents definition below as `def falsePositive2[T: ClassTag]: Int`
33+
// that is equivalent of methods below
34+
// def falsePositive2[T](implicit evidence$3: ClassTag[T]): Int
35+
// = 1
36+
37+
class Outer[A]:
38+
def falsePositiveInner[T](implicit evidence$3: ClassTag[A]): Int
39+
= 1

scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scala.quoted._
1010
import SymOps._
1111
import NameNormalizer._
1212
import SyntheticsSupport._
13+
import dotty.tools.dotc.core.NameKinds
1314

1415
trait ClassLikeSupport:
1516
self: TastyParser =>
@@ -612,20 +613,21 @@ trait ClassLikeSupport:
612613
contextBounds: Map[String, DSignature] = Map.empty,
613614
)
614615

615-
def isSyntheticEvidence(name: String) = name.startsWith("evidence$")
616616

617617
def unwrapMemberInfo(c: ClassDef, symbol: Symbol): MemberInfo =
618618
val baseTypeRepr = memberInfo(c, symbol)
619619

620+
def isSyntheticEvidence(name: String) =
621+
if !name.startsWith(NameKinds.EvidenceParamName.separator) then false else
622+
symbol.paramSymss.flatten.find(_.name == name).exists(_.flags.is(Flags.Implicit))
623+
620624
def handlePolyType(polyType: PolyType): MemberInfo =
621625
MemberInfo(polyType.paramNames.zip(polyType.paramBounds).toMap, List.empty, polyType.resType)
622626

623627
def handleMethodType(memberInfo: MemberInfo, methodType: MethodType): MemberInfo =
624628
val rawParams = methodType.paramNames.zip(methodType.paramTypes).toMap
625-
val (evidences, newParams) = rawParams.partition(e => isSyntheticEvidence(e._1))
626-
val newLists: List[ParameterList] = if newParams.isEmpty && evidences.nonEmpty
627-
then memberInfo.paramLists ++ Seq(EvidenceOnlyParameterList)
628-
else memberInfo.paramLists ++ Seq(newParams)
629+
val (evidences, notEvidences) = rawParams.partition(e => isSyntheticEvidence(e._1))
630+
629631

630632
def findParamRefs(t: TypeRepr): Seq[ParamRef] = t match
631633
case paramRef: ParamRef => Seq(paramRef)
@@ -638,17 +640,25 @@ trait ClassLikeSupport:
638640
val PolyType(names, _, _) = ref.binder
639641
names(ref.paramNum)
640642

641-
val contextBounds =
642-
evidences.collect {
643+
val (paramsThatLookLikeContextBounds, contextBounds) =
644+
evidences.partitionMap {
643645
case (_, AppliedType(tpe, List(typeParam: ParamRef))) =>
644-
nameForRef(typeParam) -> tpe.asSignature
645-
case (_, original) =>
646-
val typeParam = findParamRefs(original).head // TODO throw nicer error!
647-
val name = nameForRef(typeParam)
648-
val signature = Seq(s"([$name] =>> ") ++ original.asSignature ++ Seq(")")
649-
name -> signature
646+
Right(nameForRef(typeParam) -> tpe.asSignature)
647+
case (name, original) =>
648+
findParamRefs(original) match
649+
case Nil => Left((name, original))
650+
case typeParam :: _ =>
651+
val name = nameForRef(typeParam)
652+
val signature = Seq(s"([$name] =>> ") ++ original.asSignature ++ Seq(")")
653+
Right(name -> signature)
650654
}
651655

656+
val newParams = notEvidences ++ paramsThatLookLikeContextBounds
657+
658+
val newLists: List[ParameterList] = if newParams.isEmpty && contextBounds.nonEmpty
659+
then memberInfo.paramLists ++ Seq(EvidenceOnlyParameterList)
660+
else memberInfo.paramLists ++ Seq(newParams)
661+
652662
MemberInfo(memberInfo.genericTypes, newLists , methodType.resType, contextBounds.toMap)
653663

654664
def handleByNameType(memberInfo: MemberInfo, byNameType: ByNameType): MemberInfo =

0 commit comments

Comments
 (0)