summaryrefslogtreecommitdiff
path: root/src/dotnet-library/scala/reflect/Manifest.scala
blob: 125c1ed73efd77e74f7d639ea8e8a1b36524cbe2 (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
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2007-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.reflect

/** <p>
  *   A <code>Manifest[T]</code> is an opaque descriptor for type <code>T</code>.
  *   Currently, its only use is to give access to the erasure of the type as a
  *   <code>Class</code> instance.
  * </p>
  * <p>
  *   <b>BE AWARE</b>: The different type-relation operators are all forwarded
  *   to the erased type as an approximation of the final semantics where
  *   these operators should be on the unerased type.
  * </p>
  */
trait Manifest[T] {

  /** A class representing the type U to which T would be erased. Note
    * that there is no subtyping relationship between T and U. */
  def erasure: Predef.Class[U] forSome { type U }

  /** Tests whether the type represented by this manifest is a subtype of
    * the type represented by `that' manifest. BE AWARE: the current
    * implementation is an approximation, as the test is done on the
    * erasure of the type. */
  def <:<(that: Manifest[_]): Boolean = {
    def subtype(sub: Predef.Class[_], sup: Predef.Class[_]): Boolean = {
      val subSuperClass = sub.BaseType
      val subSuperInterfaces = sub.GetInterfaces.toList
      val subSuper =
        (if (subSuperClass == null) Nil else List(subSuperClass)) ::: subSuperInterfaces
      (subSuper contains sup) || (subSuper exists (subtype(_, sup)))
    }
    this.erasure == that.erasure || subtype(this.erasure, that.erasure)
  }

  /** Tests whether the type represented by this manifest is a supertype
    * of the type represented by `that' manifest. BE AWARE: the current
    * implementation is an approximation, as the test is done on the
    * erasure of the type. */
  def >:>(that: Manifest[_]): Boolean =
    that <:< this

  /** Tests whether the type represented by this manifest is equal to the
    * type represented by `that' manifest. BE AWARE: the current
    * implementation is an approximation, as the test is done on the
    * erasure of the type. */
  override def equals(that: Any): Boolean = that match {
    case m:Manifest[_] => this.erasure == m.erasure
    case _ => false
  }

}

/** <p>
  *   This object is used by the compiler and <b>should not be used in client
  *   code</b>. The object <code>Manifest</code> defines factory methods for
  *   manifests.
  * </p>
  * <p>
  *   <b>BE AWARE</b>: The factory for refinement types is missing and
  *   will be implemented in a later version of this class.
  * </p>
  */
object Manifest {

  /** Manifest for the singleton type `value.type'. */
  def singleType[T](value: Any): Manifest[T] =
    new Manifest[T] {
      lazy val erasure =
        value match {
          case anyRefValue: AnyRef => anyRefValue.GetType
          case anyValue => error("There is no singleton type for AnyVal values")
        }
      override lazy val toString = value.toString + ".type"
    }

  /** Manifest for the class type `clazz', where `clazz' is
    * a top-level or static class. */
  def classType[T](clazz: Predef.Class[T]): Manifest[T] =
    new Manifest[T] {
      val erasure = clazz
      override lazy val toString = erasure.getName
    }

  /** Manifest for the class type `clazz[args]', where `clazz' is
    * a top-level or static class. */
  def classType[T](clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
    new Manifest[T] {
      val erasure = clazz
      val typeArguments: Seq[Manifest[_]] = args
      override lazy val toString = erasure.getName + typeArguments.mkString("[", ", ", "]")
    }

  /** Manifest for the class type `prefix # clazz'. */
  def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] =
    new Manifest[T] {
      val erasure = clazz
      override lazy val toString = prefix.toString + "#" + clazz.getName
    }

  /** Manifest for the class type `prefix # clazz[args]'. */
  def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
    new Manifest[T] {
      val erasure = clazz
      val typeArguments: Seq[Manifest[_]] = args
      override lazy val toString = prefix.toString + "#" + clazz.getName + typeArguments.mkString("[", ", ", "]")
    }

  /** Manifest for the abstract type `prefix # name'. `upperBound' is not
    * strictly necessary as it could be obtained by reflection. It was
    * added so that erasure can be calculated without reflection. */
  def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_]): Manifest[T] =
    new Manifest[T] {
      lazy val erasure = upperBound.erasure
      override lazy val toString = prefix.toString + "#" + name
    }

  /** Manifest for the abstract type `prefix # name[args]'. */
  def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] =
    new Manifest[T] {
      lazy val erasure = upperBound.erasure
      val typeArguments: Seq[Manifest[_]] = args
      override lazy val toString = prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]")
    }

  /** Manifest for the intersection type `parents_0 with ... with parents_n'. */
  def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
    new Manifest[T] {
      lazy val erasure = parents.first.erasure
      override lazy val toString = parents.mkString(" with ")
    }

}