From 9e159dbeb57ccb2d928a3df5fa23114bf2cdd09f Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 3 Jun 2021 20:54:35 +0200 Subject: [PATCH] fix #12401: mangle ctor names in ExtractAPI --- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../tools/dotc/sbt/ExtractDependencies.scala | 12 ++---------- compiler/src/dotty/tools/dotc/sbt/package.scala | 16 ++++++++++++++++ .../constructors-curried/A.scala | 1 + .../constructors-curried/B.scala | 1 + .../constructors-curried/changes/A2.scala | 1 + .../constructors-curried/changes/B2.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 ++++++++++++ .../constructors-curried/test | 10 ++++++++++ .../source-dependencies/constructors/A.scala | 1 + .../source-dependencies/constructors/B.scala | 1 + .../constructors/changes/A2.scala | 1 + .../constructors/changes/B2.scala | 1 + .../project/DottyInjectedPlugin.scala | 12 ++++++++++++ sbt-test/source-dependencies/constructors/test | 10 ++++++++++ 15 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/sbt/package.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/A.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/B.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/changes/A2.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/changes/B2.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/project/DottyInjectedPlugin.scala create mode 100644 sbt-test/source-dependencies/constructors-curried/test create mode 100644 sbt-test/source-dependencies/constructors/A.scala create mode 100644 sbt-test/source-dependencies/constructors/B.scala create mode 100644 sbt-test/source-dependencies/constructors/changes/A2.scala create mode 100644 sbt-test/source-dependencies/constructors/changes/B2.scala create mode 100644 sbt-test/source-dependencies/constructors/project/DottyInjectedPlugin.scala create mode 100644 sbt-test/source-dependencies/constructors/test diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index cf8b3e01822a..9dc51eb0108f 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -366,7 +366,7 @@ private class ExtractAPICollector(using Context) extends ThunkHolder { val vparamss = paramLists(sym.info, sym.paramSymss) val retTp = sym.info.finalResultType.widenExpr - api.Def.of(sym.name.toString, apiAccess(sym), apiModifiers(sym), + api.Def.of(sym.zincMangledName.toString, apiAccess(sym), apiModifiers(sym), apiAnnotations(sym).toArray, tparams.toArray, vparamss.toArray, apiType(retTp)) } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 860e9e3e6c4c..4294e55da470 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -310,14 +310,6 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT } } - /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ - private def mangledName(sym: Symbol)(using Context): Name = { - def constructorName = sym.owner.fullName ++ ";init;" - - if (sym.isConstructor) constructorName - else sym.name.stripModuleClassSuffix - } - private def addMemberRefDependency(sym: Symbol)(using Context): Unit = if (!ignoreDependency(sym)) { val enclOrModuleClass = if (sym.is(ModuleVal)) sym.moduleClass else sym.enclosingClass @@ -327,7 +319,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT if (fromClass.exists) { // can happen when visiting imports assert(fromClass.isClass) - addUsedName(fromClass, mangledName(sym), UseScope.Default) + addUsedName(fromClass, sym.zincMangledName, UseScope.Default) // packages have class symbol. Only record them as used names but not dependency if (!sym.is(Package)) { _dependencies += ClassDependency(fromClass, enclOrModuleClass, DependencyByMemberRef) @@ -490,7 +482,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT val traverser = new TypeDependencyTraverser { def addDependency(symbol: Symbol) = if (!ignoreDependency(symbol) && symbol.is(Sealed)) { - val usedName = mangledName(symbol) + val usedName = symbol.zincMangledName addUsedName(usedName, UseScope.PatMatTarget) } } diff --git a/compiler/src/dotty/tools/dotc/sbt/package.scala b/compiler/src/dotty/tools/dotc/sbt/package.scala new file mode 100644 index 000000000000..d5f9a289c800 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/sbt/package.scala @@ -0,0 +1,16 @@ +package dotty.tools.dotc.sbt + +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Symbols.Symbol +import dotty.tools.dotc.core.NameOps.stripModuleClassSuffix +import dotty.tools.dotc.core.Names.Name + +extension (sym: Symbol) + + def constructorName(using Context) = + sym.owner.fullName ++ ";init;" + + /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ + def zincMangledName(using Context): Name = + if (sym.isConstructor) constructorName + else sym.name.stripModuleClassSuffix diff --git a/sbt-test/source-dependencies/constructors-curried/A.scala b/sbt-test/source-dependencies/constructors-curried/A.scala new file mode 100644 index 000000000000..b81025bada4d --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/A.scala @@ -0,0 +1 @@ +class A(a: Int) diff --git a/sbt-test/source-dependencies/constructors-curried/B.scala b/sbt-test/source-dependencies/constructors-curried/B.scala new file mode 100644 index 000000000000..e44b1d4c7852 --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/B.scala @@ -0,0 +1 @@ +class B { val y = new A(2) } diff --git a/sbt-test/source-dependencies/constructors-curried/changes/A2.scala b/sbt-test/source-dependencies/constructors-curried/changes/A2.scala new file mode 100644 index 000000000000..d5dcc57395eb --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/changes/A2.scala @@ -0,0 +1 @@ +class A(a: Int)(b: String) diff --git a/sbt-test/source-dependencies/constructors-curried/changes/B2.scala b/sbt-test/source-dependencies/constructors-curried/changes/B2.scala new file mode 100644 index 000000000000..83ef0b737c5a --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/changes/B2.scala @@ -0,0 +1 @@ +class B { val y = new A(2)("a") } diff --git a/sbt-test/source-dependencies/constructors-curried/project/DottyInjectedPlugin.scala b/sbt-test/source-dependencies/constructors-curried/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..69f15d168bfc --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +import sbt._ +import Keys._ + +object DottyInjectedPlugin extends AutoPlugin { + override def requires = plugins.JvmPlugin + override def trigger = allRequirements + + override val projectSettings = Seq( + scalaVersion := sys.props("plugin.scalaVersion"), + scalacOptions += "-source:3.0-migration" + ) +} diff --git a/sbt-test/source-dependencies/constructors-curried/test b/sbt-test/source-dependencies/constructors-curried/test new file mode 100644 index 000000000000..b2c9830cf971 --- /dev/null +++ b/sbt-test/source-dependencies/constructors-curried/test @@ -0,0 +1,10 @@ +> compile +$ copy-file changes/A2.scala A.scala +# we should detect that A has changed, +# this should trigger recompilation of B, +# which should fail due to missing curried argument +-> compile +$ copy-file changes/B2.scala B.scala +# B is updated so that it passes an extra +# argument to A's constructor, it should compile +> compile diff --git a/sbt-test/source-dependencies/constructors/A.scala b/sbt-test/source-dependencies/constructors/A.scala new file mode 100644 index 000000000000..b81025bada4d --- /dev/null +++ b/sbt-test/source-dependencies/constructors/A.scala @@ -0,0 +1 @@ +class A(a: Int) diff --git a/sbt-test/source-dependencies/constructors/B.scala b/sbt-test/source-dependencies/constructors/B.scala new file mode 100644 index 000000000000..e44b1d4c7852 --- /dev/null +++ b/sbt-test/source-dependencies/constructors/B.scala @@ -0,0 +1 @@ +class B { val y = new A(2) } diff --git a/sbt-test/source-dependencies/constructors/changes/A2.scala b/sbt-test/source-dependencies/constructors/changes/A2.scala new file mode 100644 index 000000000000..edd9e160e7bf --- /dev/null +++ b/sbt-test/source-dependencies/constructors/changes/A2.scala @@ -0,0 +1 @@ +class A(a: String) diff --git a/sbt-test/source-dependencies/constructors/changes/B2.scala b/sbt-test/source-dependencies/constructors/changes/B2.scala new file mode 100644 index 000000000000..701f0514685f --- /dev/null +++ b/sbt-test/source-dependencies/constructors/changes/B2.scala @@ -0,0 +1 @@ +class B { val y = new A("a") } diff --git a/sbt-test/source-dependencies/constructors/project/DottyInjectedPlugin.scala b/sbt-test/source-dependencies/constructors/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..69f15d168bfc --- /dev/null +++ b/sbt-test/source-dependencies/constructors/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +import sbt._ +import Keys._ + +object DottyInjectedPlugin extends AutoPlugin { + override def requires = plugins.JvmPlugin + override def trigger = allRequirements + + override val projectSettings = Seq( + scalaVersion := sys.props("plugin.scalaVersion"), + scalacOptions += "-source:3.0-migration" + ) +} diff --git a/sbt-test/source-dependencies/constructors/test b/sbt-test/source-dependencies/constructors/test new file mode 100644 index 000000000000..fbf8ac8d2f0e --- /dev/null +++ b/sbt-test/source-dependencies/constructors/test @@ -0,0 +1,10 @@ +> compile +$ copy-file changes/A2.scala A.scala +# we should detect that A has changed, +# this should trigger recompilation of B, +# which should fail due to mismatched arguments +-> compile +$ copy-file changes/B2.scala B.scala +# B is updated so that it passes a correct +# argument to A's constructor, it should compile +> compile