0
# Metaprogramming
1
2
Compile-time operations, quoted expressions, and macro support for powerful metaprogramming with type-safe code generation and compile-time computation.
3
4
## Capabilities
5
6
### Compile-Time Operations
7
8
Core compile-time functions for constant folding, implicit summoning, and compile-time errors.
9
10
```scala { .api }
11
/**
12
* Get a value of singleton type T at compile time
13
* T must be a constant type like 42 or "hello"
14
*/
15
inline def constValue[T]: T
16
17
/**
18
* Safely get a constant value, returns None if not a constant type
19
*/
20
inline def constValueOpt[T]: Option[T]
21
22
/**
23
* Extract all constant values from a tuple type
24
*/
25
inline def constValueTuple[T <: Tuple]: T
26
27
/**
28
* Pattern match on types without values (erased matching)
29
*/
30
inline def erasedValue[T]: T
31
32
/**
33
* Marker for uninitialized fields (use with caution)
34
*/
35
def uninitialized: Nothing
36
37
/**
38
* Marker for deferred given instances
39
*/
40
def deferred: Nothing
41
42
/**
43
* Emit compile-time error with custom message
44
*/
45
inline def error(msg: String): Nothing
46
47
/**
48
* Get string representation of code expression
49
*/
50
inline def codeOf(arg: Any): String
51
52
/**
53
* Require that expression is a compile-time constant
54
*/
55
inline def requireConst(x: Boolean | Byte | Short | Int | Long | Float | Double | Char | String): Unit
56
57
/**
58
* Delayed implicit summoning - resolved at inline expansion
59
*/
60
inline def summonInline[T]: T
61
62
/**
63
* Conditional implicit summoning with fallback handling
64
*/
65
inline def summonFrom[T](f: Nothing => T): T
66
67
/**
68
* Summon all implicit instances for tuple of types
69
*/
70
inline def summonAll[T <: Tuple]: T
71
72
/**
73
* Force by-name parameter evaluation (compile-time assertion)
74
*/
75
inline def byName[T](x: => T): T
76
```
77
78
**Usage Examples:**
79
80
```scala
81
import scala.compiletime.*
82
83
// Constant value extraction
84
type Three = 3
85
val three: 3 = constValue[Three] // 3
86
87
type Message = "Hello, World!"
88
val msg: String = constValue[Message] // "Hello, World!"
89
90
// Safe constant extraction
91
val maybeConst = constValueOpt[Int] // None (Int is not a singleton type)
92
val definiteConst = constValueOpt[42] // Some(42)
93
94
// Tuple constant extraction
95
type Point = (1, 2, 3)
96
val coords = constValueTuple[Point] // (1, 2, 3)
97
98
// Type-based pattern matching
99
inline def sizeOf[T]: Int = inline erasedValue[T] match
100
case _: Byte => 1
101
case _: Short => 2
102
case _: Int => 4
103
case _: Long => 8
104
case _: Float => 4
105
case _: Double => 8
106
107
// Compile-time errors
108
inline def assertPositive(x: Int): Int =
109
inline if x <= 0 then error("Value must be positive")
110
else x
111
112
// Code introspection
113
val code = codeOf(1 + 2 * 3) // "1.+(2.*(3))"
114
115
// Conditional summoning
116
inline def optionalSummoning[T]: Option[T] = summonFrom {
117
case given T => Some(summon[T])
118
case _ => None
119
}
120
121
// By-name forcing
122
inline def debugTime[T](name: String)(expr: => T): T =
123
println(s"Evaluating $name")
124
byName(expr)
125
```
126
127
### Type-Level Operations
128
129
Compile-time operations on types for type-level programming.
130
131
#### Any Type Operations
132
133
```scala { .api }
134
/**
135
* Convert any type to its string representation
136
*/
137
type ToString[X] <: String
138
139
/**
140
* Type equality test
141
*/
142
type =:=[X, Y] <: Boolean
143
```
144
145
#### Boolean Operations
146
147
```scala { .api }
148
/**
149
* Boolean negation at type level
150
*/
151
type ![X <: Boolean] <: Boolean
152
153
/**
154
* Boolean AND at type level
155
*/
156
type &&[X <: Boolean, Y <: Boolean] <: Boolean
157
158
/**
159
* Boolean OR at type level
160
*/
161
type ||[X <: Boolean, Y <: Boolean] <: Boolean
162
```
163
164
#### Integer Operations
165
166
```scala { .api }
167
/**
168
* Successor (add 1) at type level
169
*/
170
type S[X <: Int] <: Int
171
172
/**
173
* Addition at type level
174
*/
175
type +[X <: Int, Y <: Int] <: Int
176
177
/**
178
* Subtraction at type level
179
*/
180
type -[X <: Int, Y <: Int] <: Int
181
182
/**
183
* Multiplication at type level
184
*/
185
type *[X <: Int, Y <: Int] <: Int
186
187
/**
188
* Division at type level
189
*/
190
type /[X <: Int, Y <: Int] <: Int
191
192
/**
193
* Modulo at type level
194
*/
195
type %[X <: Int, Y <: Int] <: Int
196
197
/**
198
* Less than comparison at type level
199
*/
200
type <[X <: Int, Y <: Int] <: Boolean
201
202
/**
203
* Less than or equal at type level
204
*/
205
type <=[X <: Int, Y <: Int] <: Boolean
206
207
/**
208
* Greater than at type level
209
*/
210
type >[X <: Int, Y <: Int] <: Boolean
211
212
/**
213
* Greater than or equal at type level
214
*/
215
type >=[X <: Int, Y <: Int] <: Boolean
216
217
/**
218
* Absolute value at type level
219
*/
220
type Abs[X <: Int] <: Int
221
222
/**
223
* Maximum of two integers at type level
224
*/
225
type Max[X <: Int, Y <: Int] <: Int
226
227
/**
228
* Minimum of two integers at type level
229
*/
230
type Min[X <: Int, Y <: Int] <: Int
231
```
232
233
#### String Operations
234
235
```scala { .api }
236
/**
237
* String concatenation at type level
238
*/
239
type +[X <: String, Y <: String] <: String
240
241
/**
242
* String length at type level
243
*/
244
type Length[X <: String] <: Int
245
246
/**
247
* Substring extraction at type level
248
*/
249
type Substring[S <: String, IBeg <: Int, IEnd <: Int] <: String
250
251
/**
252
* Regular expression matching at type level
253
*/
254
type Matches[S <: String, Regex <: String] <: Boolean
255
```
256
257
**Usage Examples:**
258
259
```scala
260
import scala.compiletime.ops.*
261
262
// Type-level arithmetic
263
type Five = int.+[2, 3] // 5
264
type Seven = int.*[Five, 1] // 7
265
type Two = int.-[Five, 3] // 2
266
267
// Type-level boolean logic
268
type True = boolean.![false] // true
269
type False = boolean.&&[true, false] // false
270
271
// Type-level string operations
272
type Greeting = string.+["Hello", " World"] // "Hello World"
273
type Len = string.Length[Greeting] // 11
274
type Sub = string.Substring[Greeting, 0, 5] // "Hello"
275
276
// Using in function signatures
277
def vectorOfSize[N <: Int](size: N): IArray[Int] =
278
IArray.fill(constValue[N])(0)
279
280
val vec5 = vectorOfSize[5] // IArray of size 5
281
```
282
283
### Quoted Expressions
284
285
Quotation system for representing and manipulating Scala expressions at compile time.
286
287
```scala { .api }
288
/**
289
* Quoted expression representing Scala code of type T
290
*/
291
abstract class Expr[+T]:
292
/** Show the expression as a string */
293
def show(using Quotes): String
294
/** Get the value if expression is a constant */
295
def value(using Quotes): Option[T]
296
/** Get the value, throwing if not constant */
297
def valueOrAbort(using Quotes)(msg: String): T
298
/** Apply beta reduction to inline definitions */
299
def betaReduce(using Quotes): Expr[T]
300
301
object Expr:
302
/** Lift a value to an expression */
303
def apply[T](value: T)(using ToExpr[T], Quotes): Expr[T]
304
/** Create block expression */
305
def block[T](statements: List[Expr[Any]], expr: Expr[T])(using Quotes): Expr[T]
306
/** Unapply to extract value from constant expression */
307
def unapply[T](expr: Expr[T])(using Quotes): Option[T]
308
/** Create expression from sequence */
309
def ofSeq[T](elems: Seq[Expr[T]])(using Type[T], Quotes): Expr[Seq[T]]
310
/** Create expression from list */
311
def ofList[T](elems: List[Expr[T]])(using Type[T], Quotes): Expr[List[T]]
312
/** Create tuple expression from sequence */
313
def ofTupleFromSeq(elems: Seq[Expr[Any]])(using Quotes): Expr[Tuple]
314
/** Summon implicit and create expression */
315
def summon[T](using Type[T], Quotes): Expr[T]
316
317
/**
318
* Type representation in quoted context
319
*/
320
trait Type[T]:
321
/** Show the type as a string */
322
def show(using Quotes): String
323
324
/**
325
* Quotes context providing access to compiler information
326
*/
327
trait Quotes:
328
/** Reflect API for advanced operations */
329
val reflect: Reflect
330
331
/**
332
* Convert values to expressions
333
*/
334
trait ToExpr[T]:
335
def apply(x: T)(using Quotes): Expr[T]
336
337
/**
338
* Extract values from expressions
339
*/
340
trait FromExpr[T]:
341
def apply(x: Expr[T])(using Quotes): Option[T]
342
343
/**
344
* Variable argument expressions
345
*/
346
object Varargs:
347
def apply[T](elems: Expr[T]*)(using Type[T], Quotes): Expr[Seq[T]]
348
def unapply[T](expr: Expr[Seq[T]])(using Quotes): Option[Seq[Expr[T]]]
349
```
350
351
**Usage Examples:**
352
353
```scala
354
import scala.quoted.*
355
356
// Basic quotation (inside macro)
357
def exampleMacro(using Quotes): Expr[Int] =
358
val two = Expr(2)
359
val three = Expr(3)
360
'{ $two + $three } // Creates expression: 2 + 3
361
362
// Pattern matching on expressions
363
def analyzeExpr(expr: Expr[Int])(using Quotes): String = expr match
364
case Expr(n) => s"Constant: $n"
365
case '{ $x + $y } => s"Addition of ${x.show} and ${y.show}"
366
case _ => "Complex expression"
367
368
// Creating block expressions
369
def blockMacro(using Quotes): Expr[String] =
370
val printExpr = '{ println("Computing...") }
371
val resultExpr = '{ "Hello, World!" }
372
Expr.block(List(printExpr), resultExpr)
373
374
// Working with sequences
375
def listMacro(elems: Expr[Seq[Int]])(using Quotes): Expr[List[Int]] = elems match
376
case Varargs(exprs) =>
377
val listExprs = exprs.map(e => '{ $e }).toList
378
Expr.ofList(listExprs)
379
case _ =>
380
'{ $elems.toList }
381
```
382
383
### Compile-Time Testing
384
385
Utilities for testing compile-time behavior and error handling.
386
387
```scala { .api }
388
/**
389
* Representation of a compile-time error
390
*/
391
case class Error(
392
message: String,
393
line: Int,
394
column: Int,
395
kind: ErrorKind
396
)
397
398
/**
399
* Classification of compile errors
400
*/
401
enum ErrorKind:
402
case Parser, Typer, Other
403
404
/**
405
* Test if code compiles without errors
406
*/
407
def typeChecks(code: String): Boolean
408
409
/**
410
* Get all compile errors for given code
411
*/
412
def typeCheckErrors(code: String): List[Error]
413
```
414
415
**Usage Examples:**
416
417
```scala
418
import scala.compiletime.testing.*
419
420
// Test compilation
421
val goodCode = "val x: Int = 42"
422
val badCode = "val x: String = 42"
423
424
assert(typeChecks(goodCode)) // true
425
assert(!typeChecks(badCode)) // false
426
427
// Analyze errors
428
val errors = typeCheckErrors("val x: String = 42")
429
errors.foreach { error =>
430
println(s"Error at line ${error.line}: ${error.message}")
431
}
432
433
// Use in inline tests
434
inline def testInline(): Unit =
435
inline if !typeChecks("val x: Int = \"hello\"") then
436
println("Type error detected as expected")
437
```
438
439
### Extension Methods for Metaprogramming
440
441
```scala { .api }
442
extension (inline x: Any)
443
/** Cast value to Matchable for pattern matching */
444
inline def asMatchable: Matchable
445
```
446
447
**Usage Examples:**
448
449
```scala
450
def processAny(x: Any): String =
451
x.asMatchable match
452
case s: String => s"String: $s"
453
case i: Int => s"Int: $i"
454
case _ => "Other"
455
```
456
457
## Types
458
459
```scala { .api }
460
// Core metaprogramming types
461
abstract class Expr[+T]
462
trait Type[T]
463
trait Quotes
464
trait ToExpr[T]
465
trait FromExpr[T]
466
467
// Type-level operation types
468
object ops:
469
object any:
470
type ToString[X] <: String
471
type =:=[X, Y] <: Boolean
472
473
object boolean:
474
type ![X <: Boolean] <: Boolean
475
type &&[X <: Boolean, Y <: Boolean] <: Boolean
476
type ||[X <: Boolean, Y <: Boolean] <: Boolean
477
478
object int:
479
type S[X <: Int] <: Int
480
type +[X <: Int, Y <: Int] <: Int
481
type -[X <: Int, Y <: Int] <: Int
482
type *[X <: Int, Y <: Int] <: Int
483
type /[X <: Int, Y <: Int] <: Int
484
type %[X <: Int, Y <: Int] <: Int
485
type <[X <: Int, Y <: Int] <: Boolean
486
type <=[X <: Int, Y <: Int] <: Boolean
487
type >[X <: Int, Y <: Int] <: Boolean
488
type >=[X <: Int, Y <: Int] <: Boolean
489
type Abs[X <: Int] <: Int
490
type Max[X <: Int, Y <: Int] <: Int
491
type Min[X <: Int, Y <: Int] <: Int
492
493
object long:
494
// Similar operations for Long types
495
496
object double:
497
// Similar operations for Double types
498
499
object float:
500
// Similar operations for Float types
501
502
object string:
503
type +[X <: String, Y <: String] <: String
504
type Length[X <: String] <: Int
505
type Substring[S <: String, IBeg <: Int, IEnd <: Int] <: String
506
type Matches[S <: String, Regex <: String] <: Boolean
507
508
// Testing types
509
case class Error(message: String, line: Int, column: Int, kind: ErrorKind)
510
enum ErrorKind
511
```