Skip to content

Commit a582d01

Browse files
authored
Merge pull request #11671 from dotty-staging/sjs-union
Treat Scala.js pseudo-unions as real unions
2 parents 8b88918 + 62965b9 commit a582d01

File tree

23 files changed

+421
-58
lines changed

23 files changed

+421
-58
lines changed

compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ final class JSDefinitions()(using Context) {
5959
@threadUnsafe lazy val PseudoUnion_fromTypeConstructorR = PseudoUnionModule.requiredMethodRef("fromTypeConstructor")
6060
def PseudoUnion_fromTypeConstructor(using Context) = PseudoUnion_fromTypeConstructorR.symbol
6161

62+
@threadUnsafe lazy val UnionOpsModuleRef = requiredModuleRef("scala.scalajs.js.internal.UnitOps")
63+
6264
@threadUnsafe lazy val JSArrayType: TypeRef = requiredClassRef("scala.scalajs.js.Array")
6365
def JSArrayClass(using Context) = JSArrayType.symbol.asClass
6466
@threadUnsafe lazy val JSDynamicType: TypeRef = requiredClassRef("scala.scalajs.js.Dynamic")

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Phases._
66
import Flags.JavaDefined
77
import Uniques.unique
88
import TypeOps.makePackageObjPrefixExplicit
9+
import backend.sjs.JSDefinitions
910
import transform.ExplicitOuter._
1011
import transform.ValueClasses._
1112
import transform.TypeUtils._
@@ -142,29 +143,31 @@ object TypeErasure {
142143
}
143144
}
144145

145-
private def erasureIdx(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean) =
146+
private def erasureIdx(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, isSymbol: Boolean, wildcardOK: Boolean) =
146147
extension (b: Boolean) def toInt = if b then 1 else 0
147148
wildcardOK.toInt
148-
+ (isConstructor.toInt << 1)
149-
+ (semiEraseVCs.toInt << 2)
150-
+ (sourceLanguage.ordinal << 3)
149+
+ (isSymbol.toInt << 1)
150+
+ (isConstructor.toInt << 2)
151+
+ (semiEraseVCs.toInt << 3)
152+
+ (sourceLanguage.ordinal << 4)
151153

152-
private val erasures = new Array[TypeErasure](1 << (SourceLanguage.bits + 3))
154+
private val erasures = new Array[TypeErasure](1 << (SourceLanguage.bits + 4))
153155

154156
for
155157
sourceLanguage <- SourceLanguage.values
156158
semiEraseVCs <- List(false, true)
157159
isConstructor <- List(false, true)
160+
isSymbol <- List(false, true)
158161
wildcardOK <- List(false, true)
159162
do
160-
erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)) =
161-
new TypeErasure(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)
163+
erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)) =
164+
new TypeErasure(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)
162165

163166
/** Produces an erasure function. See the documentation of the class [[TypeErasure]]
164167
* for a description of each parameter.
165168
*/
166-
private def erasureFn(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean): TypeErasure =
167-
erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK))
169+
private def erasureFn(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, isSymbol: Boolean, wildcardOK: Boolean): TypeErasure =
170+
erasures(erasureIdx(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK))
168171

