Skip to content

Commit

Permalink
Correctly unpickle Scala 2 private case classes in traits (#16519)
Browse files Browse the repository at this point in the history
Fixes #16443

I don't know how to make a test that reproduces the exact problem. In
the test of this commit `TypeHints_1.scala` should be compiled with
Scala 2.13, but I am not sure how to implement that.
  • Loading branch information
odersky authored Dec 14, 2022
2 parents d3070f6 + a7691fe commit 6836037
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 5 deletions.
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/core/NamerOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ object NamerOps:
completer.withSourceModule(findModuleBuddy(name.sourceModuleName, scope))

/** Find moduleClass/sourceModule in effective scope */
def findModuleBuddy(name: Name, scope: Scope)(using Context) = {
val it = scope.lookupAll(name).filter(_.is(Module))
if (it.hasNext) it.next()
def findModuleBuddy(name: Name, scope: Scope, alternate: Name = EmptyTermName)(using Context): Symbol =
var it = scope.lookupAll(name).filter(_.is(Module))
if !alternate.isEmpty then it ++= scope.lookupAll(alternate).filter(_.is(Module))
if it.hasNext then it.next()
else NoSymbol.assertingErrorsReported(em"no companion $name in $scope")
}

/** If a class has one of these flags, it does not get a constructor companion */
private val NoConstructorProxyNeededFlags = Abstract | Trait | Case | Synthetic | Module | Invisible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ object Scala2Unpickler {
val sourceModule = denot.sourceModule.orElse {
// For non-toplevel modules, `sourceModule` won't be set when completing
// the module class, we need to go find it ourselves.
NamerOps.findModuleBuddy(cls.name.sourceModuleName, denot.owner.info.decls)
val modName = cls.name.sourceModuleName
val alternate =
if cls.privateWithin.exists && cls.owner.is(Trait) then modName.expandedName(cls.owner)
else EmptyTermName
NamerOps.findModuleBuddy(modName, denot.owner.info.decls, alternate)
}
denot.owner.thisType.select(sourceModule)
else selfInfo
Expand Down
2 changes: 2 additions & 0 deletions tests/pos/i16443/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@main def Test =
println(NoTypeHints)
15 changes: 15 additions & 0 deletions tests/pos/i16443/TypeHints_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// This should be run with Scala 2.13
trait TypeHints {
val hints: List[Class[_]]
def components: List[TypeHints] = List(this)

def + (hints: TypeHints): TypeHints = CompositeTypeHints(components ::: hints.components)

private case class CompositeTypeHints(override val components: List[TypeHints]) extends TypeHints {
override val hints: List[Class[_]] = components.flatMap(_.hints)
}
}

case object NoTypeHints extends TypeHints {
override val hints = Nil
}

0 comments on commit 6836037

Please sign in to comment.