12
12
13
13
package org .scalajs .ir
14
14
15
- import scala .annotation .tailrec
16
-
17
15
import Names ._
18
16
import Trees ._
19
17
@@ -62,20 +60,14 @@ object Types {
62
60
}
63
61
}
64
62
65
- sealed abstract class PrimTypeWithRef extends PrimType {
66
- def primRef : PrimRef = this match {
67
- case VoidType => VoidRef
68
- case BooleanType => BooleanRef
69
- case CharType => CharRef
70
- case ByteType => ByteRef
71
- case ShortType => ShortRef
72
- case IntType => IntRef
73
- case LongType => LongRef
74
- case FloatType => FloatRef
75
- case DoubleType => DoubleRef
76
- case NullType => NullRef
77
- case NothingType => NothingRef
78
- }
63
+ /* Each PrimTypeWithRef creates its corresponding `PrimRef`. Therefore, it
64
+ * takes the parameters that need to be passed to the `PrimRef` constructor.
65
+ * This little dance ensures proper initialization safety between
66
+ * `PrimTypeWithRef`s and `PrimRef`s.
67
+ */
68
+ sealed abstract class PrimTypeWithRef (primRefCharCode : Char , primRefDisplayName : String )
69
+ extends PrimType {
70
+ val primRef : PrimRef = new PrimRef (this , primRefCharCode, primRefDisplayName)
79
71
}
80
72
81
73
/** Any type.
@@ -106,50 +98,50 @@ object Types {
106
98
* Expressions from which one can never come back are typed as `Nothing`.
107
99
* For example, `throw` and `return`.
108
100
*/
109
- case object NothingType extends PrimTypeWithRef
101
+ case object NothingType extends PrimTypeWithRef ( 'E' , " nothing " )
110
102
111
103
/** The type of `undefined`. */
112
104
case object UndefType extends PrimType
113
105
114
106
/** Boolean type.
115
107
* It does not accept `null` nor `undefined`.
116
108
*/
117
- case object BooleanType extends PrimTypeWithRef
109
+ case object BooleanType extends PrimTypeWithRef ( 'Z' , " boolean " )
118
110
119
111
/** `Char` type, a 16-bit UTF-16 code unit.
120
112
* It does not accept `null` nor `undefined`.
121
113
*/
122
- case object CharType extends PrimTypeWithRef
114
+ case object CharType extends PrimTypeWithRef ( 'C' , " char " )
123
115
124
116
/** 8-bit signed integer type.
125
117
* It does not accept `null` nor `undefined`.
126
118
*/
127
- case object ByteType extends PrimTypeWithRef
119
+ case object ByteType extends PrimTypeWithRef ( 'B' , " byte " )
128
120
129
121
/** 16-bit signed integer type.
130
122
* It does not accept `null` nor `undefined`.
131
123
*/
132
- case object ShortType extends PrimTypeWithRef
124
+ case object ShortType extends PrimTypeWithRef ( 'S' , " short " )
133
125
134
126
/** 32-bit signed integer type.
135
127
* It does not accept `null` nor `undefined`.
136
128
*/
137
- case object IntType extends PrimTypeWithRef
129
+ case object IntType extends PrimTypeWithRef ( 'I' , " int " )
138
130
139
131
/** 64-bit signed integer type.
140
132
* It does not accept `null` nor `undefined`.
141
133
*/
142
- case object LongType extends PrimTypeWithRef
134
+ case object LongType extends PrimTypeWithRef ( 'J' , " long " )
143
135
144
136
/** Float type (32-bit).
145
137
* It does not accept `null` nor `undefined`.
146
138
*/
147
- case object FloatType extends PrimTypeWithRef
139
+ case object FloatType extends PrimTypeWithRef ( 'F' , " float " )
148
140
149
141
/** Double type (64-bit).
150
142
* It does not accept `null` nor `undefined`.
151
143
*/
152
- case object DoubleType extends PrimTypeWithRef
144
+ case object DoubleType extends PrimTypeWithRef ( 'D' , " double " )
153
145
154
146
/** String type.
155
147
* It does not accept `null` nor `undefined`.
@@ -160,7 +152,7 @@ object Types {
160
152
* It does not accept `undefined`.
161
153
* The null type is a subtype of all class types and array types.
162
154
*/
163
- case object NullType extends PrimTypeWithRef
155
+ case object NullType extends PrimTypeWithRef ( 'N' , " null " )
164
156
165
157
/** Class (or interface) type. */
166
158
final case class ClassType (className : ClassName , nullable : Boolean ) extends Type {
@@ -210,7 +202,7 @@ object Types {
210
202
}
211
203
212
204
/** Void type, the top of type of our type system. */
213
- case object VoidType extends PrimTypeWithRef
205
+ case object VoidType extends PrimTypeWithRef ( 'V' , " void " )
214
206
215
207
@ deprecated(" Use VoidType instead" , since = " 1.18.0" )
216
208
lazy val NoType : VoidType .type = VoidType
@@ -265,8 +257,12 @@ object Types {
265
257
266
258
sealed abstract class NonArrayTypeRef extends TypeRef
267
259
260
+ // scalastyle:off equals.hash.code
261
+ // PrimRef uses reference equality, but has a stable hashCode() method
262
+
268
263
/** Primitive type reference. */
269
- final case class PrimRef private [ir] (tpe : PrimTypeWithRef )
264
+ final class PrimRef private [Types ] (val tpe : PrimTypeWithRef ,
265
+ charCodeInit : Char , displayNameInit : String ) // "Init" variants so we can have good Scaladoc on the val's
270
266
extends NonArrayTypeRef {
271
267
272
268
/** The display name of this primitive type.
@@ -278,19 +274,7 @@ object Types {
278
274
* For `NullType` and `NothingType`, the names are `"null"` and
279
275
* `"nothing"`, respectively.
280
276
*/
281
- val displayName : String = tpe match {
282
- case VoidType => " void"
283
- case BooleanType => " boolean"
284
- case CharType => " char"
285
- case ByteType => " byte"
286
- case ShortType => " short"
287
- case IntType => " int"
288
- case LongType => " long"
289
- case FloatType => " float"
290
- case DoubleType => " double"
291
- case NullType => " null"
292
- case NothingType => " nothing"
293
- }
277
+ val displayName : String = displayNameInit
294
278
295
279
/** The char code of this primitive type.
296
280
*
@@ -302,41 +286,30 @@ object Types {
302
286
* For `NullType` and `NothingType`, the char codes are `'N'` and `'E'`,
303
287
* respectively.
304
288
*/
305
- val charCode : Char = tpe match {
306
- case VoidType => 'V'
307
- case BooleanType => 'Z'
308
- case CharType => 'C'
309
- case ByteType => 'B'
310
- case ShortType => 'S'
311
- case IntType => 'I'
312
- case LongType => 'J'
313
- case FloatType => 'F'
314
- case DoubleType => 'D'
315
- case NullType => 'N'
316
- case NothingType => 'E'
317
- }
289
+ val charCode : Char = charCodeInit
290
+
291
+ // Stable hash code, corresponding to reference equality
292
+ override def hashCode (): Int = charCode.##
318
293
}
319
294
320
- /* @unchecked for the initialization checker of Scala 3
321
- * When we get here, `VoidType` is not yet considered fully initialized because
322
- * its method `primRef` can access `VoidRef`. Since the constructor of
323
- * `PrimRef` pattern-matches on its `tpe`, which is `VoidType`, this is flagged
324
- * by the init checker, although our usage is safe given that we do not call
325
- * `primRef`. The same reasoning applies to the other primitive types.
326
- * In the future, we may want to rearrange the initialization sequence of
327
- * this file to avoid this issue.
328
- */
329
- final val VoidRef = PrimRef (VoidType : @ unchecked)
330
- final val BooleanRef = PrimRef (BooleanType : @ unchecked)
331
- final val CharRef = PrimRef (CharType : @ unchecked)
332
- final val ByteRef = PrimRef (ByteType : @ unchecked)
333
- final val ShortRef = PrimRef (ShortType : @ unchecked)
334
- final val IntRef = PrimRef (IntType : @ unchecked)
335
- final val LongRef = PrimRef (LongType : @ unchecked)
336
- final val FloatRef = PrimRef (FloatType : @ unchecked)
337
- final val DoubleRef = PrimRef (DoubleType : @ unchecked)
338
- final val NullRef = PrimRef (NullType : @ unchecked)
339
- final val NothingRef = PrimRef (NothingType : @ unchecked)
295
+ // scalastyle:on equals.hash.code
296
+
297
+ object PrimRef {
298
+ def unapply (typeRef : PrimRef ): Some [PrimTypeWithRef ] =
299
+ Some (typeRef.tpe)
300
+ }
301
+
302
+ final val VoidRef = VoidType .primRef
303
+ final val BooleanRef = BooleanType .primRef
304
+ final val CharRef = CharType .primRef
305
+ final val ByteRef = ByteType .primRef
306
+ final val ShortRef = ShortType .primRef
307
+ final val IntRef = IntType .primRef
308
+ final val LongRef = LongType .primRef
309
+ final val FloatRef = FloatType .primRef
310
+ final val DoubleRef = DoubleType .primRef
311
+ final val NullRef = NullType .primRef
312
+ final val NothingRef = NothingType .primRef
340
313
341
314
/** Class (or interface) type. */
342
315
final case class ClassRef (className : ClassName ) extends NonArrayTypeRef {
0 commit comments