В Scala 3, с одной стороны, можно завести тип, имя которого — просто некоторое число, с другой стороны, можно делать вычисления с типами, а с третьей стороны можно объединять типы через логическое «или». Из этого следует, что безо всяких макросов есть возможность определить функцию, которая, например, принимает в качестве параметра значения от нуля до какого-то определённого, а если попытаться передать какое-то другое, то компилятор выдаст ошибку. Тот же фокус можно проделать и с переменной: ограничить её возможные значения, причём с проверкой во время компиляции. Такая переменная будет прекрасно подходить к соответствующей функции. type LessBuilder = [ T <: Int , Acc ] =>> T match case 1 => 1 | Acc case _ => LessBuilder [ T - 1 , T | Acc ] type UpTo [ T <: Int ] = LessBuilder [ T - 1 , T ] def f ( x : UpTo [ 5 ] ) = x + 1 println ( f ( 3 ) ) println ( f ( 9 ) ) // Ошибка компиляции val x : UpTo [ 5 ] = 4 println ( f ( x ) ) Правда, расшифровка типа UpTo[5] получается прямо вообще офигенная. (1 : Int) | ((5 : Int) - (1 : Int) - (1 : Int) - (1 : Int) | ((5 : Int) - (1 : Int) - (1 : Int) | ((5 : Int) - (1 : Int) | (5 : Int)))) Но, блин, работает. Не знаю, зачем это нужно, но вдруг. doc-файл