CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scala-lang--scala3-library-3

The Scala 3 standard library providing essential data types, collections, and functional programming constructs for the Scala 3 programming language

Overview
Eval results
Files

compile-time.mddocs/

Compile-Time Programming

The scala.compiletime package provides comprehensive utilities for compile-time metaprogramming, type-level computation, and constexpr-style programming in Scala 3.

Core Compile-Time Functions

Value Extraction and Constants

def erasedValue[T]: T
transparent inline def constValue[T]: T
transparent inline def constValueOpt[T]: Option[T]
inline def constValueTuple[T <: Tuple]: T
  • erasedValue[T]: Pattern match on types without having actual values (used in inline matches)
  • constValue[T]: Convert singleton types to their corresponding values at compile time
  • constValueOpt[T]: Safe version of constValue that returns None if conversion fails
  • constValueTuple[T]: Extract tuple of constant values from tuple type

Given Summoning

transparent inline def summonFrom[T](f: Nothing => T): T
transparent inline def summonInline[T]: T
inline def summonAll[T <: Tuple]: T
  • summonFrom[T]: Pattern match on available given instances
  • summonInline[T]: Summon given value with delayed resolution until full inlining
  • summonAll[T]: Summon all elements of a tuple type as a tuple of given instances

Compile-Time Assertions and Debugging

inline 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): Unit
  • error: Produce user-defined compile errors during inline expansion
  • codeOf: Get string representation of code (for debugging and error messages)
  • requireConst: Assert that a value is constant after inlining and constant folding

Initialization and Deferred Values

def uninitialized: Nothing
def deferred: Nothing
def byName[T](x: => T): T
  • uninitialized: Marker for uninitialized mutable fields (compile-time only)
  • deferred: Marker for deferred given definitions in traits
  • byName: Assertion for by-name parameters (used in nullability checking)

Type Conversion

extension [T](x: T) transparent inline def asMatchable: x.type & Matchable

Cast values to be Matchable for pattern matching with unconstrained type parameters.

Type-Level Operations

Integer Type Operations

// 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   // Maximum

Boolean Type Operations

type ![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 OR

String Type Operations

type +[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 matching

Usage Examples

Pattern Matching on Types

import 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"

Working with Constant Values

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]

Compile-Time Assertions

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 constant

Summoning Given Instances

import 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")

Type-Level Arithmetic

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"

String Type Operations

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"

Code Generation and Debugging

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"

Advanced Generic Programming

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)

Conditional Compilation

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

docs

annotations.md

compile-time.md

generic-programming.md

immutable-arrays.md

index.md

macros.md

structural-types.md

tuples.md

type-safe-equality.md

tile.json