diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 0533de0f36f6..cdbda516e026 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -147,6 +147,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder new api.Annotated(tp, Array(marker)) private def marker(name: String) = new api.Annotation(new api.Constant(Constants.emptyType, name), Array()) + val typeArgRefMarker = marker("TypeArgRef") val orMarker = marker("Or") val byNameMarker = marker("ByName") @@ -343,6 +344,12 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder } } + // Hack to represent dotty types which don't have an equivalent in xsbti + def combineApiTypes(apiTps: api.Type*): api.Type = { + new api.Structure(strict2lzy(apiTps.toArray), + strict2lzy(Array()), strict2lzy(Array())) + } + def apiType(tp: Type): api.Type = { typeCache.getOrElseUpdate(tp, computeType(tp)) } @@ -450,7 +457,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // TODO: Add a real representation for AndOrTypes in xsbti. The order of // types in an `AndOrType` does not change the API, so the API hash should // be symmetric. - val s = new api.Structure(strict2lzy(parents.toArray), strict2lzy(Array()), strict2lzy(Array())) + val s = combineApiTypes(apiType(tp.tp1), apiType(tp.tp2)) if (tp.isAnd) s else @@ -471,6 +478,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder apiType(tp.ref) case tp: TypeVar => apiType(tp.underlying) + case TypeArgRef(prefix, clsRef, idx) => + val apiClsWithIdx = withMarker(apiType(clsRef), marker(idx.toString)) + withMarker(combineApiTypes(apiType(prefix), apiClsWithIdx), typeArgRefMarker) case _ => { ctx.warning(i"sbt-api: Unhandled type ${tp.getClass} : $tp") Constants.emptyType diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/A.scala b/sbt-dotty/sbt-test/source-dependencies/typeargref/A.scala new file mode 100644 index 000000000000..ec3bd54f5c1d --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/A.scala @@ -0,0 +1,10 @@ +import scala.collection.JavaConverters._ +import java.util.{ Map => JMap } + +class A { + // Inferred type for `param`: java.util.Map[Int, _ <: String]# + def param = { + val opt: Option[JMap[Int, _ <: String]] = None + opt.getOrElse(Map.empty.asJava).get(42) + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/B.scala b/sbt-dotty/sbt-test/source-dependencies/typeargref/B.scala new file mode 100644 index 000000000000..7571bd2988e3 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/B.scala @@ -0,0 +1,3 @@ +object B { + def foo(a: A): Int = a.param.length +} diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/changes/A1.scala b/sbt-dotty/sbt-test/source-dependencies/typeargref/changes/A1.scala new file mode 100644 index 000000000000..9f85b963f2e7 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/changes/A1.scala @@ -0,0 +1,10 @@ +import scala.collection.JavaConverters._ +import java.util.{ Map => JMap } + +class A { + // Inferred type for `param`: java.util.Map[Int, _ <: Int]# + def param = { + val opt: Option[JMap[Int, _ <: Int]] = None + opt.getOrElse(Map.empty.asJava).get(42) + } +} diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/project/DottyInjectedPlugin.scala b/sbt-dotty/sbt-test/source-dependencies/typeargref/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..ce3d46d79921 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/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 += "-language:Scala2" + ) +} diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/project/plugins.sbt b/sbt-dotty/sbt-test/source-dependencies/typeargref/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/source-dependencies/typeargref/test b/sbt-dotty/sbt-test/source-dependencies/typeargref/test new file mode 100644 index 000000000000..7e830ff34e73 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/typeargref/test @@ -0,0 +1,4 @@ +> compile +$ copy-file changes/A1.scala A.scala +# Compilation of B.scala should fail because the signature of A#param has changed +-> compile