summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Mirrors.scala
blob: 4fd99433799a2d3a54e93e936b0f2e773420f8a8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
package scala
package reflect
package api

/**
 * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
 *
 * This trait provides support for Mirrors in the Scala Reflection API.
 *
 * `Mirror`s are a central part of Scala Reflection. All information provided by
 * reflection is made accessible through `Mirror`s. Depending on the type of information
 * to be obtained, or the reflective action to be taken, different flavors of mirrors
 * must be used. "Classloader" mirrors can be used to obtain representations of types
 * and members. From a classloader `Mirror`, it's possible to obtain more specialized
 * "invoker" `Mirror`s (the most commonly-used mirrors), which implement reflective
 * invocations, such as method/constructor calls and field accesses.
 *
 * The two flavors of mirrors:
 *
 * <ul>
 * <li>'''“Classloader” mirrors'''. These mirrors translate names to symbols
 * (via methods `staticClass`/`staticModule`/`staticPackage`).</li>
 * <li>'''"Invoker” mirrors'''. These mirrors implement reflective invocations
 * (via methods `MethodMirror.apply`, `FieldMirror.get`, etc). These "invoker"
 * mirrors are the types of mirrors that are most commonly used.</li>
 * </ul>
 *
 * === Compile-time Mirrors ===
 * Compile-time `Mirror`s make use of only classloader `Mirror`s to load `Symbol`s
 * by name.
 *
 * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.Context#mirror]].
 * Typical methods which use classloader `Mirror`s include [[scala.reflect.api.Mirror#staticClass]],
 * [[scala.reflect.api.Mirror#staticModule]], and [[scala.reflect.api.Mirror#staticPackage]]. For
 * example:
 * {{{
 *  import scala.reflect.macros.Context
 *
 *  case class Location(filename: String, line: Int, column: Int)
 *
 *  object Macros {
 *    def currentLocation: Location = macro impl
 *
 *    def impl(c: Context): c.Expr[Location] = {
 *      import c.universe._
 *      val pos = c.macroApplication.pos
 *      val clsLocation = c.mirror.staticModule("Location") // get symbol of "Location" object
 *      c.Expr(Apply(Ident(clsLocation), List(Literal(Constant(pos.source.path)), Literal(Constant(pos.line)), Literal(Constant(pos.column)))))
 *    }
 *  }
 * }}}
 *
 * ''Of Note:'' There are several high-level alternatives that one can use to avoid having to manually
 * lookup symbols. For example, `typeOf[Location.type].termSymbol` (or `typeOf[Location].typeSymbol`
 * if we needed a `ClassSymbol`), which are type safe since we don’t have to use `String`s to lookup
 * the `Symbol`.
 *
 * === Runtime Mirrors ===
 *
 * Runtime `Mirror`s make use of both classloader and invoker `Mirror`s.
 *
 * The entry point to `Mirror`s for use at runtime is via `ru.runtimeMirror(<classloader>)`, where
 * `ru` is [[scala.reflect.runtime.universe]].
 *
 * The result of a [[scala.reflect.api.JavaMirrors#runtimeMirror]] call is a classloader mirror,
 * of type [[scala.reflect.api.Mirrors#ReflectiveMirror]], which can load symbols by names as
 * discussed above (in the “Compile-time” section).
 *
 * A classloader mirror can create invoker mirrors, which include: [[scala.reflect.api.Mirrors#InstanceMirror]],
 * [[scala.reflect.api.Mirrors#MethodMirror]], [[scala.reflect.api.Mirrors#FieldMirror]],
 * [[scala.reflect.api.Mirrors#ClassMirror]] and [[scala.reflect.api.Mirrors#ModuleMirror]].
 *
 * Examples of how these two types of `Mirror`s interact are available below.
 *
 * === Types of Mirrors, Their Use Cases & Examples ===
 *
 * '''[[scala.reflect.api.Mirrors#ReflectiveMirror]]'''. Used for loading `Symbol`s by name, and
 * as an entry point into invoker mirrors. Entry point: `val m = ru.runtimeMirror(<classloader>)`.
 * Example:
 * {{{
 *   scala> val ru = scala.reflect.runtime.universe
 *   ru: scala.reflect.api.JavaUniverse = ...
 *
 *   scala> val m = ru.runtimeMirror(getClass.getClassLoader)
 *   m: reflect.runtime.universe.Mirror = JavaMirror ...
 * }}}
 *
 * '''[[scala.reflect.api.Mirrors#InstanceMirror]]'''. Used for creating invoker `Mirror`s for methods
 * and fields and for inner classes and inner objects (modules). Entry point: `val im = m.reflect(<value>)`.
 * Example:
 * {{{
 *   scala> class C { def x = 2 }
 *   defined class C
 *
 *   scala> val im = m.reflect(new C)
 *   im: reflect.runtime.universe.InstanceMirror = instance mirror for C@3442299e
 * }}}
 *
 * '''[[scala.reflect.api.Mirrors#MethodMirror]]'''. Used for invoking instance methods (Scala only has
 * instance methods-- methods of objects are instance methods of object instances, obtainable
 * via `ModuleMirror.instance`). Entry point: `val mm = im.reflectMethod(<method symbol>)`.
 * Example:
 * {{{
 *   scala> val methodX = typeOf[C].declaration(newTermName("x")).asMethod
 *   methodX: reflect.runtime.universe.MethodSymbol = method x
 *
 *   scala> val mm = im.reflectMethod(methodX)
 *   mm: reflect.runtime.universe.MethodMirror = method mirror for C.x: scala.Int (bound to C@3442299e)
 *
 *   scala> mm()
 *   res0: Any = 2
 * }}}
 *
 * '''[[scala.reflect.api.Mirrors#FieldMirror]]'''. Used for getting/setting instance fields
 * (Scala only has instance fields-- fields of objects are instance methods of object instances
 * obtainable via ModuleMirror.instance). Entry point:
 * `val fm = im.reflectMethod(<field or accessor symbol>)`.
 * Example:
 * {{{
 *   scala> class C { val x = 2; val y = 3 }
 *   defined class C
 *
 *   scala> val m = ru.runtimeMirror(getClass.getClassLoader)
 *   m: reflect.runtime.universe.Mirror = JavaMirror ...
 *
 *   scala> val im = m.reflect(new C)
 *   im: reflect.runtime.universe.InstanceMirror = instance mirror for C@5f0c8ac1
 *
 *   scala> val fieldX = typeOf[C].declaration(newTermName("x")).asTerm.accessed.asTerm
 *   fieldX: reflect.runtime.universe.TermSymbol = value x
 *   scala> val fmX = im.reflectField(fieldX)
 *   fmX: reflect.runtime.universe.FieldMirror = field mirror for C.x (bound to C@5f0c8ac1)
 *
 *   scala> fmX.get
 *   res0: Any = 2
 *
 *   scala> fmX.set(3)
 *   scala.ScalaReflectionException: cannot set an immutable field x
 *   ...
 *
 *   scala> val fieldY = typeOf[C].declaration(newTermName("y")).asTerm.accessed.asTerm
 *   fieldY: reflect.runtime.universe.TermSymbol = variable y
 *
 *   scala> val fmY = im.reflectField(fieldY)
 *   fmY: reflect.runtime.universe.FieldMirror = field mirror for C.y (bound to C@5f0c8ac1)
 *
 *   scala> fmY.get
 *   res1: Any = 3
 *
 *   scala> fmY.set(4)
 *
 *   scala> fmY.get
 *   res2: Any = 4
 * }}}
 *
 * '''[[scala.reflect.api.Mirrors#ClassMirror]]'''. Used for creating invoker mirrors for constructors.
 * Entry points: for ''static classes'' `val cm1 = m.reflectClass(<class symbol>)`,
 * for ''inner classes'' `val mm2 = im.reflectClass(<module symbol>)`.
 * Example:
 * {{{
 *   scala> case class C(x: Int)
 *   defined class C
 *
 *   scala> val m = ru.runtimeMirror(getClass.getClassLoader)
 *   m: reflect.runtime.universe.Mirror = JavaMirror ...
 *
 *   scala> val classC = typeOf[C].typeSymbol.asClass
 *
 *   classC: reflect.runtime.universe.Symbol = class C
 *
 *   scala> val cm = m.reflectClass(classC)
 *   cm: reflect.runtime.universe.ClassMirror = class mirror for C (bound to null)
 *
 *   scala> val ctorC = typeOf[C].declaration(ru.nme.CONSTRUCTOR).asMethod
 *   ctorC: reflect.runtime.universe.MethodSymbol = constructor C
 *
 *   scala> val ctorm = cm.reflectConstructor(ctorC)
 *   ctorm: reflect.runtime.universe.MethodMirror = constructor mirror for C.<init>(x: scala.Int): C (bound to null)
 *
 *   scala> ctorm(2)
 *   res0: Any = C(2)
 * }}}
 *
 * '''[[scala.reflect.api.Mirrors#ModuleMirror]]'''. Used for getting singleton instances of objects.
 * Entry points: for ''static objects (modules)'' `val mm1 = m.reflectModule(<module symbol>)`,
 * for ''inner objects (modules)'' `val mm2 = im.reflectModule(<module symbol>)`.
 * Example:
 * {{{
 *   scala> object C { def x = 2 }
 *   defined module C
 *
 *   scala> val m = ru.runtimeMirror(getClass.getClassLoader)
 *   m: reflect.runtime.universe.Mirror = JavaMirror ...
 *
 *   scala> val objectC = typeOf[C.type].termSymbol.asModule
 *   objectC: reflect.runtime.universe.ModuleSymbol = object C
 *
 *   scala> val mm = m.reflectModule(objectC)
 *   mm: reflect.runtime.universe.ModuleMirror = module mirror for C (bound to null)
 *
 *   scala> val obj = mm.instance
 *   obj: Any = C$@1005ec04
 * }}}
 *
 * For more information about `Mirrors`s, see the
 * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
 *
 *  @contentDiagram hideNodes "*Api"
 *  @group ReflectionAPI
 */
