diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 6fb2e758087d..1e0644efd00f 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -138,7 +138,7 @@ class ScalaSettings extends Settings.SettingGroup { //.withPostSetHook( _ => YprofileEnabled.value = true ) // Extremely experimental language features - val YkindPolymorphism: Setting[Boolean] = BooleanSetting("-Ykind-polymorphism", "Enable kind polymorphism (see http://dotty.epfl.ch/docs/reference/kind-polymorphism.html). Potentially unsound.") + val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting("-Yno-kind-polymorphism", "Enable kind polymorphism (see http://dotty.epfl.ch/docs/reference/kind-polymorphism.html). Potentially unsound.") /** Area-specific debug output */ val YexplainLowlevel: Setting[Boolean] = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 29208283c5d7..731154d2a8ea 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -320,7 +320,7 @@ class Definitions { lazy val AnyKindClass: ClassSymbol = { val cls = ctx.newCompleteClassSymbol(ScalaPackageClass, tpnme.AnyKind, AbstractFinal | Permanent, Nil) - if (ctx.settings.YkindPolymorphism.value) { + if (!ctx.settings.YnoKindPolymorphism.value) { // Enable kind-polymorphism by exposing scala.AnyKind cls.entered } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 082292945856..773fe5d847f5 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -351,10 +351,6 @@ class ReifyQuotes extends MacroTransform { // typer to allow pickling/unpickling phase consistent types transformSplice(spliceTree) - case tree: TypeTree if tree.tpe.typeSymbol.isSplice => - val splicedType = tree.tpe.stripTypeVar.asInstanceOf[TypeRef].prefix.termSymbol - transformSplice(ref(splicedType).select(tpnme.splice).withSpan(tree.span)) - case tree: RefTree if isCaptured(tree.symbol, level) => val t = capturers(tree.symbol).apply(tree) transformSplice(t.select(if (tree.isTerm) nme.splice else tpnme.splice)) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 523c3cef3a24..6bdb708e58f6 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -91,7 +91,6 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("tests/pos-scala2", scala2Mode) + compileFilesInDir("tests/pos", defaultOptions) + compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes) + - compileFilesInDir("tests/pos-kind-polymorphism", defaultOptions and "-Ykind-polymorphism") + compileFile( // succeeds despite -Xfatal-warnings because of -nowarn "tests/neg-custom-args/fatal-warnings/xfatalWarnings.scala", @@ -145,7 +144,7 @@ class CompilationTests extends ParallelTesting { implicit val testGroup: TestGroup = TestGroup("compileNeg") compileFilesInDir("tests/neg", defaultOptions) + compileFilesInDir("tests/neg-tailcall", defaultOptions) + - compileFilesInDir("tests/neg-kind-polymorphism", defaultOptions and "-Ykind-polymorphism") + + compileFilesInDir("tests/neg-no-kind-polymorphism", defaultOptions and "-Yno-kind-polymorphism") + compileFilesInDir("tests/neg-custom-args/deprecation", defaultOptions.and("-Xfatal-warnings", "-deprecation")) + compileFilesInDir("tests/neg-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")) + compileFilesInDir("tests/neg-custom-args/allow-double-bindings", allowDoubleBindings) + diff --git a/docs/docs/reference/other-new-features/kind-polymorphism.md b/docs/docs/reference/other-new-features/kind-polymorphism.md index 31cae284a119..1703f4f429d5 100644 --- a/docs/docs/reference/other-new-features/kind-polymorphism.md +++ b/docs/docs/reference/other-new-features/kind-polymorphism.md @@ -42,5 +42,5 @@ It is declared `abstract` and `final`, so it can be neither instantiated nor ext `AnyKind` plays a special role in Scala's subtype system: It is a supertype of all other types no matter what their kind is. It is also assumed to be kind-compatible with all other types. Furthermore, `AnyKind` is treated as a higher-kinded type (so it cannot be used as a type of values), but at the same time it has no type parameters (so it cannot be instantiated). -**Note**: This feature is considered experimental and is only enabled under a compiler flag -(i.e. `-Ykind-polymorphism`). +**Note**: This feature is considered experimental but stable and it can be disabled under compiler flag +(i.e. `-Yno-kind-polymorphism`). diff --git a/library/src-bootstrapped/scala/quoted/Type.scala b/library/src-bootstrapped/scala/quoted/Type.scala new file mode 100644 index 000000000000..e65f7155f6e7 --- /dev/null +++ b/library/src-bootstrapped/scala/quoted/Type.scala @@ -0,0 +1,46 @@ +package scala.quoted + +import scala.quoted.Types.TaggedType +import scala.reflect.ClassTag +import scala.runtime.quoted.Unpickler.Pickled + +sealed abstract class Type[T <: AnyKind] { + type `$splice` = T +} + +/** Some basic type tags, currently incomplete */ +object Type { + /** A term quote is desugared by the compiler into a call to this method */ + def apply[T <: AnyKind]: Type[T] = + throw new Error("Internal error: this method call should have been replaced by the compiler") + + implicit def UnitTag: Type[Unit] = new TaggedType[Unit] + implicit def BooleanTag: Type[Boolean] = new TaggedType[Boolean] + implicit def ByteTag: Type[Byte] = new TaggedType[Byte] + implicit def CharTag: Type[Char] = new TaggedType[Char] + implicit def ShortTag: Type[Short] = new TaggedType[Short] + implicit def IntTag: Type[Int] = new TaggedType[Int] + implicit def LongTag: Type[Long] = new TaggedType[Long] + implicit def FloatTag: Type[Float] = new TaggedType[Float] + implicit def DoubleTag: Type[Double] = new TaggedType[Double] +} + +/** All implementations of Type[T]. + * These should never be used directly. + */ +object Types { + /** A Type backed by a pickled TASTY tree */ + final class TastyType[T](val tasty: Pickled, val args: Seq[Any]) extends Type[T] { + override def toString(): String = s"Type()" + } + + /** An Type backed by a value */ + final class TaggedType[T](implicit val ct: ClassTag[T]) extends Type[T] { + override def toString: String = s"Type($ct)" + } + + /** An Type backed by a tree */ + final class TreeType[Tree](val typeTree: Tree) extends quoted.Type[Any] { + override def toString: String = s"Type()" + } +} diff --git a/library/src-bootstrapped/scala/tasty/reflect/QuotedOps.scala b/library/src-bootstrapped/scala/tasty/reflect/QuotedOps.scala new file mode 100644 index 000000000000..e60b3a42eb4f --- /dev/null +++ b/library/src-bootstrapped/scala/tasty/reflect/QuotedOps.scala @@ -0,0 +1,29 @@ +package scala.tasty.reflect + +/** Extension methods on scala.quoted.{Expr|Type} to convert to scala.tasty.Tasty objects */ +trait QuotedOps extends Core { + + implicit class QuotedExprAPI[T](expr: scala.quoted.Expr[T]) { + /** View this expression `Expr[T]` as a `Term` */ + def unseal(implicit ctx: Context): Term = + kernel.QuotedExpr_unseal(expr) + } + + implicit class QuotedTypeAPI[T <: AnyKind](tpe: scala.quoted.Type[T]) { + /** View this expression `Type[T]` as a `TypeTree` */ + def unseal(implicit ctx: Context): TypeTree = + kernel.QuotedType_unseal(tpe) + } + + implicit class TermToQuotedAPI(term: Term) { + /** Convert `Term` to an `Expr[T]` and check that it conforms to `T` */ + def seal[T](implicit tpe: scala.quoted.Type[T], ctx: Context): scala.quoted.Expr[T] = + kernel.QuotedExpr_seal(term)(tpe) + } + + implicit class TypeToQuotedAPI(tpe: Type) { + /** Convert `Type` to an `quoted.Type[T]` */ + def seal(implicit ctx: Context): scala.quoted.Type[_] = + kernel.QuotedType_seal(tpe) + } +} diff --git a/library/src/scala/quoted/Type.scala b/library/src-non-bootstrapped/scala/quoted/Type.scala similarity index 100% rename from library/src/scala/quoted/Type.scala rename to library/src-non-bootstrapped/scala/quoted/Type.scala diff --git a/library/src/scala/tasty/reflect/QuotedOps.scala b/library/src-non-bootstrapped/scala/tasty/reflect/QuotedOps.scala similarity index 100% rename from library/src/scala/tasty/reflect/QuotedOps.scala rename to library/src-non-bootstrapped/scala/tasty/reflect/QuotedOps.scala diff --git a/tests/neg-no-kind-polymorphism/anykind.scala b/tests/neg-no-kind-polymorphism/anykind.scala new file mode 100644 index 000000000000..07c98c4f9576 --- /dev/null +++ b/tests/neg-no-kind-polymorphism/anykind.scala @@ -0,0 +1,2 @@ + +trait Foo[T <: AnyKind] // error: Not found: type AnyKind diff --git a/tests/neg-kind-polymorphism/anykind.scala b/tests/neg/anykind.scala similarity index 100% rename from tests/neg-kind-polymorphism/anykind.scala rename to tests/neg/anykind.scala diff --git a/tests/neg-kind-polymorphism/anykind1.scala b/tests/neg/anykind1.scala similarity index 100% rename from tests/neg-kind-polymorphism/anykind1.scala rename to tests/neg/anykind1.scala diff --git a/tests/neg-kind-polymorphism/anykind2.scala b/tests/neg/anykind2.scala similarity index 100% rename from tests/neg-kind-polymorphism/anykind2.scala rename to tests/neg/anykind2.scala diff --git a/tests/neg-kind-polymorphism/anykind3.scala b/tests/neg/anykind3.scala similarity index 100% rename from tests/neg-kind-polymorphism/anykind3.scala rename to tests/neg/anykind3.scala diff --git a/tests/neg-kind-polymorphism/anykind4.scala b/tests/neg/anykind4.scala similarity index 100% rename from tests/neg-kind-polymorphism/anykind4.scala rename to tests/neg/anykind4.scala diff --git a/tests/pos-kind-polymorphism/anykind.scala b/tests/pos/anykind.scala similarity index 100% rename from tests/pos-kind-polymorphism/anykind.scala rename to tests/pos/anykind.scala diff --git a/tests/pos-kind-polymorphism/kindPolySemiGroup.scala b/tests/pos/kindPolySemiGroup.scala similarity index 100% rename from tests/pos-kind-polymorphism/kindPolySemiGroup.scala rename to tests/pos/kindPolySemiGroup.scala diff --git a/tests/run-with-compiler/i5965.check b/tests/run-with-compiler/i5965.check new file mode 100644 index 000000000000..d0077520135f --- /dev/null +++ b/tests/run-with-compiler/i5965.check @@ -0,0 +1,18 @@ +{ + val y: collection.immutable.List[scala.Int] = scala.List.apply[scala.Int](1, 2, 3) + + (y: collection.immutable.List[scala.Int]) +} +List(1, 2, 3) +{ + val y: scala.Option[scala.Int] = scala.Option.apply[scala.Int](4) + + (y: scala.Option[scala.Int]) +} +Some(4) +{ + val y: collection.immutable.Map[scala.Int, scala.Int] = scala.Predef.Map.apply[scala.Int, scala.Int](scala.Predef.ArrowAssoc[scala.Int](4).->[scala.Int](1)) + + (y: collection.immutable.Map[scala.Int, scala.Int]) +} +Map(4 -> 1) diff --git a/tests/run-with-compiler/i5965.scala b/tests/run-with-compiler/i5965.scala new file mode 100644 index 000000000000..7ca1e74aabb4 --- /dev/null +++ b/tests/run-with-compiler/i5965.scala @@ -0,0 +1,28 @@ +import scala.quoted._ + +import scala.tasty._ + +object Test { + + implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make + + def main(args: Array[String]): Unit = { + '[List] + val list = bound('{List(1, 2, 3)}) + println(list.show) + println(list.run) + + val opt = bound('{Option(4)}) + println(opt.show) + println(opt.run) + + val map = bound('{Map(4 -> 1)}) + println(map.show) + println(map.run) + } + + def bound[T: Type, S[_]: Type](x: Expr[S[T]]): Expr[S[T]] = '{ + val y: S[T] = $x + y + } +} diff --git a/tests/run-with-compiler/i5965b.check b/tests/run-with-compiler/i5965b.check new file mode 100644 index 000000000000..d0077520135f --- /dev/null +++ b/tests/run-with-compiler/i5965b.check @@ -0,0 +1,18 @@ +{ + val y: collection.immutable.List[scala.Int] = scala.List.apply[scala.Int](1, 2, 3) + + (y: collection.immutable.List[scala.Int]) +} +List(1, 2, 3) +{ + val y: scala.Option[scala.Int] = scala.Option.apply[scala.Int](4) + + (y: scala.Option[scala.Int]) +} +Some(4) +{ + val y: collection.immutable.Map[scala.Int, scala.Int] = scala.Predef.Map.apply[scala.Int, scala.Int](scala.Predef.ArrowAssoc[scala.Int](4).->[scala.Int](1)) + + (y: collection.immutable.Map[scala.Int, scala.Int]) +} +Map(4 -> 1) diff --git a/tests/run-with-compiler/i5965b.scala b/tests/run-with-compiler/i5965b.scala new file mode 100644 index 000000000000..992fa029c6b7 --- /dev/null +++ b/tests/run-with-compiler/i5965b.scala @@ -0,0 +1,28 @@ +import scala.quoted._ + +import scala.tasty._ + +object Test { + + implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make + + def main(args: Array[String]): Unit = { + '[List] + val list = bound('{List(1, 2, 3)}) + println(list.show) + println(list.run) + + val opt = bound('{Option(4)}) + println(opt.show) + println(opt.run) + + val map = bound('{Map(4 -> 1)}) + println(map.show) + println(map.run) + } + + def bound[T: Type, S[_]: Type](x: Expr[S[T]]): Expr[S[T]] = '{ + val y = $x + y + } +}