diff --git a/community-build/community-projects/scodec b/community-build/community-projects/scodec index 17858b32a28a..620880b81bff 160000 --- a/community-build/community-projects/scodec +++ b/community-build/community-projects/scodec @@ -1 +1 @@ -Subproject commit 17858b32a28a7a0a226e30e2ce688d84ec9fed00 +Subproject commit 620880b81bff1cb365f28ff4cbf93e799265bf4d diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index e644804d83c5..169503cd464c 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -12,6 +12,10 @@ import reporting.Message object Feature: + private val dependent = "dependent".toTermName + private val namedTypeArguments = "namedTypeArguments".toTermName + private val genericNumberLiterals = "genericNumberLiterals".toTermName + /** Is `feature` enabled by by a command-line setting? The enabling setting is * * -language:feature @@ -58,10 +62,13 @@ object Feature: enabled(nme.dynamics) def dependentEnabled(using Context) = - enabled(nme.dependent, defn.LanguageExperimentalModule.moduleClass) + enabled(dependent, defn.LanguageExperimentalModule.moduleClass) def namedTypeArgsEnabled(using Context) = - enabled(nme.namedTypeArguments, defn.LanguageExperimentalModule.moduleClass) + enabled(namedTypeArguments, defn.LanguageExperimentalModule.moduleClass) + + def genericNumberLiteralsEnabled(using Context) = + enabled(genericNumberLiterals, defn.LanguageExperimentalModule.moduleClass) def scala2ExperimentalMacroEnabled(using Context) = enabled("macros".toTermName, defn.LanguageExperimentalModule.moduleClass) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index c8c79788b80f..0bb2b9bc898b 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -446,7 +446,6 @@ object StdNames { val definitions: N = "definitions" val delayedInit: N = "delayedInit" val delayedInitArg: N = "delayedInit$body" - val dependent: N = "dependent" val derived: N = "derived" val derives: N = "derives" val doubleHash: N = "doubleHash" @@ -528,7 +527,6 @@ object StdNames { val moduleClass : N = "moduleClass" val name: N = "name" val nameDollar: N = "$name" - val namedTypeArguments: N = "namedTypeArguments" val ne: N = "ne" val newFreeTerm: N = "newFreeTerm" val newFreeType: N = "newFreeType" diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 3f8759028542..d0731667fb34 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -624,7 +624,9 @@ class Typer extends Namer case Whole(16) => // cant parse hex literal as double case _ => return lit(doubleFromDigits(digits)) } - else if (target.isValueType && isFullyDefined(target, ForceDegree.none)) { + else if genericNumberLiteralsEnabled + && target.isValueType && isFullyDefined(target, ForceDegree.none) + then // If expected type is defined with a FromDigits instance, use that one val fromDigitsCls = tree.kind match { case Whole(10) => defn.FromDigitsClass @@ -645,7 +647,6 @@ class Typer extends Namer return typed(app, pt) case _ => } - } // Otherwise convert to Int or Double according to digits format tree.kind match { case Whole(radix) => lit(intFromDigits(digits, radix)) diff --git a/docs/docs/reference/changed-features/numeric-literals.md b/docs/docs/reference/changed-features/numeric-literals.md index 9678a9616d87..4e4f815ff264 100644 --- a/docs/docs/reference/changed-features/numeric-literals.md +++ b/docs/docs/reference/changed-features/numeric-literals.md @@ -3,6 +3,11 @@ layout: doc-page title: Numeric Literals --- +**Note**: This feature is not yet part of the Scala 3 language definition. It can be made available by a language import: +```scala +import scala.language.experimental.genericNumberLiterals +``` + In Scala 2, numeric literals were confined to the primitive numeric types `Int`, `Long`, `Float`, and `Double`. Scala 3 allows to write numeric literals also for user defined types. Example: ```scala val x: Long = -10_000_000_000 diff --git a/library/src/scalaShadowing/language.scala b/library/src/scalaShadowing/language.scala index fe16ce0e10ef..80ce28ae4ca3 100644 --- a/library/src/scalaShadowing/language.scala +++ b/library/src/scalaShadowing/language.scala @@ -216,6 +216,9 @@ object language { /** Experimental support for named type arguments */ object namedTypeArguments + + /** Experimental support for generic number literals */ + object genericNumberLiterals } /** Where imported, a backwards compatibility mode for Scala2 is enabled */ diff --git a/tests/neg-macros/BigFloat/BigFloatFromDigitsImpl_1.scala b/tests/neg-macros/BigFloat/BigFloatFromDigitsImpl_1.scala index 7f29fdc2505a..12614de4eac1 100644 --- a/tests/neg-macros/BigFloat/BigFloatFromDigitsImpl_1.scala +++ b/tests/neg-macros/BigFloat/BigFloatFromDigitsImpl_1.scala @@ -1,4 +1,5 @@ package test +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/neg-macros/BigFloat/BigFloat_1.scala b/tests/neg-macros/BigFloat/BigFloat_1.scala index 61308fa93c45..296d14e0ee50 100644 --- a/tests/neg-macros/BigFloat/BigFloat_1.scala +++ b/tests/neg-macros/BigFloat/BigFloat_1.scala @@ -1,4 +1,5 @@ package test +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/neg-macros/GenericNumLits/EvenFromDigitsImpl_1.scala b/tests/neg-macros/GenericNumLits/EvenFromDigitsImpl_1.scala index 3c618e583c8e..b7c78d2bd441 100644 --- a/tests/neg-macros/GenericNumLits/EvenFromDigitsImpl_1.scala +++ b/tests/neg-macros/GenericNumLits/EvenFromDigitsImpl_1.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ import Even._ diff --git a/tests/neg-macros/GenericNumLits/Even_1.scala b/tests/neg-macros/GenericNumLits/Even_1.scala index 37da76205719..be618d1cd741 100644 --- a/tests/neg-macros/GenericNumLits/Even_1.scala +++ b/tests/neg-macros/GenericNumLits/Even_1.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/neg-macros/GenericNumLits/Test_2.scala b/tests/neg-macros/GenericNumLits/Test_2.scala index 9ba8aec01b9e..37b5ebab553e 100644 --- a/tests/neg-macros/GenericNumLits/Test_2.scala +++ b/tests/neg-macros/GenericNumLits/Test_2.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals object Test extends App { val e1: Even = 1234 diff --git a/tests/neg-with-compiler/GenericNumLits/EvenFromDigitsImpl_1.scala b/tests/neg-with-compiler/GenericNumLits/EvenFromDigitsImpl_1.scala index 3c618e583c8e..b7c78d2bd441 100644 --- a/tests/neg-with-compiler/GenericNumLits/EvenFromDigitsImpl_1.scala +++ b/tests/neg-with-compiler/GenericNumLits/EvenFromDigitsImpl_1.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ import Even._ diff --git a/tests/neg-with-compiler/GenericNumLits/Even_1.scala b/tests/neg-with-compiler/GenericNumLits/Even_1.scala index 37da76205719..be618d1cd741 100644 --- a/tests/neg-with-compiler/GenericNumLits/Even_1.scala +++ b/tests/neg-with-compiler/GenericNumLits/Even_1.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/neg-with-compiler/GenericNumLits/Test_2.scala b/tests/neg-with-compiler/GenericNumLits/Test_2.scala index 783ec1bf3e53..579fca249337 100644 --- a/tests/neg-with-compiler/GenericNumLits/Test_2.scala +++ b/tests/neg-with-compiler/GenericNumLits/Test_2.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals object Test extends App { val e1: Even = 1234 diff --git a/tests/neg/genericNumbers.scala b/tests/neg/genericNumbers.scala new file mode 100644 index 000000000000..62481ddcecc1 --- /dev/null +++ b/tests/neg/genericNumbers.scala @@ -0,0 +1,41 @@ +import scala.util.FromDigits + +object Test extends App { + + val x: BigInt = 13232202002020202020202 // error + val z: BigDecimal = 132322020020.223 + + case class Even(n: Int) + + given FromDigits[Even] { + def fromDigits(digits: String): Even = { + val intValue = digits.toInt + if (intValue % 2 == 0) Even(intValue) + else throw FromDigits.MalformedNumber() + } + } + + val e: Even = 1234 // error + + try { + println(123: Even) // error + } catch { + case ex: FromDigits.MalformedNumber => println("malformed") + } + + x match { + case 13_232_202_002_020_202_020_202 => () // error + } + (x: Any) match { + case 13232202002020202020202: BigInt => () // error + } + x match { + case 13232202002020202020202 => assert(false) // error + case -0xaabb12345ACF12345AC => () // error + } + + (e: Any) match { + case 1234: Even => // error + case _: Even => + } +} \ No newline at end of file diff --git a/tests/run-macros/BigFloat/BigFloatFromDigitsImpl_1.scala b/tests/run-macros/BigFloat/BigFloatFromDigitsImpl_1.scala index 7f29fdc2505a..12614de4eac1 100644 --- a/tests/run-macros/BigFloat/BigFloatFromDigitsImpl_1.scala +++ b/tests/run-macros/BigFloat/BigFloatFromDigitsImpl_1.scala @@ -1,4 +1,5 @@ package test +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/run-macros/BigFloat/BigFloat_1.scala b/tests/run-macros/BigFloat/BigFloat_1.scala index 61308fa93c45..296d14e0ee50 100644 --- a/tests/run-macros/BigFloat/BigFloat_1.scala +++ b/tests/run-macros/BigFloat/BigFloat_1.scala @@ -1,4 +1,5 @@ package test +import language.experimental.genericNumberLiterals import scala.util.FromDigits import scala.quoted._ diff --git a/tests/run-macros/BigFloat/Test_2.scala b/tests/run-macros/BigFloat/Test_2.scala index cae28d1ab700..49690d2ffe80 100644 --- a/tests/run-macros/BigFloat/Test_2.scala +++ b/tests/run-macros/BigFloat/Test_2.scala @@ -1,4 +1,5 @@ import test.BigFloat +import language.experimental.genericNumberLiterals import scala.util.FromDigits object Test extends App { diff --git a/tests/run/genericNumLits.scala b/tests/run/genericNumLits.scala index 5c0970cc3982..7d1737903d21 100644 --- a/tests/run/genericNumLits.scala +++ b/tests/run/genericNumLits.scala @@ -1,3 +1,4 @@ +import language.experimental.genericNumberLiterals import scala.util.FromDigits object Test extends App {