diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 66e02ede2b36..433a1b7ca962 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -231,20 +231,20 @@ class Definitions { @tu lazy val Compiletime_constValue : Symbol = CompiletimePackageObject.requiredMethod("constValue") @tu lazy val Compiletime_constValueOpt: Symbol = CompiletimePackageObject.requiredMethod("constValueOpt") @tu lazy val Compiletime_summonFrom : Symbol = CompiletimePackageObject.requiredMethod("summonFrom") - @tu lazy val CompiletimeTestingPackageObject: Symbol = requiredModule("scala.compiletime.testing.package") - @tu lazy val CompiletimeTesting_typeChecks: Symbol = CompiletimeTestingPackageObject.requiredMethod("typeChecks") - @tu lazy val CompiletimeTesting_typeCheckErrors: Symbol = CompiletimeTestingPackageObject.requiredMethod("typeCheckErrors") + @tu lazy val CompiletimeTestingPackage: Symbol = requiredPackage("scala.compiletime.testing") + @tu lazy val CompiletimeTesting_typeChecks: Symbol = CompiletimeTestingPackage.requiredMethod("typeChecks") + @tu lazy val CompiletimeTesting_typeCheckErrors: Symbol = CompiletimeTestingPackage.requiredMethod("typeCheckErrors") @tu lazy val CompiletimeTesting_ErrorClass: ClassSymbol = requiredClass("scala.compiletime.testing.Error") @tu lazy val CompiletimeTesting_Error: Symbol = requiredModule("scala.compiletime.testing.Error") @tu lazy val CompiletimeTesting_Error_apply = CompiletimeTesting_Error.requiredMethod(nme.apply) @tu lazy val CompiletimeTesting_ErrorKind: Symbol = requiredModule("scala.compiletime.testing.ErrorKind") @tu lazy val CompiletimeTesting_ErrorKind_Parser: Symbol = CompiletimeTesting_ErrorKind.requiredMethod("Parser") @tu lazy val CompiletimeTesting_ErrorKind_Typer: Symbol = CompiletimeTesting_ErrorKind.requiredMethod("Typer") - @tu lazy val CompiletimeOpsPackageObject: Symbol = requiredModule("scala.compiletime.ops.package") - @tu lazy val CompiletimeOpsPackageObjectAny: Symbol = requiredModule("scala.compiletime.ops.package.any") - @tu lazy val CompiletimeOpsPackageObjectInt: Symbol = requiredModule("scala.compiletime.ops.package.int") - @tu lazy val CompiletimeOpsPackageObjectString: Symbol = requiredModule("scala.compiletime.ops.package.string") - @tu lazy val CompiletimeOpsPackageObjectBoolean: Symbol = requiredModule("scala.compiletime.ops.package.boolean") + @tu lazy val CompiletimeOpsPackage: Symbol = requiredPackage("scala.compiletime.ops") + @tu lazy val CompiletimeOpsAny: Symbol = requiredModule("scala.compiletime.ops.any") + @tu lazy val CompiletimeOpsInt: Symbol = requiredModule("scala.compiletime.ops.int") + @tu lazy val CompiletimeOpsString: Symbol = requiredModule("scala.compiletime.ops.string") + @tu lazy val CompiletimeOpsBoolean: Symbol = requiredModule("scala.compiletime.ops.boolean") /** Note: We cannot have same named methods defined in Object and Any (and AnyVal, for that matter) * because after erasure the Any and AnyVal references get remapped to the Object methods @@ -1088,10 +1088,10 @@ class Definitions { compiletimePackageOpTypes.contains(sym.name) && ( sym.owner == CompiletimePackageObject.moduleClass && sym.name == tpnme.S - || sym.owner == CompiletimeOpsPackageObjectAny.moduleClass && compiletimePackageAnyTypes.contains(sym.name) - || sym.owner == CompiletimeOpsPackageObjectInt.moduleClass && compiletimePackageIntTypes.contains(sym.name) - || sym.owner == CompiletimeOpsPackageObjectBoolean.moduleClass && compiletimePackageBooleanTypes.contains(sym.name) - || sym.owner == CompiletimeOpsPackageObjectString.moduleClass && compiletimePackageStringTypes.contains(sym.name) + || sym.owner == CompiletimeOpsAny.moduleClass && compiletimePackageAnyTypes.contains(sym.name) + || sym.owner == CompiletimeOpsInt.moduleClass && compiletimePackageIntTypes.contains(sym.name) + || sym.owner == CompiletimeOpsBoolean.moduleClass && compiletimePackageBooleanTypes.contains(sym.name) + || sym.owner == CompiletimeOpsString.moduleClass && compiletimePackageStringTypes.contains(sym.name) ) // ----- Scala-2 library patches -------------------------------------- diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 720f0cc4ac55..d8efa3ca8973 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3985,11 +3985,11 @@ object Types { if (owner == defn.CompiletimePackageObject.moduleClass) name match { case tpnme.S if nArgs == 1 => constantFold1(natValue, _ + 1) case _ => None - } else if (owner == defn.CompiletimeOpsPackageObjectAny.moduleClass) name match { + } else if (owner == defn.CompiletimeOpsAny.moduleClass) name match { case tpnme.Equals if nArgs == 2 => constantFold2(constValue, _ == _) case tpnme.NotEquals if nArgs == 2 => constantFold2(constValue, _ != _) case _ => None - } else if (owner == defn.CompiletimeOpsPackageObjectInt.moduleClass) name match { + } else if (owner == defn.CompiletimeOpsInt.moduleClass) name match { case tpnme.Abs if nArgs == 1 => constantFold1(intValue, _.abs) case tpnme.Negate if nArgs == 1 => constantFold1(intValue, x => -x) case tpnme.ToString if nArgs == 1 => constantFold1(intValue, _.toString) @@ -4017,10 +4017,10 @@ object Types { case tpnme.Min if nArgs == 2 => constantFold2(intValue, _ min _) case tpnme.Max if nArgs == 2 => constantFold2(intValue, _ max _) case _ => None - } else if (owner == defn.CompiletimeOpsPackageObjectString.moduleClass) name match { + } else if (owner == defn.CompiletimeOpsString.moduleClass) name match { case tpnme.Plus if nArgs == 2 => constantFold2(stringValue, _ + _) case _ => None - } else if (owner == defn.CompiletimeOpsPackageObjectBoolean.moduleClass) name match { + } else if (owner == defn.CompiletimeOpsBoolean.moduleClass) name match { case tpnme.Not if nArgs == 1 => constantFold1(boolValue, x => !x) case tpnme.And if nArgs == 2 => constantFold2(boolValue, _ && _) case tpnme.Or if nArgs == 2 => constantFold2(boolValue, _ || _) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 3b544e80a32d..83a4ca37ab9d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -72,7 +72,7 @@ object Inliner { */ def inlineCall(tree: Tree)(using Context): Tree = { if tree.symbol.denot != SymDenotations.NoDenotation - && tree.symbol.owner.companionModule == defn.CompiletimeTestingPackageObject + && tree.symbol.effectiveOwner == defn.CompiletimeTestingPackage.moduleClass then if (tree.symbol == defn.CompiletimeTesting_typeChecks) return Intrinsics.typeChecks(tree) if (tree.symbol == defn.CompiletimeTesting_typeCheckErrors) return Intrinsics.typeCheckErrors(tree) diff --git a/library/src/scala/compiletime/ops/any.scala b/library/src/scala/compiletime/ops/any.scala new file mode 100644 index 000000000000..2119188fcc30 --- /dev/null +++ b/library/src/scala/compiletime/ops/any.scala @@ -0,0 +1,21 @@ +package scala.compiletime +package ops + +object any: + /** Equality comparison of two singleton types. + * ```scala + * val eq1: 1 == 1 = true + * val eq2: 1 == "1" = false + * val eq3: "1" == "1" = true + * ``` + */ + type ==[X, Y] <: Boolean + + /** Inequality comparison of two singleton types. + * ```scala + * val eq1: 1 != 1 = false + * val eq2: 1 != "1" = true + * val eq3: "1" != "1" = false + * ``` + */ + type !=[X, Y] <: Boolean diff --git a/library/src/scala/compiletime/ops/boolean.scala b/library/src/scala/compiletime/ops/boolean.scala new file mode 100644 index 000000000000..dd050c8ad57a --- /dev/null +++ b/library/src/scala/compiletime/ops/boolean.scala @@ -0,0 +1,36 @@ +package scala.compiletime +package ops + +object boolean: + + /** Negation of a `Boolean` singleton type. + * ```scala + * val notFalse: ![false] = true + * val notTrue: ![true] = false + * ``` + */ + type ![X <: Boolean] <: Boolean + + /** Exclusive disjunction of two `Boolean` singleton types. + * ```scala + * val a: true ^ true = false + * val b: false ^ true = true + * ``` + */ + type ^[X <: Boolean, Y <: Boolean] <: Boolean + + /** Conjunction of two `Boolean` singleton types. + * ```scala + * val a: true && true = true + * val b: false && true = false + * ``` + */ + type &&[X <: Boolean, Y <: Boolean] <: Boolean + + /** Disjunction of two `Boolean` singleton types. + * ```scala + * val a: true || false = true + * val b: false || false = false + * ``` + */ + type ||[X <: Boolean, Y <: Boolean] <: Boolean diff --git a/library/src/scala/compiletime/ops/int.scala b/library/src/scala/compiletime/ops/int.scala new file mode 100644 index 000000000000..cfcfd439e7eb --- /dev/null +++ b/library/src/scala/compiletime/ops/int.scala @@ -0,0 +1,149 @@ +package scala.compiletime +package ops + +object int: + /** Addition of two `Int` singleton types. + * ```scala + * val sum: 2 + 2 = 4 + * ``` + */ + type +[X <: Int, Y <: Int] <: Int + + /** Subtraction of two `Int` singleton types. + * ```scala + * val sub: 4 - 2 = 2 + * ``` + */ + type -[X <: Int, Y <: Int] <: Int + + /** Multiplication of two `Int` singleton types. + * ```scala + * val mul: 4 * 2 = 8 + * ``` + */ + type *[X <: Int, Y <: Int] <: Int + + /** Integer division of two `Int` singleton types. + * ```scala + * val div: 5 / 2 = 2 + * ``` + */ + type /[X <: Int, Y <: Int] <: Int + + /** Remainder of the division of `X` by `Y`. + * ```scala + * val mod: 5 % 2 = 1 + * ``` + */ + type %[X <: Int, Y <: Int] <: Int + + /** Binary left shift of `X` by `Y`. + * ```scala + * val lshift: 1 << 2 = 4 + * ``` + */ + type <<[X <: Int, Y <: Int] <: Int + + /** Binary right shift of `X` by `Y`. + * ```scala + * val rshift: 10 >> 1 = 5 + * ``` + */ + type >>[X <: Int, Y <: Int] <: Int + + /** Binary right shift of `X` by `Y`, filling the left with zeros. + * ```scala + * val rshiftzero: 10 >>> 1 = 5 + * ``` + */ + type >>>[X <: Int, Y <: Int] <: Int + + /** Bitwise xor of `X` and `Y`. + * ```scala + * val xor: 10 ^ 30 = 20 + * ``` + */ + type ^[X <: Int, Y <: Int] <: Int + + /** Less-than comparison of two `Int` singleton types. + * ```scala + * val lt1: 4 < 2 = false + * val lt2: 2 < 4 = true + * ``` + */ + type <[X <: Int, Y <: Int] <: Boolean + + /** Greater-than comparison of two `Int` singleton types. + * ```scala + * val gt1: 4 > 2 = true + * val gt2: 2 > 2 = false + * ``` + */ + type >[X <: Int, Y <: Int] <: Boolean + + /** Greater-or-equal comparison of two `Int` singleton types. + * ```scala + * val ge1: 4 >= 2 = true + * val ge2: 2 >= 3 = false + * ``` + */ + type >=[X <: Int, Y <: Int] <: Boolean + + /** Less-or-equal comparison of two `Int` singleton types. + * ```scala + * val lt1: 4 <= 2 = false + * val lt2: 2 <= 2 = true + * ``` + */ + type <=[X <: Int, Y <: Int] <: Boolean + + /** Bitwise and of `X` and `Y`. + * ```scala + * val and1: BitwiseAnd[4, 4] = 4 + * val and2: BitwiseAnd[10, 5] = 0 + * ``` + */ + type BitwiseAnd[X <: Int, Y <: Int] <: Int + + /** Bitwise or of `X` and `Y`. + * ```scala + * val or: BitwiseOr[10, 11] = 11 + * ``` + */ + type BitwiseOr[X <: Int, Y <: Int] <: Int + + /** Absolute value of an `Int` singleton type. + * ```scala + * val abs: Abs[-1] = 1 + * ``` + */ + type Abs[X <: Int] <: Int + + /** Negation of an `Int` singleton type. + * ```scala + * val neg1: Neg[-1] = 1 + * val neg2: Neg[1] = -1 + * ``` + */ + type Negate[X <: Int] <: Int + + /** Minimum of two `Int` singleton types. + * ```scala + * val min: Min[-1, 1] = -1 + * ``` + */ + type Min[X <: Int, Y <: Int] <: Int + + /** Maximum of two `Int` singleton types. + * ```scala + * val max: Max[-1, 1] = 1 + * ``` + */ + type Max[X <: Int, Y <: Int] <: Int + + /** String conversion of an `Int` singleton type. + * ```scala + * val abs: ToString[1] = "1" + * ``` + */ + type ToString[X <: Int] <: String diff --git a/library/src/scala/compiletime/ops/package.scala b/library/src/scala/compiletime/ops/package.scala deleted file mode 100644 index 13a0123d5292..000000000000 --- a/library/src/scala/compiletime/ops/package.scala +++ /dev/null @@ -1,215 +0,0 @@ -package scala.compiletime - -package object ops { - object any { - /** Equality comparison of two singleton types. - * ```scala - * val eq1: 1 == 1 = true - * val eq2: 1 == "1" = false - * val eq3: "1" == "1" = true - * ``` - */ - type ==[X, Y] <: Boolean - - /** Inequality comparison of two singleton types. - * ```scala - * val eq1: 1 != 1 = false - * val eq2: 1 != "1" = true - * val eq3: "1" != "1" = false - * ``` - */ - type !=[X, Y] <: Boolean - } - - object string { - /** Concatenation of two `String` singleton types. - * ```scala - * val hello: "hello " + "world" = "hello world" - * ``` - */ - type +[X <: String, Y <: String] <: String - } - - object int { - /** Addition of two `Int` singleton types. - * ```scala - * val sum: 2 + 2 = 4 - * ``` - */ - type +[X <: Int, Y <: Int] <: Int - - /** Subtraction of two `Int` singleton types. - * ```scala - * val sub: 4 - 2 = 2 - * ``` - */ - type -[X <: Int, Y <: Int] <: Int - - /** Multiplication of two `Int` singleton types. - * ```scala - * val mul: 4 * 2 = 8 - * ``` - */ - type *[X <: Int, Y <: Int] <: Int - - /** Integer division of two `Int` singleton types. - * ```scala - * val div: 5 / 2 = 2 - * ``` - */ - type /[X <: Int, Y <: Int] <: Int - - /** Remainder of the division of `X` by `Y`. - * ```scala - * val mod: 5 % 2 = 1 - * ``` - */ - type %[X <: Int, Y <: Int] <: Int - - /** Binary left shift of `X` by `Y`. - * ```scala - * val lshift: 1 << 2 = 4 - * ``` - */ - type <<[X <: Int, Y <: Int] <: Int - - /** Binary right shift of `X` by `Y`. - * ```scala - * val rshift: 10 >> 1 = 5 - * ``` - */ - type >>[X <: Int, Y <: Int] <: Int - - /** Binary right shift of `X` by `Y`, filling the left with zeros. - * ```scala - * val rshiftzero: 10 >>> 1 = 5 - * ``` - */ - type >>>[X <: Int, Y <: Int] <: Int - - /** Bitwise xor of `X` and `Y`. - * ```scala - * val xor: 10 ^ 30 = 20 - * ``` - */ - type ^[X <: Int, Y <: Int] <: Int - - /** Less-than comparison of two `Int` singleton types. - * ```scala - * val lt1: 4 < 2 = false - * val lt2: 2 < 4 = true - * ``` - */ - type <[X <: Int, Y <: Int] <: Boolean - - /** Greater-than comparison of two `Int` singleton types. - * ```scala - * val gt1: 4 > 2 = true - * val gt2: 2 > 2 = false - * ``` - */ - type >[X <: Int, Y <: Int] <: Boolean - - /** Greater-or-equal comparison of two `Int` singleton types. - * ```scala - * val ge1: 4 >= 2 = true - * val ge2: 2 >= 3 = false - * ``` - */ - type >=[X <: Int, Y <: Int] <: Boolean - - /** Less-or-equal comparison of two `Int` singleton types. - * ```scala - * val lt1: 4 <= 2 = false - * val lt2: 2 <= 2 = true - * ``` - */ - type <=[X <: Int, Y <: Int] <: Boolean - - /** Bitwise and of `X` and `Y`. - * ```scala - * val and1: BitwiseAnd[4, 4] = 4 - * val and2: BitwiseAnd[10, 5] = 0 - * ``` - */ - type BitwiseAnd[X <: Int, Y <: Int] <: Int - - /** Bitwise or of `X` and `Y`. - * ```scala - * val or: BitwiseOr[10, 11] = 11 - * ``` - */ - type BitwiseOr[X <: Int, Y <: Int] <: Int - - /** Absolute value of an `Int` singleton type. - * ```scala - * val abs: Abs[-1] = 1 - * ``` - */ - type Abs[X <: Int] <: Int - - /** Negation of an `Int` singleton type. - * ```scala - * val neg1: Neg[-1] = 1 - * val neg2: Neg[1] = -1 - * ``` - */ - type Negate[X <: Int] <: Int - - /** Minimum of two `Int` singleton types. - * ```scala - * val min: Min[-1, 1] = -1 - * ``` - */ - type Min[X <: Int, Y <: Int] <: Int - - /** Maximum of two `Int` singleton types. - * ```scala - * val max: Max[-1, 1] = 1 - * ``` - */ - type Max[X <: Int, Y <: Int] <: Int - - /** String conversion of an `Int` singleton type. - * ```scala - * val abs: ToString[1] = "1" - * ``` - */ - type ToString[X <: Int] <: String - } - - object boolean { - - /** Negation of a `Boolean` singleton type. - * ```scala - * val notFalse: ![false] = true - * val notTrue: ![true] = false - * ``` - */ - type ![X <: Boolean] <: Boolean - - /** Exclusive disjunction of two `Boolean` singleton types. - * ```scala - * val a: true ^ true = false - * val b: false ^ true = true - * ``` - */ - type ^[X <: Boolean, Y <: Boolean] <: Boolean - - /** Conjunction of two `Boolean` singleton types. - * ```scala - * val a: true && true = true - * val b: false && true = false - * ``` - */ - type &&[X <: Boolean, Y <: Boolean] <: Boolean - - /** Disjunction of two `Boolean` singleton types. - * ```scala - * val a: true || false = true - * val b: false || false = false - * ``` - */ - type ||[X <: Boolean, Y <: Boolean] <: Boolean - } -} diff --git a/library/src/scala/compiletime/ops/string.scala b/library/src/scala/compiletime/ops/string.scala new file mode 100644 index 000000000000..77aa8a1329f4 --- /dev/null +++ b/library/src/scala/compiletime/ops/string.scala @@ -0,0 +1,10 @@ +package scala.compiletime +package ops + +object string: + /** Concatenation of two `String` singleton types. + * ```scala + * val hello: "hello " + "world" = "hello world" + * ``` + */ + type +[X <: String, Y <: String] <: String diff --git a/library/src/scala/compiletime/testing/ErrorKind.scala b/library/src/scala/compiletime/testing/ErrorKind.scala index ef4a8e7aaa61..c7e38ae22d83 100644 --- a/library/src/scala/compiletime/testing/ErrorKind.scala +++ b/library/src/scala/compiletime/testing/ErrorKind.scala @@ -1,7 +1,8 @@ package scala.compiletime.testing /** An error can be either a parse-time or a typecheck-time */ -sealed trait ErrorKind // TODO make this enum, so far not doable because ScalaJS compilation fails on it +sealed trait ErrorKind // This should be an enum but currently, Dotty lib fails to + // compile with an obscure error. object ErrorKind: case object Parser extends ErrorKind case object Typer extends ErrorKind diff --git a/library/src/scala/compiletime/testing/package.scala b/library/src/scala/compiletime/testing/package.scala index d0d5558e738f..780debc87b20 100644 --- a/library/src/scala/compiletime/testing/package.scala +++ b/library/src/scala/compiletime/testing/package.scala @@ -1,33 +1,31 @@ package scala.compiletime +package testing -package object testing { +/** Whether the code type checks in the current context? + * + * @param code The code to be type checked + * + * @return false if the code has syntax error or type error in the current context, otherwise returns true. + * + * The code should be a sequence of expressions or statements that may appear in a block. + */ +inline def typeChecks(inline code: String): Boolean = + // implemented in package dotty.tools.dotc.typer.Inliner.Intrinsics + error("Compiler bug: `typeChecks` was not checked by the compiler") - /** Whether the code type checks in the current context? - * - * @param code The code to be type checked - * - * @return false if the code has syntax error or type error in the current context, otherwise returns true. - * - * The code should be a sequence of expressions or statements that may appear in a block. - */ - inline def typeChecks(inline code: String): Boolean = - // implemented in package dotty.tools.dotc.typer.Inliner.Intrinsics - error("Compiler bug: `typeChecks` was not checked by the compiler") - - /** Whether the code type checks in the current context? If not, - * returns a list of errors encountered on compilation. - * IMPORTANT: No stability guarantees are provided on the format of these - * errors. This means the format and the API may change from - * version to version. This API is to be used for testing purposes - * only. - * - * @param code The code to be type checked - * - * @return a list of errors encountered during parsing and typechecking. - * - * The code should be a sequence of expressions or statements that may appear in a block. - */ - inline def typeCheckErrors(inline code: String): List[Error] = - // implemented in package dotty.tools.dotc.typer.Inliner.Intrinsics - error("Compiler bug: `typeCheckErrors` was not checked by the compiler") -} +/** Whether the code type checks in the current context? If not, + * returns a list of errors encountered on compilation. + * IMPORTANT: No stability guarantees are provided on the format of these + * errors. This means the format and the API may change from + * version to version. This API is to be used for testing purposes + * only. + * + * @param code The code to be type checked + * + * @return a list of errors encountered during parsing and typechecking. + * + * The code should be a sequence of expressions or statements that may appear in a block. + */ +inline def typeCheckErrors(inline code: String): List[Error] = + // implemented in package dotty.tools.dotc.typer.Inliner.Intrinsics + error("Compiler bug: `typeCheckErrors` was not checked by the compiler") diff --git a/vscode-dotty/out/.keep b/vscode-dotty/out/.keep deleted file mode 100644 index e69de29bb2d1..000000000000