Skip to content

Commit

Permalink
Add missing parents to companions of case classes in stdlib-bootstrap…
Browse files Browse the repository at this point in the history
…ped (#18153)
  • Loading branch information
sjrd authored Jul 20, 2023
2 parents 5ca1b01 + e0070d4 commit aac8ba7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 27 deletions.
46 changes: 36 additions & 10 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -549,14 +549,19 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>

private def scala2LibPatch(tree: TypeDef)(using Context) =
val sym = tree.symbol
if compilingScala2StdLib
&& sym.is(ModuleClass) && !sym.derivesFrom(defn.SerializableClass)
&& sym.companionClass.derivesFrom(defn.SerializableClass)
then
// Add Serializable to companion objects of serializable classes
if compilingScala2StdLib && sym.is(ModuleClass) then
// Add Serializable to companion objects of serializable classes,
// and add AbstractFunction1 to companion objects of case classes with 1 parameter.
tree.rhs match
case impl: Template =>
val parents1 = impl.parents :+ TypeTree(defn.SerializableType)
var parents1 = impl.parents
val companionClass = sym.companionClass
if !sym.derivesFrom(defn.SerializableClass) && companionClass.derivesFrom(defn.SerializableClass) then
parents1 = parents1 :+ TypeTree(defn.SerializableType)
argTypeOfCaseClassThatNeedsAbstractFunction1(sym) match
case Some(args) if parents1.head.symbol.owner == defn.ObjectClass =>
parents1 = New(defn.AbstractFunctionClass(1).typeRef).select(nme.CONSTRUCTOR).appliedToTypes(args).ensureApplied :: parents1.tail
case _ =>
val impl1 = cpy.Template(impl)(parents = parents1)
cpy.TypeDef(tree)(rhs = impl1)
else tree
Expand All @@ -567,10 +572,31 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>

def transformInfo(tp: Type, sym: Symbol)(using Context): Type = tp match
case info: ClassInfo =>
if !sym.derivesFrom(defn.SerializableClass)
&& sym.companionClass.derivesFrom(defn.SerializableClass)
then
info.derivedClassInfo(declaredParents = info.parents :+ defn.SerializableType)
var parents1 = info.parents
val companionClass = sym.companionClass
if !sym.derivesFrom(defn.SerializableClass) && companionClass.derivesFrom(defn.SerializableClass) then
parents1 = parents1 :+ defn.SerializableType
argTypeOfCaseClassThatNeedsAbstractFunction1(sym) match
case Some(args) if parents1.head.typeSymbol == defn.ObjectClass =>
parents1 = defn.AbstractFunctionClass(1).typeRef.appliedTo(args) :: parents1.tail
case _ =>
if parents1 ne info.parents then info.derivedClassInfo(declaredParents = parents1)
else tp
case _ => tp

private def argTypeOfCaseClassThatNeedsAbstractFunction1(sym: Symbol)(using Context): Option[List[Type]] =
val companionClass = sym.companionClass
if companionClass.is(CaseClass)
&& !companionClass.primaryConstructor.is(Private)
&& !companionClass.primaryConstructor.info.isVarArgsMethod
then
sym.info.decl(nme.apply).info match
case info: MethodType =>
info.paramInfos match
case arg :: Nil =>
Some(arg :: info.resultType :: Nil)
case args => None
case _ => None
else
None
}
10 changes: 2 additions & 8 deletions project/MiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ object MiMaFilters {
// Companion module class
ProblemFilters.exclude[FinalClassProblem]("scala.*$"),

// Missing types {scala.runtime.AbstractFunction1}
ProblemFilters.exclude[MissingTypesProblem]("scala.ScalaReflectionException$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.UninitializedFieldError$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.StringView$"),

// Scala 2 intrinsic macros
ProblemFilters.exclude[FinalMethodProblem]("scala.StringContext.s"),

Expand Down Expand Up @@ -131,15 +126,12 @@ object MiMaFilters {
"scala.collection.mutable.LinkedHashMap.newBuilder", "scala.collection.mutable.LinkedHashSet.newBuilder",
"scala.collection.mutable.LongMap#ToBuildFrom.newBuilder",
"scala.collection.mutable.PriorityQueue#ResizableArrayAccess.this",
"scala.collection.StringView.andThen", "scala.collection.StringView.compose",
"scala.concurrent.BatchingExecutor#AbstractBatch.this",
"scala.concurrent.Channel#LinkedList.this",
"scala.Enumeration#ValueOrdering.this",
"scala.io.Source#RelaxedPosition.this",
"scala.PartialFunction#OrElse.andThen", "scala.PartialFunction#OrElse.orElse",
"scala.runtime.Rich*.num", "scala.runtime.Rich*.ord",
"scala.ScalaReflectionException.andThen", "scala.ScalaReflectionException.compose",
"scala.UninitializedFieldError.andThen", "scala.UninitializedFieldError.compose",
"scala.util.Properties.<clinit>",
"scala.util.Sorting.scala$util$Sorting$$mergeSort$default$5",
).map(ProblemFilters.exclude[DirectMissingMethodProblem])
Expand Down Expand Up @@ -216,6 +208,8 @@ object MiMaFilters {
"scala.collection.mutable.RedBlackTree#Node.apply", "scala.collection.mutable.RedBlackTree#Node.leaf", "scala.collection.mutable.RedBlackTree#Node.unapply", "scala.collection.mutable.RedBlackTree#Tree.empty",
"scala.collection.mutable.UnrolledBuffer.unrolledlength", "scala.collection.mutable.UnrolledBuffer#Unrolled.<init>$default$4",
"scala.collection.Searching#Found.apply", "scala.collection.Searching#Found.unapply",
"scala.collection.Searching#Found.andThen", "scala.collection.Searching#Found.compose",
"scala.collection.Searching#InsertionPoint.andThen", "scala.collection.Searching#InsertionPoint.compose",
"scala.collection.Searching#InsertionPoint.apply", "scala.collection.Searching#InsertionPoint.unapply",
"scala.collection.SortedMapFactoryDefaults.empty", "scala.collection.SortedMapFactoryDefaults.fromSpecific",
"scala.collection.SortedMapOps.ordMsg", "scala.collection.SortedSetOps.ordMsg",
Expand Down
9 changes: 0 additions & 9 deletions project/TastyMiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,6 @@ object TastyMiMaFilters {
// Probably OK: Case class with varargs
ProblemMatcher.make(ProblemKind.IncompatibleTypeChange, "scala.StringContext.parts"), // before: scala.<repeated>[Predef.String]; after: scala.collection.immutable.Seq[Predef.String] @scala.annotation.internal.Repeated

// Problem: Missing type {scala.runtime.AbstractFunction1}
ProblemMatcher.make(ProblemKind.MissingParent, "scala.collection.Searching.Found$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.collection.Searching.InsertionPoint$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.collection.StringView$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.jdk.FunctionWrappers.AsJava*$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.jdk.FunctionWrappers.FromJava*$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.ScalaReflectionException$"),
ProblemMatcher.make(ProblemKind.MissingParent, "scala.UninitializedFieldError$"),

// Probably OK: ConstantType for `null` versus `scala.Null`
// Calls to the default getter seem to link correctly.
// Tested in stdlib-bootstrapped/test/scala/collection/UnrolledBufferTest.scala
Expand Down

0 comments on commit aac8ba7

Please sign in to comment.