The Scala 3 standard library providing essential data types, collections, and functional programming constructs for the Scala 3 programming language
The scala.compiletime package provides comprehensive utilities for compile-time metaprogramming, type-level computation, and constexpr-style programming in Scala 3.
def erasedValue[T]: T
transparent inline def constValue[T]: T
transparent inline def constValueOpt[T]: Option[T]
inline def constValueTuple[T <: Tuple]: TerasedValue[T]: Pattern match on types without having actual values (used in inline matches)constValue[T]: Convert singleton types to their corresponding values at compile timeconstValueOpt[T]: Safe version of constValue that returns None if conversion failsconstValueTuple[T]: Extract tuple of constant values from tuple typetransparent inline def summonFrom[T](f: Nothing => T): T
transparent inline def summonInline[T]: T
inline def summonAll[T <: Tuple]: TsummonFrom[T]: Pattern match on available given instancessummonInline[T]: Summon given value with delayed resolution until full inliningsummonAll[T]: Summon all elements of a tuple type as a tuple of given instancesinline def error(inline msg: String): Nothing
transparent inline def codeOf(arg: Any): String
inline def requireConst(inline x: Boolean | Byte | Short | Int | Long | Float | Double | Char | String): Uniterror: Produce user-defined compile errors during inline expansioncodeOf: Get string representation of code (for debugging and error messages)requireConst: Assert that a value is constant after inlining and constant foldingdef uninitialized: Nothing
def deferred: Nothing
def byName[T](x: => T): Tuninitialized: Marker for uninitialized mutable fields (compile-time only)deferred: Marker for deferred given definitions in traitsbyName: Assertion for by-name parameters (used in nullability checking)extension [T](x: T) transparent inline def asMatchable: x.type & MatchableCast values to be Matchable for pattern matching with unconstrained type parameters.
// Arithmetic operations
type +[X <: Int, Y <: Int] <: Int
type -[X <: Int, Y <: Int] <: Int
type *[X <: Int, Y <: Int] <: Int
type /[X <: Int, Y <: Int] <: Int
type %[X <: Int, Y <: Int] <: Int
// Comparison operations
type <[X <: Int, Y <: Int] <: Boolean
type <=[X <: Int, Y <: Int] <: Boolean
type >[X <: Int, Y <: Int] <: Boolean
type >=[X <: Int, Y <: Int] <: Boolean
// Utility operations
type S[X <: Int] <: Int // Successor (X + 1)
type Abs[X <: Int] <: Int // Absolute value
type Min[X <: Int, Y <: Int] <: Int // Minimum
type Max[X <: Int, Y <: Int] <: Int // Maximumtype ![X <: Boolean] <: Boolean // Negation
type &&[X <: Boolean, Y <: Boolean] <: Boolean // Logical AND
type ||[X <: Boolean, Y <: Boolean] <: Boolean // Logical OR
type XOR[X <: Boolean, Y <: Boolean] <: Boolean // Exclusive ORtype +[X <: String, Y <: String] <: String // Concatenation
type Length[X <: String] <: Int // String length
type Substring[S <: String, IBeg <: Int, IEnd <: Int] <: String // Substring
type CharAt[S <: String, I <: Int] <: Char // Character at index
type Matches[S <: String, Regex <: String] <: Boolean // Regex matchingimport scala.compiletime.*
inline def typeDescription[T]: String =
inline erasedValue[T] match
case _: String => "text"
case _: Int => "integer"
case _: Boolean => "boolean"
case _: EmptyTuple => "empty tuple"
case _: (h *: t) => s"tuple starting with ${typeDescription[h]}"
case _ => "unknown type"
// Usage
val desc1 = typeDescription[String] // "text"
val desc2 = typeDescription[Int *: String *: EmptyTuple] // "tuple starting with integer"import scala.compiletime.*
// Convert singleton types to values
type Three = 3
type Hello = "hello"
val three: 3 = constValue[Three] // 3
val hello: "hello" = constValue[Hello] // "hello"
// Safe constant extraction
inline def safeConstant[T]: String =
constValueOpt[T] match
case Some(value) => s"Constant: $value"
case None => "Not a constant type"
val result1 = safeConstant[42] // "Constant: 42"
val result2 = safeConstant[String] // "Not a constant type"
// Working with tuple constants
type Numbers = (1, 2, 3)
val numbers: (1, 2, 3) = constValueTuple[Numbers]import scala.compiletime.*
inline def safeDivision(inline numerator: Int, inline denominator: Int): Double =
requireConst(denominator) // Ensure denominator is known at compile time
inline if constValue[denominator.type] == 0 then
error("Division by zero detected at compile time")
else
numerator.toDouble / denominator.toDouble
// Usage
val result1 = safeDivision(10, 2) // Compiles: 5.0
// val result2 = safeDivision(10, 0) // Compile error: "Division by zero detected at compile time"
val x = 5
// val result3 = safeDivision(10, x) // Compile error: x is not constantimport scala.compiletime.*
trait Show[T]:
def show(value: T): String
given Show[Int] with
def show(value: Int) = value.toString
given Show[String] with
def show(value: String) = s"\"$value\""
given Show[Boolean] with
def show(value: Boolean) = value.toString
// Summon specific instance
inline def showValue[T](value: T): String =
summonInline[Show[T]].show(value)
// Pattern match on available instances
inline def showAny[T](value: T): String =
summonFrom {
case given Show[T] => summon[Show[T]].show(value)
case _ => "No Show instance available"
}
// Summon multiple instances
inline def showTuple[T <: Tuple](tuple: T): List[String] =
summonAll[Tuple.Map[T, Show]].toList.zip(tuple.toList).map {
case (showInstance, value) => showInstance.asInstanceOf[Show[Any]].show(value)
}
val result1 = showValue(42) // "42"
val result2 = showAny("hello") // "\"hello\""
val result3 = showTuple((42, "world", true)) // List("42", "\"world\"", "true")import scala.compiletime.ops.int.*
type Two = 2
type Three = 3
type Five = Two + Three
type Six = Two * Three
type IsLess = Two < Three // true
type Successor = S[Two] // 3
// Compile-time computation
inline def factorial[N <: Int]: Int =
inline constValue[N] match
case 0 => 1
case 1 => 1
case n => n * factorial[N - 1]
val fact5: Int = factorial[5] // 120 (computed at compile time)
// Type-level validation
inline def validateArrayIndex[Size <: Int, Index <: Int]: Unit =
inline if constValue[Index >= Size] then
error("Array index out of bounds")
else if constValue[Index < 0] then
error("Negative array index")
validateArrayIndex[5, 2] // Compiles
// validateArrayIndex[5, 7] // Compile error: "Array index out of bounds"import scala.compiletime.ops.string.*
type Hello = "Hello"
type World = "World"
type HelloWorld = Hello + " " + World // "Hello World"
type HelloLength = Length[Hello] // 5
type FirstChar = CharAt[Hello, 0] // 'H'
inline def greet[Name <: String]: String =
"Hello, " + constValue[Name] + "!"
val greeting = greet["Alice"] // "Hello, Alice!"
// Compile-time string validation
inline def validateEmail[Email <: String]: Unit =
inline if !constValue[Matches[Email, ".*@.*\\..*"]] then
error("Invalid email format")
validateEmail["user@example.com"] // Compiles
// validateEmail["invalid-email"] // Compile error: "Invalid email format"import scala.compiletime.*
inline def logged[T](inline expr: T): T =
println(s"Evaluating: ${codeOf(expr)}")
expr
val result = logged(2 + 3 * 4)
// Prints: "Evaluating: 2.+(3.*(4))"
// Returns: 14
// Debug macro expansion
inline def debugType[T]: String =
inline erasedValue[T] match
case _: Int => s"Int type with code: ${codeOf(42)}"
case _: String => s"String type with code: ${codeOf("hello")}"
case _ => s"Other type"import scala.compiletime.*
// Compile-time list processing
type NestedTuple = ((Int, String), (Boolean, Double), (Char, Float))
inline def processTuple[T <: Tuple]: String =
inline erasedValue[T] match
case _: EmptyTuple => "empty"
case _: (h *: t) =>
s"head: ${typeDescription[h]}, tail: ${processTuple[t]}"
inline def tupleSize[T <: Tuple]: Int =
inline erasedValue[T] match
case _: EmptyTuple => 0
case _: (h *: t) => 1 + tupleSize[t]
val description = processTuple[NestedTuple]
val size = tupleSize[NestedTuple] // 3
// Compile-time validation for type classes
inline def requireShow[T]: Unit =
summonFrom {
case given Show[T] => ()
case _ => error(s"No Show instance for type ${codeOf(??? : T)}")
}
inline def showIfPossible[T](value: T): String =
requireShow[T]
summon[Show[T]].show(value)import scala.compiletime.*
inline def platformSpecific[T](value: T): String =
inline if constValue[scala.util.Properties.isWin] then
s"Windows: $value"
else if constValue[scala.util.Properties.isLinux] then
s"Linux: $value"
else
s"Other OS: $value"
// Feature flags at compile time
inline val FEATURE_ENABLED = true
inline def withFeature[T](inline enabled: T, inline disabled: T): T =
inline if FEATURE_ENABLED then enabled else disabled
val result = withFeature("Feature is on", "Feature is off")The compile-time programming capabilities in Scala 3 enable powerful metaprogramming techniques, allowing developers to move computations and validations from runtime to compile time, resulting in better performance and stronger type safety guarantees.
Install with Tessl CLI
npx tessl i tessl/maven-org-scala-lang--scala3-library-3