trait Mirrors { self: Universe =>

  /** The base type of all mirrors of this universe.
   *
   *  This abstract type conforms the base interface for all mirrors defined in [[scala.reflect.api.Mirror]]
   *  and is gradually refined in specific universes (e.g. `Mirror` of a [[scala.reflect.api.JavaUniverse]] is capable of reflection).
   *  @group Mirrors
   */
  type Mirror >: Null <: scala.reflect.api.Mirror[self.type]

  /** The root mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`,
   *  `Nothing`, `Null`, and all classes loaded from scala-library, which are shared across all mirrors within the enclosing universe.
   *  @group Mirrors
   */
  val rootMirror: Mirror

  /** Abstracts the runtime representation of a class on the underlying platform.
   *  @group Mirrors
   */
  type RuntimeClass >: Null

  // todo. an improvement might be having mirrors reproduce the structure of the reflection domain
  // e.g. a ClassMirror could also have a list of fields, methods, constructors and so on
  // read up more on the proposed design in "Reflecting Scala" by Y. Coppel

  /** A mirror that reflects a runtime value.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait InstanceMirror {

    /** The instance value reflected by this mirror */
    def instance: Any

    /** The symbol corresponding to the runtime class of the reflected instance */
    def symbol: ClassSymbol

    /** Reflects against a field symbol and returns a mirror
     *  that can be used to get and, if appropriate, set the value of the field.
     *
     *  FieldMirrors are the only way to get at private[this] vals and vars and
     *  might be useful to inspect the data of underlying Java fields.
     *  For all other uses, it's better to go through the fields accessor.
     *
     *  In particular, there should be no need to ever access a field mirror
     *  when reflecting on just the public members of a class or trait.
     *  Note also that only accessor MethodMirrors, but not FieldMirrors will accurately reflect overriding behavior.
     *
     *  To get a field symbol by the name of the field you would like to reflect,
     *  use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the field>)).asTerm.accessed`.
     *  For further information about member lookup refer to `Symbol.typeSignature`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be a member (declared or inherited) of the class of the instance underlying this mirror.
     *
     *  The input symbol can represent either a field itself or one of the corresponding accessors
     *  (in all cases the resulting mirror will refer to the field symbol).
     *
     *  If a field symbol doesn't correspond to a reflectable entity of the underlying platform,
     *  a `ScalaReflectionException` exception will be thrown. This might happen, for example, for primary constructor parameters.
     *  Typically they produce class fields, however, private parameters that aren't used outside the constructor
     *  remain plain parameters of a constructor method of the class.
     */
    def reflectField(field: TermSymbol): FieldMirror