169172
/** The current context with a phase no later than erasure */
170173
def preErasureCtx(using Context) =
@@ -175,19 +178,19 @@ object TypeErasure {
175178
* @param tp The type to erase.
176179
*/
177180
def erasure(tp: Type)(using Context): Type =
178-
erasureFn(sourceLanguage = SourceLanguage.Scala3, semiEraseVCs = false, isConstructor = false, wildcardOK = false)(tp)(using preErasureCtx)
181+
erasureFn(sourceLanguage = SourceLanguage.Scala3, semiEraseVCs = false, isConstructor = false, isSymbol = false, wildcardOK = false)(tp)(using preErasureCtx)
179182

180183
/** The value class erasure of a Scala type, where value classes are semi-erased to
181184
* ErasedValueType (they will be fully erased in [[ElimErasedValueType]]).
182185
*
183186
* @param tp The type to erase.
184187
*/
185188
def valueErasure(tp: Type)(using Context): Type =
186-
erasureFn(sourceLanguage = SourceLanguage.Scala3, semiEraseVCs = true, isConstructor = false, wildcardOK = false)(tp)(using preErasureCtx)
189+
erasureFn(sourceLanguage = SourceLanguage.Scala3, semiEraseVCs = true, isConstructor = false, isSymbol = false, wildcardOK = false)(tp)(using preErasureCtx)
187190

188191
/** The erasure that Scala 2 would use for this type. */
189192
def scala2Erasure(tp: Type)(using Context): Type =
190-
erasureFn(sourceLanguage = SourceLanguage.Scala2, semiEraseVCs = true, isConstructor = false, wildcardOK = false)(tp)(using preErasureCtx)
193+
erasureFn(sourceLanguage = SourceLanguage.Scala2, semiEraseVCs = true, isConstructor = false, isSymbol = false, wildcardOK = false)(tp)(using preErasureCtx)
191194

192195
/** Like value class erasure, but value classes erase to their underlying type erasure */
193196
def fullErasure(tp: Type)(using Context): Type =
@@ -197,7 +200,7 @@ object TypeErasure {
197200

198201
def sigName(tp: Type, sourceLanguage: SourceLanguage)(using Context): TypeName = {
199202
val normTp = tp.translateFromRepeated(toArray = sourceLanguage.isJava)
200-
val erase = erasureFn(sourceLanguage, semiEraseVCs = !sourceLanguage.isJava, isConstructor = false, wildcardOK = true)
203+
val erase = erasureFn(sourceLanguage, semiEraseVCs = !sourceLanguage.isJava, isConstructor = false, isSymbol = false, wildcardOK = true)
201204
erase.sigName(normTp)(using preErasureCtx)
202205
}
203206

@@ -227,7 +230,7 @@ object TypeErasure {
227230
def transformInfo(sym: Symbol, tp: Type)(using Context): Type = {
228231
val sourceLanguage = SourceLanguage(sym)
229232
val semiEraseVCs = !sourceLanguage.isJava // Java sees our value classes as regular classes.
230-
val erase = erasureFn(sourceLanguage, semiEraseVCs, sym.isConstructor, wildcardOK = false)
233+
val erase = erasureFn(sourceLanguage, semiEraseVCs, sym.isConstructor, isSymbol = true, wildcardOK = false)
231234

232235
def eraseParamBounds(tp: PolyType): Type =
233236
tp.derivedLambdaType(
@@ -446,10 +449,11 @@ import TypeErasure._
446449
* (they will be fully erased in [[ElimErasedValueType]]).
447450
* If false, they are erased like normal classes.
448451
* @param isConstructor Argument forms part of the type of a constructor
452+
* @param isSymbol If true, the type being erased is the info of a symbol.
449453
* @param wildcardOK Wildcards are acceptable (true when using the erasure
450454
* for computing a signature name).
451455
*/
452-
class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean) {
456+
class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, isSymbol: Boolean, wildcardOK: Boolean) {
453457

454458
/** The erasure |T| of a type T. This is:
455459
*
@@ -520,10 +524,22 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
520524
else
521525
erasedGlb(this(tp1), this(tp2), isJava = sourceLanguage.isJava)
522526
case OrType(tp1, tp2) =>
523-
TypeComparer.orType(this(tp1), this(tp2), isErased = true)
527+
if isSymbol && sourceLanguage.isScala2 && ctx.settings.scalajs.value then
528+
// In Scala2Unpickler we unpickle Scala.js pseudo-unions as if they were
529+
// real unions, but we must still erase them as Scala 2 would to emit
530+
// the correct signatures in SJSIR.
531+
// We only do this when `isSymbol` is true since in other situations we
532+
// cannot distinguish a Scala.js pseudo-union from a Scala 3 union that
533+
// has been substituted into a Scala 2 type (e.g., via `asSeenFrom`),
534+
// erasing these unions as if they were pseudo-unions could have an
535+
// impact on overriding relationships so it's best to leave them
536+
// alone (and this doesn't impact the SJSIR we generate).
537+
JSDefinitions.jsdefn.PseudoUnionType
538+
else
539+
TypeComparer.orType(this(tp1), this(tp2), isErased = true)
524540
case tp: MethodType =>
525541
def paramErasure(tpToErase: Type) =
526-
erasureFn(sourceLanguage, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
542+
erasureFn(sourceLanguage, semiEraseVCs, isConstructor, isSymbol, wildcardOK)(tpToErase)
527543
val (names, formals0) = if (tp.isErasedMethod) (Nil, Nil) else (tp.paramNames, tp.paramInfos)
528544
val formals = formals0.mapConserve(paramErasure)
529545
eraseResult(tp.resultType) match {
@@ -567,7 +583,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
567583
val defn.ArrayOf(elemtp) = tp
568584
if (classify(elemtp).derivesFrom(defn.NullClass)) JavaArrayType(defn.ObjectType)
569585
else if (isUnboundedGeneric(elemtp) && !sourceLanguage.isJava) defn.ObjectType
570-
else JavaArrayType(erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, wildcardOK)(elemtp))
586+
else JavaArrayType(erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, isSymbol, wildcardOK)(elemtp))
571587
}
572588

573589
private def erasePair(tp: Type)(using Context): Type = {
@@ -608,7 +624,9 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
608624
val genericUnderlying = unbox.info.resultType
609625
val underlying = tp.select(unbox).widen.resultType
610626

611-
val erasedUnderlying = erasure(underlying)
627+
// The underlying part of an ErasedValueType cannot be an ErasedValueType itself
628+
val erase = erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, isSymbol, wildcardOK)
629+
val erasedUnderlying = erase(underlying)
612630

613631
// Ideally, we would just use `erasedUnderlying` as the erasure of `tp`, but to
614632
// be binary-compatible with Scala 2 we need two special cases for polymorphic
@@ -646,7 +664,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
646664
// correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the result type of a
647665
// constructor method should not be semi-erased.
648666
if semiEraseVCs && isConstructor && !tp.isInstanceOf[MethodOrPoly] then
649-
erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, wildcardOK).eraseResult(tp)
667+
erasureFn(sourceLanguage, semiEraseVCs = false, isConstructor, isSymbol, wildcardOK).eraseResult(tp)
650668
else tp match
651669
case tp: TypeRef =>
652670
val sym = tp.symbol

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import NameKinds.{Scala2MethodNameKinds, SuperAccessorName, ExpandedName}
1313
import util.Spans._
1414
import dotty.tools.dotc.ast.{tpd, untpd}, ast.tpd._
1515
import ast.untpd.Modifiers
16+
import backend.sjs.JSDefinitions
1617
import printing.Texts._
1718
import printing.Printer
1819
import io.AbstractFile
@@ -675,6 +676,10 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
675676

676677
def removeSingleton(tp: Type): Type =
677678
if (tp isRef defn.SingletonClass) defn.AnyType else tp
679+
def mapArg(arg: Type) = arg match {
680+
case arg: TypeRef if isBound(arg) => arg.symbol.info
681+
case _ => arg
682+
}
678683
def elim(tp: Type): Type = tp match {
679684
case tp @ RefinedType(parent, name, rinfo) =>
680685
val parent1 = elim(tp.parent)
@@ -690,12 +695,11 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
690695
}
691696
case tp @ AppliedType(tycon, args) =>
692697
val tycon1 = tycon.safeDealias
693-
def mapArg(arg: Type) = arg match {
694-
case arg: TypeRef if isBound(arg) => arg.symbol.info
695-
case _ => arg
696-
}
697698
if (tycon1 ne tycon) elim(tycon1.appliedTo(args))
698699
else tp.derivedAppliedType(tycon, args.map(mapArg))
700+
case tp: AndOrType =>
701+
// scalajs.js.|.UnionOps has a type parameter upper-bounded by `_ | _`
702+
tp.derivedAndOrType(mapArg(tp.tp1).bounds.hi, mapArg(tp.tp2).bounds.hi)
699703
case _ =>
700704
tp
701705
}
@@ -777,6 +781,12 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
777781
val tycon = select(pre, sym)
778782
val args = until(end, () => readTypeRef())
779783
if (sym == defn.ByNameParamClass2x) ExprType(args.head)
784+
else if (ctx.settings.scalajs.value && args.length == 2 &&
785+
sym.owner == JSDefinitions.jsdefn.ScalaJSJSPackageClass && sym == JSDefinitions.jsdefn.PseudoUnionClass) {
786+
// Treat Scala.js pseudo-unions as real unions, this requires a
787+
// special-case in erasure, see TypeErasure#eraseInfo.
788+
OrType(args(0), args(1), soft = false)
789+
}
780790
else if (args.nonEmpty) tycon.safeAppliedTo(EtaExpandIfHK(sym.typeParams, args.map(translateTempPoly)))
781791
else if (sym.typeParams.nonEmpty) tycon.EtaExpand(sym.typeParams)
782792
else tycon

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2126,7 +2126,7 @@ import transform.SymUtils._
21262126
val addendum =
21272127
if (scrutTp != testTp) s" is a subtype of ${testTp.show}"
21282128
else " is the same as the tested type"
2129-
s"The highlighted type test will always succeed since the scrutinee type ($scrutTp.show)" + addendum
2129+
s"The highlighted type test will always succeed since the scrutinee type ${scrutTp.show}" + addendum
21302130
}
21312131
def explain = ""
21322132
}

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools
22
package dotc
33
package typer
44

5+
import backend.sjs.JSDefinitions
56
import core._
67
import ast.{Trees, TreeTypeMap, untpd, tpd, DesugarEnums}
78
import util.Spans._
@@ -634,6 +635,14 @@ trait ImplicitRunInfo:
634635
else pre.member(sym.name.toTermName)
635636
.suchThat(companion => companion.is(Module) && companion.owner == sym.owner)
636637
.symbol)
638+
639+
// The companion of `js.|` defines an implicit conversions from
640+
// `A | Unit` to `js.UndefOrOps[A]`. To keep this conversion in scope
641+
// in Scala 3, where we re-interpret `js.|` as a real union, we inject
642+
// it in the scope of `Unit`.
643+
if t.isRef(defn.UnitClass) && ctx.settings.scalajs.value then
644+
companions += JSDefinitions.jsdefn.UnionOpsModuleRef
645+
637646
if sym.isClass then
638647
for p <- t.parents do companions ++= iscopeRefs(p)
639648
else

compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package dotty.tools
22
package dotc
33
package typer
44

5+
import backend.sjs.JSDefinitions
56
import core._
67
import Contexts._, Types._, Symbols._, Names._, Decorators._, ProtoTypes._
78
import Flags._, SymDenotations._
89
import NameKinds.FlatName
910
import NameOps._
11+
import StdNames._
1012
import config.Printers.{implicits, implicitsDetailed}
1113
import util.Spans.Span
1214
import ast.{untpd, tpd}
@@ -64,6 +66,8 @@ trait ImportSuggestions:
6466
else !root.name.is(FlatName)
6567
&& !root.name.lastPart.contains('$')
6668
&& root.is(ModuleVal, butNot = JavaDefined)
69+
// The implicits in `scalajs.js.|` are implementation details and shouldn't be suggested
70+
&& !(root.name == nme.raw.BAR && ctx.settings.scalajs.value && root == JSDefinitions.jsdefn.PseudoUnionModule)
6771
}
6872

6973
def nestedRoots(site: Type)(using Context): List[Symbol] =

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools
22
package dotc
33
package typer
44

5+
import backend.sjs.JSDefinitions
56
import core._
67
import ast._
78
import Trees._
@@ -219,7 +220,13 @@ class Typer extends Namer
219220
denot = denot.filterWithPredicate { mbr =>
220221
mbr.matchesImportBound(if mbr.symbol.is(Given) then imp.givenBound else imp.wildcardBound)
221222
}
222-
if reallyExists(denot) then
223+
def isScalaJsPseudoUnion =
224+
denot.name == tpnme.raw.BAR && ctx.settings.scalajs.value && denot.symbol == JSDefinitions.jsdefn.PseudoUnionClass
225+
// Just like Scala2Unpickler reinterprets Scala.js pseudo-unions
226+
// as real union types, we want references to `A | B` in sources
227+
// to be typed as a real union even if `js.|` has been imported,
228+
// so we ignore that import.
229+
if reallyExists(denot) && !isScalaJsPseudoUnion then
223230
if unimported.isEmpty || !unimported.contains(pre.termSymbol) then
224231
return pre.select(name, denot)
225232
case _ =>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package scala.scalajs.js.internal
2+
3+
import scala.scalajs.js
4+
5+
/** Under -scalajs, this object is part of the implicit scope of `scala.Unit` */
6+
object UnitOps:
7+
implicit def unitOrOps[A](x: A | Unit): js.UndefOrOps[A] =
8+
new js.UndefOrOps(x)

project/Build.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ object Build {
698698
settings(
699699
libraryDependencies +=
700700
("org.scala-js" %% "scalajs-library" % scalaJSVersion).withDottyCompat(scalaVersion.value),
701-
Compile / unmanagedSourceDirectories :=
701+
Compile / unmanagedSourceDirectories ++=
702702
(`scala3-library-bootstrapped` / Compile / unmanagedSourceDirectories).value,
703703

704704
// Configure the source maps to point to GitHub for releases
@@ -1105,9 +1105,13 @@ object Build {
11051105
-- "ObjectTest.scala" // compile errors caused by #9588
11061106
-- "StackTraceTest.scala" // would require `npm install source-map-support`
11071107
-- "UnionTypeTest.scala" // requires the Scala 2 macro defined in Typechecking*.scala
1108+
-- "PromiseMock.scala" // TODO: Enable once we use a Scala.js with https://github.com/scala-js/scala-js/pull/4451 in
1109+
// and remove copy in tests/sjs-junit
11081110
)).get
11091111

1110-
++ (dir / "js/src/test/require-2.12" ** "*.scala").get
1112+
++ (dir / "js/src/test/require-2.12" ** (("*.scala": FileFilter)
1113+
-- "JSOptionalTest212.scala" // TODO: Enable once we use a Scala.js with https://github.com/scala-js/scala-js/pull/4451 in
1114+
)).get
11111115
++ (dir / "js/src/test/require-sam" ** "*.scala").get
11121116
++ (dir / "js/src/test/scala-new-collections" ** "*.scala").get
11131117
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
lazy val scala2Lib = project.in(file("scala2Lib"))
2+
.enablePlugins(ScalaJSPlugin)
3+
.settings(
4+
// TODO: switch to 2.13.5 once we've upgrade sbt-scalajs to 1.5.0
5+
scalaVersion := "2.13.4"
6+
)
7+
8+
lazy val dottyApp = project.in(file("dottyApp"))
9+
.dependsOn(scala2Lib)
10+
.enablePlugins(ScalaJSPlugin)
11+
.settings(
12+
scalaVersion := sys.props("plugin.scalaVersion"),
13+
14+
scalaJSUseMainModuleInitializer := true,
15+
scalaJSLinkerConfig ~= (_.withCheckIR(true)),
16+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Main {
2+
def main(args: Array[String]): Unit = {
3+
val a = new scala2Lib.A
4+
assert(a.foo(1) == "1")
5+
assert(a.foo("") == "1")
6+
assert(a.foo(Array(1)) == "2")
7+
8+
val b = new scala2Lib.B
9+
assert(b.foo(1) == "1")
10+
assert(b.foo("") == "1")
11+
assert(b.foo(Array(1)) == "2")
12+
}
13+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
2+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % sys.props("plugin.scalaJSVersion"))
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Keep synchronized with dottyApp/Api.scala
2+
package scala2Lib
3+
4+
import scala.scalajs.js
5+
import js.|
6+
7+
class A {
8+
def foo(x: Int | String): String = "1"
9+
def foo(x: Array[Int]): String = "2"
10+
}
11+
12+
class B extends js.Object {
13+
def foo(x: Int | String): String = "1"
14+
def foo(x: Array[Int]): String = "2"
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
> dottyApp/run
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
lazy val scala2Lib = project.in(file("scala2Lib"))
22
.settings(
3-
scalaVersion := "2.13.2"
3+
scalaVersion := "2.13.5"
44
)
55

66
lazy val dottyApp = project.in(file("dottyApp"))
77
.dependsOn(scala2Lib)
88
.settings(
9-
scalaVersion := sys.props("plugin.scalaVersion"),
10-
// https://github.com/sbt/sbt/issues/5369
11-
projectDependencies := {
12-
projectDependencies.value.map(_.withDottyCompat(scalaVersion.value))
13-
}
9+
scalaVersion := sys.props("plugin.scalaVersion")
1410
)
15-

0 commit comments

Comments
 (0)