When traversing parents inside ClassLikeSupport, there is some strange bug coming from tasty with casting.
java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$DefDef cannot be cast to class dotty.tools.dotc.ast.Trees$TypeDef (dotty.tools.dotc.ast.Trees$DefDef and dotty.tools.dotc.ast.Trees$TypeDef are in unnamed module of loader 'app')
For now, there is workaround to catch errors and ignore them, resulting in heuristically correct graph where it can be
More info can be found in hackGetParents method in dotty.dokka.tasty.ClassLikeSupport. I will double check if this issue still persists.
What is the stack trace?
Stacktrace
java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$DefDef cannot be cast to class dotty.tools.dotc.ast.Trees$TypeDef (dotty.tools.dotc.ast.Trees$DefDef and dotty.tools.dotc.ast.Trees$TypeDef are in unnamed module of loader 'app')
at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDefMethods$.parents(QuotesImpl.scala:239)
at dotty.dokka.tasty.ClassLikeSupport.hackGetParents$1(ClassLikeSupport.scala:67)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$1(ClassLikeSupport.scala:71)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$3$$anonfun$2$$anonfun$1(ClassLikeSupport.scala:75)
at scala.collection.immutable.List.flatMap(List.scala:293)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$4$$anonfun$3(ClassLikeSupport.scala:75)
at scala.Option.fold(Option.scala:263)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$1(ClassLikeSupport.scala:76)
at dotty.dokka.tasty.ClassLikeSupport.mkClass(ClassLikeSupport.scala:86)
at dotty.dokka.tasty.ClassLikeSupport.mkClass$(ClassLikeSupport.scala:16)
at dotty.dokka.tasty.TastyParser.mkClass(TastyParser.scala:150)
at dotty.dokka.tasty.ClassLikeSupport.parseClasslike(ClassLikeSupport.scala:287)
at dotty.dokka.tasty.ClassLikeSupport.parseClasslike$(ClassLikeSupport.scala:16)
at dotty.dokka.tasty.TastyParser.parseClasslike(TastyParser.scala:150)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:190)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree(Quotes.scala:3958)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$$anonfun$1(Quotes.scala:3856)
at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:169)
at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:165)
at scala.collection.immutable.List.foldLeft(List.scala:79)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees(Quotes.scala:3856)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTrees(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree(Quotes.scala:3917)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldOverTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren(Quotes.scala:3960)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTreeChildren(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree(Quotes.scala:3956)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:186)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree(Quotes.scala:3958)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$$anonfun$1(Quotes.scala:3856)
at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:169)
at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:165)
at scala.collection.immutable.List.foldLeft(List.scala:79)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees(Quotes.scala:3856)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTrees(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree(Quotes.scala:3917)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldOverTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren(Quotes.scala:3960)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTreeChildren(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree(Quotes.scala:3956)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:186)
at dotty.dokka.tasty.TastyParser.parseRootTree(TastyParser.scala:195)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess$$anonfun$2(TastyParser.scala:128)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess$$anonfun$3(TastyParser.scala:52)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at scala.collection.immutable.List.foreach(List.scala:333)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess(TastyParser.scala:52)
at scala.tasty.inspector.TastyInspector$TastyInspectorFinishPhase$1.runOn(TastyInspector.scala:89)
at dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:185)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
at dotty.tools.dotc.Run.runPhases$5(Run.scala:195)
at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:203)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
at dotty.tools.dotc.Run.compileUnits(Run.scala:210)
at dotty.tools.dotc.Run.compileUnits(Run.scala:152)
at dotty.tools.dotc.fromtasty.TASTYRun.compile(TASTYRun.scala:11)
at dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
at dotty.tools.dotc.Driver.process(Driver.scala:186)
at scala.tasty.inspector.TastyInspector.inspectFilesInContext(TastyInspector.scala:70)
at scala.tasty.inspector.TastyInspector.inspectFilesInContext$(TastyInspector.scala:20)
at scala.tasty.inspector.DocTastyInspector.inspectFilesInContext(DocTastyInspector.scala:5)
at dotty.dokka.tasty.DokkaTastyInspector.result(TastyParser.scala:138)
at dotty.dokka.ScalaModuleProvider.invoke(ScalaModuleCreator.scala:19)
at org.jetbrains.dokka.DokkaGenerator$translateSources$$inlined$parallelMap$1$1.invokeSuspend(parallelCollectionOperations.kt:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Problem exists for accessing parents of parents with generic parameters (because of that error we have to stop evaluation at C1 though there are further ancestors)

https://scala3doc.virtuslab.com/pr-master/testcases/api/tests/hierarchy/E1.html
https://github.com/lampepfl/dotty/blob/266725f929d184ef51cedc061177a71410be999d/scala3doc-testcases/src/tests/hierarchy.scala
The issue is the following unchecked cast
The solution is to pattern match first to make sure it is a ClassDef
Will try
I observed I made a mistake the first time I was traversing supertypes by calling parents on DefDef symbol, the sufficient fix was to take owner of that DefDef. However, I encountered one more problem, could you @nicolasstucki take a look?
Here is work in progress branch:
https://github.com/lampepfl/dotty/pull/11123/files#diff-71dfe43d69363b55d8c3065200748f758316f63709a8166f203dec1d403b7cebR71
While traversing supertypes if we encounter TypeDef of some scala type wrapping java type, e. g. Serializable or Clonable and we would try call parents on it, it will fail, becuase rhs of TypeDef is not Template, but TypeTree. Is this expected or should I always look if rhs is Template?
Values of tt.tpe.typeSymbol.tree are
TypeDef(Serializable,TypeTree[TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,module class io)),trait Serializable),TypeRef(ThisType(TypeRef(NoPrefix,module class io)),trait Serializable))])
or
```
TypeDef(Cloneable,TypeTree[TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),trait Cloneable),TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),trait Cloneable))])
or
TypeDef(AnyRef,TypeTree[TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Object),TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Object))])
or
TypeDef(Serializable,Select(Select(Ident(java),io),Serializable))
<details><summary>Stacktrace</summary>
java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$TypeTree cannot be cast to class dotty.tools.dotc.ast.Trees$Template (dotty.tools.dotc.ast.Trees$TypeTree and dotty.tools.dotc.ast.Trees$Template are in unnamed module of loader 'app')
at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDefMethods$.parents(QuotesImpl.scala:240)
at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDefMethods$.parents(QuotesImpl.scala:239)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$1(ClassLikeSupport.scala:71)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$2$$anonfun$1(ClassLikeSupport.scala:81)
at scala.collection.immutable.List.flatMap(List.scala:293)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$1(ClassLikeSupport.scala:81)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$2$$anonfun$1(ClassLikeSupport.scala:81)
at scala.collection.immutable.List.flatMap(List.scala:293)
at dotty.dokka.tasty.ClassLikeSupport.getSupertypesGraph$1(ClassLikeSupport.scala:81)
at dotty.dokka.tasty.ClassLikeSupport.mkClass(ClassLikeSupport.scala:91)
at dotty.dokka.tasty.ClassLikeSupport.mkClass$(ClassLikeSupport.scala:16)
at dotty.dokka.tasty.TastyParser.mkClass(TastyParser.scala:150)
at dotty.dokka.tasty.ClassLikeSupport.parseEnum(ClassLikeSupport.scala:317)
at dotty.dokka.tasty.ClassLikeSupport.parseEnum$(ClassLikeSupport.scala:16)
at dotty.dokka.tasty.TastyParser.parseEnum(TastyParser.scala:150)
at dotty.dokka.tasty.ClassLikeSupport.parseClasslike(ClassLikeSupport.scala:291)
at dotty.dokka.tasty.ClassLikeSupport.parseClasslike$(ClassLikeSupport.scala:16)
at dotty.dokka.tasty.TastyParser.parseClasslike(TastyParser.scala:150)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:190)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree(Quotes.scala:3958)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$$anonfun$1(Quotes.scala:3856)
at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:169)
at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:165)
at scala.collection.immutable.List.foldLeft(List.scala:79)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees(Quotes.scala:3856)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTrees(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree(Quotes.scala:3917)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldOverTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren(Quotes.scala:3960)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTreeChildren(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree(Quotes.scala:3956)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:186)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree(Quotes.scala:3958)
at scala.quoted.Quotes$reflectModule$TreeTraverser.foldTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$$anonfun$1(Quotes.scala:3856)
at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:169)
at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:165)
at scala.collection.immutable.List.foldLeft(List.scala:79)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees(Quotes.scala:3856)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldTrees$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldTrees(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree(Quotes.scala:3917)
at scala.quoted.Quotes$reflectModule$TreeAccumulator.foldOverTree$(Quotes.scala:3851)
at dotty.dokka.tasty.TastyParser$Traverser$1$.foldOverTree(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren(Quotes.scala:3960)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTreeChildren$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTreeChildren(TastyParser.scala:178)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree(Quotes.scala:3956)
at scala.quoted.Quotes$reflectModule$TreeTraverser.traverseTree$(Quotes.scala:3954)
at dotty.dokka.tasty.TastyParser$Traverser$1$.traverseTree(TastyParser.scala:186)
at dotty.dokka.tasty.TastyParser.parseRootTree(TastyParser.scala:195)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess$$anonfun$2(TastyParser.scala:128)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess$$anonfun$3(TastyParser.scala:52)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at scala.collection.immutable.List.foreach(List.scala:333)
at dotty.dokka.tasty.DokkaTastyInspector.postProcess(TastyParser.scala:52)
at scala.tasty.inspector.TastyInspector$TastyInspectorFinishPhase$1.runOn(TastyInspector.scala:89)
at dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:185)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
at dotty.tools.dotc.Run.runPhases$5(Run.scala:195)
at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:203)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
at dotty.tools.dotc.Run.compileUnits(Run.scala:210)
at dotty.tools.dotc.Run.compileUnits(Run.scala:152)
at dotty.tools.dotc.fromtasty.TASTYRun.compile(TASTYRun.scala:11)
at dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
at dotty.tools.dotc.Driver.process(Driver.scala:186)
at scala.tasty.inspector.TastyInspector.inspectFilesInContext(TastyInspector.scala:70)
at scala.tasty.inspector.TastyInspector.inspectFilesInContext$(TastyInspector.scala:20)
at scala.tasty.inspector.DocTastyInspector.inspectFilesInContext(DocTastyInspector.scala:5)
at dotty.dokka.tasty.DokkaTastyInspector.result(TastyParser.scala:138)
at dotty.dokka.ScalaModuleProvider.invoke(ScalaModuleCreator.scala:19)
at org.jetbrains.dokka.DokkaGenerator$translateSources$$inlined$parallelMap$1$1.invokeSuspend(parallelCollectionOperations.kt:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
```
That seems to indicate that you are asking for the trees of some type aliases.
type Serializable = java.io.Serializable
type Cloneable = java.lang.Cloneable
type Object = java.lang.Object
type Serializable = java.io.Serializable
Template in not something you should care about in the reflection API. Those are the type definitions representing class definitions. Other TypeDef represent type definitions.
The best you can do is to remove all the asInstanceOf and use checked type tests
- tree.asInstanceOf[ClassDef]
+ tree match
+ case tree: ClassDef => tree
+ case tree => throw MatchError(tree.show(using Printer.TreeStructure))
This will crash as soon as the assumption of the type is wrong and will show you the pattern that you need to match it.
Yeah, I misinterpreted Trees here. Thank you for your help. It's working now