    /** Reflects against a method symbol and returns a mirror
     *  that can be used to invoke the method provided.
     *
     *  To get a method symbol by the name of the method you would like to reflect,
     *  use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the method>)).asMethod`.
     *  For further information about member lookup refer to `Symbol.typeSignature`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be a member (declared or inherited) of the instance underlying this mirror.
     */
    def reflectMethod(method: MethodSymbol): MethodMirror

    /** Reflects against an inner class symbol and returns a mirror
     *  that can be used to create instances of the class, inspect its companion object or perform further reflections.
     *
     *  To get a class symbol by the name of the class you would like to reflect,
     *  use `<this mirror>.symbol.typeSignature.member(newTypeName(<name of the class>)).asClass`.
     *  For further information about member lookup refer to `Symbol.typeSignature`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be a member (declared or inherited) of the instance underlying this mirror.
     */
    def reflectClass(cls: ClassSymbol): ClassMirror

    /** Reflects against an inner module symbol and returns a mirror
     *  that can be used to get the instance of the object or inspect its companion class.
     *
     *  To get a module symbol by the name of the object you would like to reflect,
     *  use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the object>)).asModule`.
     *  For further information about member lookup refer to `Symbol.typeSignature`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be a member (declared or inherited) of the instance underlying this mirror.
     */
    def reflectModule(mod: ModuleSymbol): ModuleMirror
  }

  /** A mirror that reflects a field.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait FieldMirror {

    /** The object containing the field */
    def receiver: Any

    /** The field symbol representing the field.
     *
     *  In Scala `val` and `var` declarations are usually compiled down to a pair of
     *  a backing field and corresponding accessor/accessors, which means that a single
     *  declaration might correspond to up to three different symbols. Nevertheless
     *  the `FieldMirror.symbol` field always points to a backing field symbol.
     */
    def symbol: TermSymbol

    /** Retrieves the value stored in the field.
     *
     *  Scala reflection uses reflection capabilities of the underlying platform,
     *  so `FieldMirror.get` might throw platform-specific exceptions associated
     *  with getting a field or invoking a getter method of the field.
     *
     *  If `symbol` represents a field of a base class with respect to the class of the receiver,
     *  and this base field is overriden in the class of the receiver, then this method will retrieve
     *  the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor.
     */
    def get: Any

    /** Updates the value stored in the field.
     *
     *  If a field is immutable, a `ScalaReflectionException` will be thrown.
     *
     *  Scala reflection uses reflection capabilities of the underlying platform,
     *  so `FieldMirror.get` might throw platform-specific exceptions associated
     *  with setting a field or invoking a setter method of the field.
     *
     *  If `symbol` represents a field of a base class with respect to the class of the receiver,
     *  and this base field is overriden in the class of the receiver, then this method will set
     *  the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor.
     */
    def set(value: Any): Unit

    /** Creates a new mirror which uses the same symbol, but is bound to a different receiver.
     *  This is significantly faster than recreating the mirror from scratch.
     */
    def bind(newReceiver: Any): FieldMirror
  }

  /** A mirror that reflects a method.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait MethodMirror {

    /** The receiver object of the method */
    def receiver: Any

    /** The method symbol representing the method */
    def symbol: MethodSymbol

    /** The result of applying the method to the given arguments
     *
     *  Scala reflection uses reflection capabilities of the underlying platform,
     *  so `FieldMirror.get` might throw platform-specific exceptions associated
     *  with invoking the corresponding method or constructor.
     */
    def apply(args: Any*): Any

    /** Creates a new mirror which uses the same symbol, but is bound to a different receiver.
     *  This is significantly faster than recreating the mirror from scratch.
     */
    def bind(newReceiver: Any): MethodMirror
  }

  /** A mirror that reflects the instance or static parts of a runtime class.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait TemplateMirror {

    /** True if the mirror represents the static part
     *  of a runtime class or the companion object of a Scala class.
     *  One has:
     *
     *    this.isStatic == this.isInstanceOf[ModuleMirror]
     *    !this.isStatic == this.isInstanceOf[ClassMirror]
     */
    def isStatic: Boolean

    /** The Scala symbol corresponding to the reflected runtime class or object */
    def symbol: Symbol
  }

  /** A mirror that reflects a Scala object definition or the static parts of a runtime class.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait ModuleMirror extends TemplateMirror {

    /** The Scala module symbol corresponding to the reflected object */
    override def symbol: ModuleSymbol

    /** If the reflected runtime class corresponds to a Scala object definition,
     *  returns the single instance representing that object.
     *  If this mirror reflects the static part of a runtime class, returns `null`.
     */
    def instance: Any
  }

  /** A mirror that reflects the instance parts of a runtime class.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait ClassMirror extends TemplateMirror {

    /** The Scala class symbol corresponding to the reflected class */
    override def symbol: ClassSymbol

    /** Reflects against a constructor symbol and returns a mirror
     *  that can be used to invoke it and construct instances of this mirror's symbols.
     *
     *  To get a constructor symbol you would like to reflect,
     *  use `<this mirror>.symbol.typeSignature.member(nme.CONSTRUCTOR).asMethod`.
     *  For further information about member lookup refer to `Symbol.typeSignature`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be a member (declared or inherited) of the class underlying this mirror.
     */
    def reflectConstructor(constructor: MethodSymbol): MethodMirror
  }

  /** A mirror that reflects instances and static classes.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait ReflectiveMirror extends scala.reflect.api.Mirror[Mirrors.this.type] {

    /** A reflective mirror for the given object.
     *
     *  Such a mirror can be used to further reflect against the members of the object
     *  to get/set fields, invoke methods and inspect inner classes and objects.
     */
    // we need a ClassTag here to preserve boxity of primitives
    // the class tag lets us tell apart `mirror.reflect(2)` and `mirror.reflect(new Integer(2))`
    def reflect[T: ClassTag](obj: T): InstanceMirror

    /** Reflects against a static class symbol and returns a mirror
     *  that can be used to create instances of the class, inspect its companion object or perform further reflections.
     *
     *  To get a class symbol by the name of the class you would like to reflect,
     *  use `<this mirror>.classSymbol(<runtime class loaded by its name>)`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be static, i.e. either top-level or nested within one or several static objects.
     */
    def reflectClass(cls: ClassSymbol): ClassMirror

    /** Reflects against a static module symbol and returns a mirror
     *  that can be used to get the instance of the object or inspect its companion class.
     *
     *  To get a module symbol by the name of its companion class you would like to reflect,
     *  use `<this mirror>.classSymbol(<runtime class loaded by its name>).companion.get`.
     *
     *  The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
     *  It must be static, i.e. either top-level or nested within one or several static objects.
     */
    def reflectModule(mod: ModuleSymbol): ModuleMirror
  }

  /** The API of a mirror for a reflective universe.
   *  See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
   *  @group Mirrors
   */
  trait RuntimeMirror extends ReflectiveMirror { self =>

    /** Maps a Scala type to the corresponding Java class object */
    def runtimeClass(tpe: Type): RuntimeClass

    /** Maps a Scala class symbol to the corresponding Java class object
     *  @throws ClassNotFoundException if there is no Java class
     *          corresponding to the given Scala class symbol.
     *  Note: If the Scala symbol is ArrayClass, a ClassNotFound exception is thrown
     *        because there is no unique Java class corresponding to a Scala generic array
     */
    def runtimeClass(cls: ClassSymbol): RuntimeClass

    /** A class symbol for the specified runtime class.
     *  @return The class symbol for the runtime class in the current class loader.
     *  @throws java.lang.ClassNotFoundException if no class with that name exists
     *  @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists
     *  to do: throws anything else?
     */
    def classSymbol(rtcls: RuntimeClass): ClassSymbol

    /** A module symbol for the specified runtime class.
     *  @return The module symbol for the runtime class in the current class loader.
     *  @throws java.lang.ClassNotFoundException if no class with that name exists
     *  @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists
     *  to do: throws anything else?
     */
    def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol
  }
}