summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala
blob: f1fe4fc118d7a185bacc327cba819802828248ba (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
/* NSC -- new scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  Martin Odersky
 */

package scala.reflect
package internal

import scala.collection.{ mutable, immutable }
import util._

/** The name of this trait defines the eventual intent better than
 *  it does the initial contents.
 */
trait ExistentialsAndSkolems {
  self: SymbolTable =>

  /** Map a list of type parameter symbols to skolemized symbols, which
   *  can be deskolemized to the original type parameter. (A skolem is a
   *  representation of a bound variable when viewed inside its scope.)
   *  !!!Adriaan: this does not work for hk types.
   */
  def deriveFreshSkolems(tparams: List[Symbol]): List[Symbol] = {
    class Deskolemizer extends LazyType {
      override val typeParams = tparams
      val typeSkolems  = typeParams map (_.newTypeSkolem setInfo this)
      override def complete(sym: Symbol) {
        // The info of a skolem is the skolemized info of the
        // actual type parameter of the skolem
        sym setInfo sym.deSkolemize.info.substSym(typeParams, typeSkolems)
      }
    }
    (new Deskolemizer).typeSkolems
  }

  /** Convert to corresponding type parameters all skolems of method
   *  parameters which appear in `tparams`.
   */
  def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
    class DeSkolemizeMap extends TypeMap {
      def apply(tp: Type): Type = tp match {
        case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
          mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
        case _ =>
          mapOver(tp)
      }
    }
    new DeSkolemizeMap mapOver tp
  }
}