Skip to content

Commit bd3046b

Browse files
authored
Make failing pc tests work again in non-bootstrapped mode (#21707)
Bring back experimental NamedTuple in non-bootstrapped src/library. Needed to make SignatureHelpTests and CompletionTests to go through. [test_non_bootstrapped]
2 parents f6c6ec6 + 3b9c7c8 commit bd3046b

File tree

1 file changed

+228
-0
lines changed

1 file changed

+228
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
package scala
2+
import scala.language.experimental.clauseInterleaving
3+
import annotation.experimental
4+
import compiletime.ops.boolean.*
5+
6+
@experimental
7+
object NamedTuple:
8+
9+
/** The type to which named tuples get mapped to. For instance,
10+
* (name: String, age: Int)
11+
* gets mapped to
12+
* NamedTuple[("name", "age"), (String, Int)]
13+
*/
14+
opaque type NamedTuple[N <: Tuple, +V <: Tuple] >: V <: AnyNamedTuple = V
15+
16+
/** A type which is a supertype of all named tuples */
17+
opaque type AnyNamedTuple = Any
18+
19+
def apply[N <: Tuple, V <: Tuple](x: V): NamedTuple[N, V] = x
20+
21+
def unapply[N <: Tuple, V <: Tuple](x: NamedTuple[N, V]): Some[V] = Some(x)
22+
23+
/** A named tuple expression will desugar to a call to `build`. For instance,
24+
* `(name = "Lyra", age = 23)` will desugar to `build[("name", "age")]()(("Lyra", 23))`.
25+
*/
26+
inline def build[N <: Tuple]()[V <: Tuple](x: V): NamedTuple[N, V] = x
27+
28+
extension [V <: Tuple](x: V)
29+
inline def withNames[N <: Tuple]: NamedTuple[N, V] = x
30+
31+
export NamedTupleDecomposition.{
32+
Names, DropNames,
33+
apply, size, init, head, last, tail, take, drop, splitAt, ++, map, reverse, zip, toList, toArray, toIArray
34+
}
35+
36+
extension [N <: Tuple, V <: Tuple](x: NamedTuple[N, V])
37+
38+
// ALL METHODS DEPENDING ON `toTuple` MUST BE EXPORTED FROM `NamedTupleDecomposition`
39+
/** The underlying tuple without the names */
40+
inline def toTuple: V = x
41+
42+
// This intentionally works for empty named tuples as well. I think NonEmptyTuple is a dead end
43+
// and should be reverted, just like NonEmptyList is also appealing at first, but a bad idea
44+
// in the end.
45+
46+
// inline def :* [L] (x: L): NamedTuple[Append[N, ???], Append[V, L] = ???
47+
// inline def *: [H] (x: H): NamedTuple[??? *: N], H *: V] = ???
48+
49+
end extension
50+
51+
/** The size of a named tuple, represented as a literal constant subtype of Int */
52+
type Size[X <: AnyNamedTuple] = Tuple.Size[DropNames[X]]
53+
54+
/** The type of the element value at position N in the named tuple X */
55+
type Elem[X <: AnyNamedTuple, N <: Int] = Tuple.Elem[DropNames[X], N]
56+
57+
/** The type of the first element value of a named tuple */
58+
type Head[X <: AnyNamedTuple] = Elem[X, 0]
59+
60+
/** The type of the last element value of a named tuple */
61+
type Last[X <: AnyNamedTuple] = Tuple.Last[DropNames[X]]
62+
63+
/** The type of a named tuple consisting of all elements of named tuple X except the first one */
64+
type Tail[X <: AnyNamedTuple] = Drop[X, 1]
65+
66+
/** The type of the initial part of a named tuple without its last element */
67+
type Init[X <: AnyNamedTuple] =
68+
NamedTuple[Tuple.Init[Names[X]], Tuple.Init[DropNames[X]]]
69+
70+
/** The type of the named tuple consisting of the first `N` elements of `X`,
71+
* or all elements if `N` exceeds `Size[X]`.
72+
*/
73+
type Take[X <: AnyNamedTuple, N <: Int] =
74+
NamedTuple[Tuple.Take[Names[X], N], Tuple.Take[DropNames[X], N]]
75+
76+
/** The type of the named tuple consisting of all elements of `X` except the first `N` ones,
77+
* or no elements if `N` exceeds `Size[X]`.
78+
*/
79+
type Drop[X <: AnyNamedTuple, N <: Int] =
80+
NamedTuple[Tuple.Drop[Names[X], N], Tuple.Drop[DropNames[X], N]]
81+
82+
/** The pair type `(Take(X, N), Drop[X, N]). */
83+
type Split[X <: AnyNamedTuple, N <: Int] = (Take[X, N], Drop[X, N])
84+
85+
/** Type of the concatenation of two tuples `X` and `Y` */
86+
type Concat[X <: AnyNamedTuple, Y <: AnyNamedTuple] =
87+
NamedTuple[Tuple.Concat[Names[X], Names[Y]], Tuple.Concat[DropNames[X], DropNames[Y]]]
88+
89+
/** The type of the named tuple `X` mapped with the type-level function `F`.
90+
* If `X = (n1 : T1, ..., ni : Ti)` then `Map[X, F] = `(n1 : F[T1], ..., ni : F[Ti])`.
91+
*/
92+
type Map[X <: AnyNamedTuple, F[_ <: Tuple.Union[DropNames[X]]]] =
93+
NamedTuple[Names[X], Tuple.Map[DropNames[X], F]]
94+
95+
/** A named tuple with the elements of tuple `X` in reversed order */
96+
type Reverse[X <: AnyNamedTuple] =
97+
NamedTuple[Tuple.Reverse[Names[X]], Tuple.Reverse[DropNames[X]]]
98+
99+
/** The type of the named tuple consisting of all element values of
100+
* named tuple `X` zipped with corresponding element values of
101+
* named tuple `Y`. If the two tuples have different sizes,
102+
* the extra elements of the larger tuple will be disregarded.
103+
* The names of `X` and `Y` at the same index must be the same.
104+
* The result tuple keeps the same names as the operand tuples.
105+
* For example, if
106+
* ```
107+
* X = (n1 : S1, ..., ni : Si)
108+
* Y = (n1 : T1, ..., nj : Tj) where j >= i
109+
* ```
110+
* then
111+
* ```
112+
* Zip[X, Y] = (n1 : (S1, T1), ..., ni: (Si, Ti))
113+
* ```
114+
* @syntax markdown
115+
*/
116+
type Zip[X <: AnyNamedTuple, Y <: AnyNamedTuple] =
117+
Names[X] match
118+
case Names[Y] =>
119+
NamedTuple[Names[X], Tuple.Zip[DropNames[X], DropNames[Y]]]
120+
121+
/** A type specially treated by the compiler to represent all fields of a
122+
* class argument `T` as a named tuple. Or, if `T` is already a named tuple,
123+
* `From[T]` is the same as `T`.
124+
*/
125+
type From[T] <: AnyNamedTuple
126+
127+
/** The type of the empty named tuple */
128+
type Empty = NamedTuple[EmptyTuple, EmptyTuple]
129+
130+
/** The empty named tuple */
131+
val Empty: Empty = EmptyTuple
132+
133+
end NamedTuple
134+
135+
/** Separate from NamedTuple object so that we can match on the opaque type NamedTuple. */
136+
@experimental
137+
object NamedTupleDecomposition:
138+
import NamedTuple.*
139+
extension [N <: Tuple, V <: Tuple](x: NamedTuple[N, V])
140+
/** The value (without the name) at index `n` of this tuple */
141+
inline def apply(n: Int): Tuple.Elem[V, n.type] =
142+
inline x.toTuple match
143+
case tup: NonEmptyTuple => tup(n).asInstanceOf[Tuple.Elem[V, n.type]]
144+
case tup => tup.productElement(n).asInstanceOf[Tuple.Elem[V, n.type]]
145+
146+
/** The number of elements in this tuple */
147+
inline def size: Tuple.Size[V] = x.toTuple.size
148+
149+
/** The first element value of this tuple */
150+
inline def head: Tuple.Elem[V, 0] = apply(0)
151+
152+
/** The last element value of this tuple */
153+
inline def last: Tuple.Last[V] = apply(size - 1).asInstanceOf[Tuple.Last[V]]
154+
155+
/** The tuple consisting of all elements of this tuple except the last one */
156+
inline def init: NamedTuple[Tuple.Init[N], Tuple.Init[V]] =
157+
x.toTuple.take(size - 1).asInstanceOf[NamedTuple[Tuple.Init[N], Tuple.Init[V]]]
158+
159+
/** The tuple consisting of all elements of this tuple except the first one */
160+
inline def tail: NamedTuple[Tuple.Tail[N], Tuple.Tail[V]] =
161+
x.toTuple.drop(1).asInstanceOf[NamedTuple[Tuple.Tail[N], Tuple.Tail[V]]]
162+
163+
/** The tuple consisting of the first `n` elements of this tuple, or all
164+
* elements if `n` exceeds `size`.
165+
*/
166+
inline def take(n: Int): NamedTuple[Tuple.Take[N, n.type], Tuple.Take[V, n.type]] =
167+
x.toTuple.take(n)
168+
169+
/** The tuple consisting of all elements of this tuple except the first `n` ones,
170+
* or no elements if `n` exceeds `size`.
171+
*/
172+
inline def drop(n: Int): NamedTuple[Tuple.Drop[N, n.type], Tuple.Drop[V, n.type]] =
173+
x.toTuple.drop(n)
174+
175+
/** The tuple `(x.take(n), x.drop(n))` */
176+
inline def splitAt(n: Int):
177+
(NamedTuple[Tuple.Take[N, n.type], Tuple.Take[V, n.type]],
178+
NamedTuple[Tuple.Drop[N, n.type], Tuple.Drop[V, n.type]]) =
179+
// would be nice if this could have type `Split[NamedTuple[N, V]]` instead, but
180+
// we get a type error then. Similar for other methods here.
181+
x.toTuple.splitAt(n)
182+
183+
/** The tuple consisting of all elements of this tuple followed by all elements
184+
* of tuple `that`. The names of the two tuples must be disjoint.
185+
*/
186+
inline def ++ [N2 <: Tuple, V2 <: Tuple](that: NamedTuple[N2, V2])(using Tuple.Disjoint[N, N2] =:= true)
187+
: NamedTuple[Tuple.Concat[N, N2], Tuple.Concat[V, V2]]
188+
= x.toTuple ++ that.toTuple
189+
190+
/** The named tuple consisting of all element values of this tuple mapped by
191+
* the polymorphic mapping function `f`. The names of elements are preserved.
192+
* If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
193+
*/
194+
inline def map[F[_]](f: [t] => t => F[t]): NamedTuple[N, Tuple.Map[V, F]] =
195+
x.toTuple.map(f).asInstanceOf[NamedTuple[N, Tuple.Map[V, F]]]
196+
197+
/** The named tuple consisting of all elements of this tuple in reverse */
198+
inline def reverse: NamedTuple[Tuple.Reverse[N], Tuple.Reverse[V]] =
199+
x.toTuple.reverse
200+
201+
/** The named tuple consisting of all elements values of this tuple zipped
202+
* with corresponding element values in named tuple `that`.
203+
* If the two tuples have different sizes,
204+
* the extra elements of the larger tuple will be disregarded.
205+
* The names of `x` and `that` at the same index must be the same.
206+
* The result tuple keeps the same names as the operand tuples.
207+
*/
208+
inline def zip[V2 <: Tuple](that: NamedTuple[N, V2]): NamedTuple[N, Tuple.Zip[V, V2]] =
209+
x.toTuple.zip(that.toTuple)
210+
211+
/** A list consisting of all element values */
212+
inline def toList: List[Tuple.Union[V]] = x.toTuple.toList.asInstanceOf[List[Tuple.Union[V]]]
213+
214+
/** An array consisting of all element values */
215+
inline def toArray: Array[Object] = x.toTuple.toArray
216+
217+
/** An immutable array consisting of all element values */
218+
inline def toIArray: IArray[Object] = x.toTuple.toIArray
219+
220+
end extension
221+
222+
/** The names of a named tuple, represented as a tuple of literal string values. */
223+
type Names[X <: AnyNamedTuple] <: Tuple = X match
224+
case NamedTuple[n, _] => n
225+
226+
/** The value types of a named tuple represented as a regular tuple. */
227+
type DropNames[NT <: AnyNamedTuple] <: Tuple = NT match
228+
case NamedTuple[_, x] => x

0 commit comments

Comments
 (0)