summaryrefslogblamecommitdiff
path: root/src/reflect/scala/reflect/api/Types.scala
blob: 060b0657b166eb71810b0a3b84fc6e18808efaf3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12


                     

                                                                                                                    
  





                                                                                                                     
  























































































                                                                                                                                                       











                                                                                 
 


                                                                                             
 


                                                                                                  
     

                    

                                                                                         

                          








                                                                         
 
                                                                      




                                                                                




                                                                       
       
                                 
 


                                                                          
                                  
 




                                                                                       
       
                            
 

                                                                           
                              
 



                                                                                          







                                                                              
                       



                                                                



                                                                                                      


                                                                 
                                                                                


                                                                                 
                                 
















                                                                          
           



                                                               
           



                                                        
                                                                   
       
                     
 

                                                                                     
                                                                  
      
                
      




                                          
 




























                                                                                              

   









































                                                                                          
 


                                                                                         
                                                       
                                       
                   

   

























                                                                                              
 


                                                                                         
                                                           
                                     
                 

                                 
                   
   

















                                                                                      
 





                                                                                                    
 


                                                                                         
                                                         


                                                                       
                     



                                                                       
                      
   












                                                                                                             
 









                                                                                         
 


                                                                                         
                                                               
                                                          
                       

   





























                                                                                                             
 


                                                                                         
                                                     


                                                               
                 

                                                       
                   



                                                            
                        

   







































                                                                                                           
 


                                                                                         
                                                             
                                        
                           

                                                                    
                    
   
 




























                                                                                                   
 


                                                                                         
                                                                 
                                              
                           

                                                                          
                    

                                                

                          
 





























                                                                                                      
 


                                                                                         
                                                           
                                                                       
                            

                                         
                        
   
 



















                                                                                                 
 


                                                                                         
                                                                         
                                         

                        
 




















                                                                                                    
 


                                                                                         
                                                       
                                                            
                                

                               
                        

   





















                                                                                              
 


                                                                                         
                                                                     
                                                                                      
                                

                                                       
                        

   





















                                                                                              
 


                                                                                         
                                                                 
                           
                                     

                       
                        

                                                              
                       

   



























                                                                                          
 


                                                                                         
                                                           


                                                                         
                



                                                                     
                

   































                                                                                                       
 


                                                                                         
                                                                             
                                             
                          
   
 
                                                                           

                               
                                                                               
                               


                                                                             







                                                                                        





























                                                                                                                      


                              
    
                                                                                 



                                                                        

                                                                            





                                                                          
 
package scala.reflect
package api

/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines types and operations on them.
 *  See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern.
 *
 *  While [[scala.reflect.api.Symbols symbols]] establish the structure of the program by representing the hierarchy
 *  of definitions, types bring meaning to symbols. A type is not, say, `Int` -- that's just its symbol
 *  (assuming we are talking about `scala.Int`, and not just the name). A type is the information about all members
 *  that compose that thing: methods, fields, type parameters, nested classes and traits, etc. If a symbol represents
 *  a definition, a type represents the whole structure of that definition. It is the union of all definitions that
 *  compose a class, the description of what goes into a method and what comes out, etc.
 *
 *  === Instantiating types ===
 *
 *  There are three ways to instantiate types. The simplest one involves the [[scala.reflect.api.TypeTags#typeOf]] method,
 *  which takes a type argument and produces a `Type` instance that represents that argument. For example, `typeOf[List[Int]]`
 *  produces a [[scala.reflect.api.Types#TypeRef]], which corresponds to a type `List` applied to a type argument `Int`.
 *  When type parameters are involved (as, for example, in `typeOf[List[A]]`), `typeOf` won't work, and one should use
 *  [[scala.reflect.api.TypeTags#weakTypeOf]] instead. Refer to [[scala.reflect.api.TypeTags the type tags page]] to find out
 *  more about this distinction.
 *
 *  `typeOf` requires spelling out a type explicitly, but there's also a way to capture types implicitly with the [[scala.reflect.api.TypeTag#TypeTag]]
 *  context bound. Once a type parameter `T` is annotated with the `TypeTag` context bound, the for each usage of the enclosing class or method,
 *  the compiler will automatically produce a `Type` evidence, available via `typeTag[T]`. For example, inside a method
 *  `def test[T: TypeTag](x: T) = ...` one can use `typeTag[T]` to obtain the information about the exact type of `x` passed into that method.
 *  Similarly to the situation `typeOf`, sometimes `typeTag` does not work, and one has to use `weakTypeTag`.
 *  [[scala.reflect.api.TypeTags The type tags page]] tells more about this feature.
 *
 *  Finally types can be instantiated manually using factory methods such as `typeRef` or `polyType`.
 *  This is necessary only in cases when `typeOf` or `typeTag` cannot be applied, because the type cannot be spelt out
 *  in a Scala snippet, usually when writing macros. Manual construction requires deep knowledge of Scala compiler internals
 *  and shouldn't be used, when there are other alternatives available.
 *
 *  === Using types ===
 *
 *  Arguably the most useful application of types is looking up members. Every type has `members` and `declarations` methods (along with
 *  their singular counterparts `member` and `declaration`), which provide the list of definitions associated with that type.
 *  For example, to look up the `map` method of `List`, one could write `typeOf[List[_]].member("map": TermName)`, getting a `MethodSymbol`
 *
 *  Another popular use case is doing subtype tests. Types expose `<:<` and `weak_<:<` methods for that purpose. The latter is
 *  an extension of the former - it also works with numeric types (for example, `Int <:< Long` is false, but `Int weak_<:< Long` is true).
 *  Unlike the subtype tests implemented by manifests, tests provided by `Type`s are aware of all the intricacies of the Scala type system
 *  and work correctly even for involved types.
 *
 *  Finally a word must be said about equality of types. Due to an implementation detail, the vanilla `==` method should not be used
 *  to compare types for equality, as it might work in some circumstances and fizzle under conditions that are slightly different.
 *  Instead one should always use the `=:=` method. As an added bonus, `=:=` also knows about type aliases, e.g.
 *  `typeOf[scala.List[_]] =:= typeOf[scala.collection.immutable.List[_]]`.
 *
 *  === Exploring types ===
 *
 *  {{{
 *  scala> import scala.reflect.runtime.universe._
 *  import scala.reflect.runtime.universe._
 *
 *  scala> typeOf[List[_]].members.sorted take 5 foreach println
 *  constructor List
 *  method companion
 *  method ::
 *  method :::
 *  method reverse_:::
 *
 *  scala> def test[T: TypeTag](x: T) = s"I've been called for an x typed as ${typeOf[T]}"
 *  test: [T](x: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])String
 *
 *  scala> test(2)
 *  res0 @ 3fc80fae: String = I've been called for an x typed as Int
 *
 *  scala> test(List(2, "x"))
 *  res1 @ 10139edf: String = I've been called for an x typed as List[Any]
 *  }}}
 *
 *  === How to get an internal representation of a type? ===
 *
 *  The `toString` method on types is designed to print a close-to-Scala representation
 *  of the code that a given type represents. This is usually convenient, but sometimes
 *  one would like to look under the covers and see what exactly are the elements that
 *  constitute a certain type.
 *
 *  Scala reflection provides a way to dig deeper through [[scala.reflect.api.Printers]]
 *  and their `showRaw` method. Refer to the page linked above for a series of detailed
 *  examples.
 *
 *  {{{
 *  scala> import scala.reflect.runtime.universe._
 *  import scala.reflect.runtime.universe._
 *
 *  scala> def tpe = typeOf[{ def x: Int; val y: List[Int] }]
 *  tpe: reflect.runtime.universe.Type
 *
 *  scala> show(tpe)
 *  res0: String = scala.AnyRef{def x: Int; val y: scala.List[Int]}
 *
 *  scala> showRaw(tpe)
 *  res1: String = RefinedType(
 *    List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())),
 *    Scope(
 *      newTermName("x"),
 *      newTermName("y")))
 *  }}}
 */
trait Types { self: Universe =>

  /** The type of Scala types, and also Scala type signatures.
   *  (No difference is internally made between the two).
   */
  type Type >: Null <: TypeApi

  /** A tag that preserves the identity of the `Type` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val TypeTagg: ClassTag[Type]

  /** This constant is used as a special value that indicates that no meaningful type exists.
   */
  val NoType: Type

  /** This constant is used as a special value denoting the empty prefix in a path dependent type.
   *  For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for
   *  the symbol for `x`.
   */
  val NoPrefix: Type

  /** The API of types.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  abstract class TypeApi {
    /** The term symbol associated with the type, or `NoSymbol` for types
     *  that do not refer to a term symbol.
     */
    def termSymbol: Symbol

    /** The type symbol associated with the type, or `NoSymbol` for types
     *  that do not refer to a type symbol.
     */
    def typeSymbol: Symbol

    /** The defined or declared members with name `name` in this type;
     *  an OverloadedSymbol if several exist, NoSymbol if none exist.
     *  Alternatives of overloaded symbol appear in the order they are declared.
     */
    def declaration(name: Name): Symbol

    /** A `Scope` containing directly declared members of this type.
     *  Unlike `members` this method doesn't returns inherited members.
     *
     *  Members in the returned scope might appear in arbitrary order.
     *  Use `declarations.sorted` to get an ordered list of members.
     */
    def declarations: MemberScope

    /** The member with given name, either directly declared or inherited,
     *  an OverloadedSymbol if several exist, NoSymbol if none exist.
     */
    def member(name: Name): Symbol

    /** A `Scope` containing all members of this type (directly declared or inherited).
     *  Unlike `declarations` this method also returns inherited members.
     *
     *  Members in the returned scope might appear in arbitrary order.
     *  Use `declarations.sorted` to get an ordered list of members.
     */
    def members: MemberScope

    /** Is this type a type constructor that is missing its type arguments?
     */
    def takesTypeArgs: Boolean

    /** Returns the corresponding type constructor (e.g. List for List[T] or List[String])
     */
    def typeConstructor: Type

    /**
     *  Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
     *  Functions on types are also implemented as PolyTypes.
     *
     *  Example: (in the below, <List> is the type constructor of List)
     *    TypeRef(pre, <List>, List()) is replaced by
     *    PolyType(X, TypeRef(pre, <List>, List(X)))
     */
    def normalize: Type

    /** Does this type conform to given type argument `that`? */
    def <:< (that: Type): Boolean

    /** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
     */
    def weak_<:<(that: Type): Boolean

    /** Is this type equivalent to given type argument `that`? */
    def =:= (that: Type): Boolean

    /** The list of all base classes of this type (including its own typeSymbol)
     *  in reverse linearization order, starting with the class itself and ending
     *  in class Any.
     */
    def baseClasses: List[Symbol]

    /** The least type instance of given class which is a supertype
     *  of this type.  Example:
     *  {{{
     *    class D[T]
     *    class C extends p.D[Int]
     *    ThisType(C).baseType(D) = p.D[Int]
     * }}}
     */
    def baseType(clazz: Symbol): Type

    /** This type as seen from prefix `pre` and class `clazz`. This means:
     *  Replace all thistypes of `clazz` or one of its subclasses
     *  by `pre` and instantiate all parameters by arguments of `pre`.
     *  Proceed analogously for thistypes referring to outer classes.
     *
     *  Example:
     *  {{{
     *    class D[T] { def m: T }
     *    class C extends p.D[Int]
     *    T.asSeenFrom(ThisType(C), D)  (where D is owner of m)
     *      = Int
     *  }}}
     */
    def asSeenFrom(pre: Type, clazz: Symbol): Type

    /** The erased type corresponding to this type after
     *  all transformations from Scala to Java have been performed.
     */
    def erasure: Type

    /** If this is a singleton type, widen it to its nearest underlying non-singleton
     *  base type by applying one or more `underlying` dereferences.
     *  If this is not a singleton type, returns this type itself.
     *
     *  Example:
     *
     *  class Outer { class C ; val x: C }
     *  val o: Outer
     *  <o.x.type>.widen = o.C
     */
    def widen: Type

    /******************* helpers *******************/

    /** Substitute symbols in `to` for corresponding occurrences of references to
     *  symbols `from` in this type.
     */
    def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type

    /** Substitute types in `to` for corresponding occurrences of references to
     *  symbols `from` in this type.
     */
    def substituteTypes(from: List[Symbol], to: List[Type]): Type

   /** Apply `f` to each part of this type, returning
    *  a new type. children get mapped before their parents */
    def map(f: Type => Type): Type

    /** Apply `f` to each part of this type, for side effects only */
    def foreach(f: Type => Unit)

    /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`,
     *  or None if none exists.
     */
    def find(p: Type => Boolean): Option[Type]

    /** Is there part of this type which satisfies predicate `p`? */
    def exists(p: Type => Boolean): Boolean

    /** Does this type contain a reference to given symbol? */
    def contains(sym: Symbol): Boolean
  }

  /** The type of Scala singleton types, i.e., types that are inhabited
   *  by only one nun-null value. These include types of the forms
   *  {{{
   *    C.this.type
   *    C.super.type
   *    x.type
   *  }}}
   *  as well as [[ConstantType constant types]].
   */
  type SingletonType >: Null <: Type

  /** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val SingletonTypeTag: ClassTag[SingletonType]

  /** A singleton type that describes types of the form on the left with the
   *  corresponding `ThisType` representation to the right:
   *  {{{
   *     C.this.type             ThisType(C)
   *  }}}
   */
  type ThisType >: Null <: AnyRef with SingletonType with ThisTypeApi

  /** A tag that preserves the identity of the `ThisType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val ThisTypeTag: ClassTag[ThisType]

  /** The constructor/deconstructor for `ThisType` instances. */
  val ThisType: ThisTypeExtractor

  /** An extractor class to create and pattern match with syntax `ThisType(sym)`
   *  where `sym` is the class prefix of the this type.
   */
  abstract class ThisTypeExtractor {
    /**
     * Creates a ThisType from the given class symbol.
     */
    def apply(sym: Symbol): Type
    def unapply(tpe: ThisType): Option[Symbol]
  }

  /** The API that all this types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait ThisTypeApi extends TypeApi { this: ThisType =>
    /** The underlying class symbol. */
    val sym: Symbol
  }

  /** The `SingleType` type describes types of any of the forms on the left,
   *  with their TypeRef representations to the right.
   *  {{{
   *     (T # x).type             SingleType(T, x)
   *     p.x.type                 SingleType(p.type, x)
   *     x.type                   SingleType(NoPrefix, x)
   *  }}}
   */
  type SingleType >: Null <: AnyRef with SingletonType with SingleTypeApi

  /** A tag that preserves the identity of the `SingleType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val SingleTypeTag: ClassTag[SingleType]

  /** The constructor/deconstructor for `SingleType` instances. */
  val SingleType: SingleTypeExtractor

  /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)`
   *  Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol
   *  referred to by the single-type.
   */
  abstract class SingleTypeExtractor {
    def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details
    def unapply(tpe: SingleType): Option[(Type, Symbol)]
  }

  /** The API that all single types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait SingleTypeApi extends TypeApi { this: SingleType =>
    /** The type of the qualifier. */
    val pre: Type

    /** The underlying symbol. */
    val sym: Symbol
  }
  /** The `SuperType` type is not directly written, but arises when `C.super` is used
   *  as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is
   *  {{{
   *     SuperType(thistpe, supertpe)
   *  }}}
   *  Here, `thistpe` is the type of the corresponding this-type. For instance,
   *  in the type arising from C.super, the `thistpe` part would be `ThisType(C)`.
   *  `supertpe` is the type of the super class referred to by the `super`.
   */
  type SuperType >: Null <: AnyRef with SingletonType with SuperTypeApi

  /** A tag that preserves the identity of the `SuperType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val SuperTypeTag: ClassTag[SuperType]

  /** The constructor/deconstructor for `SuperType` instances. */
  val SuperType: SuperTypeExtractor

  /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)`
   */
  abstract class SuperTypeExtractor {
    def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details
    def unapply(tpe: SuperType): Option[(Type, Type)]
  }

  /** The API that all super types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait SuperTypeApi extends TypeApi { this: SuperType =>
    /** The type of the qualifier.
     *  See the example for [[scala.reflect.api.Trees#SuperExtractor]].
     */
    val thistpe: Type

    /** The type of the selector.
     *  See the example for [[scala.reflect.api.Trees#SuperExtractor]].
     */
    val supertpe: Type
  }
  /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant.
   *  The REPL expresses constant types like `Int(11)`. Here are some constants with their types:
   *  {{{
   *     1           ConstantType(Constant(1))
   *     "abc"       ConstantType(Constant("abc"))
   *  }}}
   */
  type ConstantType >: Null <: AnyRef with SingletonType with ConstantTypeApi

  /** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val ConstantTypeTag: ClassTag[ConstantType]

  /** The constructor/deconstructor for `ConstantType` instances. */
  val ConstantType: ConstantTypeExtractor

  /** An extractor class to create and pattern match with syntax `ConstantType(constant)`
   *  Here, `constant` is the constant value represented by the type.
   */
  abstract class ConstantTypeExtractor {
    def apply(value: Constant): ConstantType
    def unapply(tpe: ConstantType): Option[Constant]
  }

  /** The API that all constant types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait ConstantTypeApi extends TypeApi { this: ConstantType =>
    /** The compile-time constant underlying this type. */
    val value: Constant
  }

  /** The `TypeRef` type describes types of any of the forms on the left,
   *  with their TypeRef representations to the right.
   *  {{{
   *     T # C[T_1, ..., T_n]      TypeRef(T, C, List(T_1, ..., T_n))
   *     p.C[T_1, ..., T_n]        TypeRef(p.type, C, List(T_1, ..., T_n))
   *     C[T_1, ..., T_n]          TypeRef(NoPrefix, C, List(T_1, ..., T_n))
   *     T # C                     TypeRef(T, C, Nil)
   *     p.C                       TypeRef(p.type, C, Nil)
   *     C                         TypeRef(NoPrefix, C, Nil)
   *  }}}
   */
  type TypeRef >: Null <: AnyRef with Type with TypeRefApi

  /** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val TypeRefTag: ClassTag[TypeRef]

  /** The constructor/deconstructor for `TypeRef` instances. */
  val TypeRef: TypeRefExtractor

  /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)`
   *  Here, `pre` is the prefix of the type reference, `sym` is the symbol
   *  referred to by the type reference, and `args` is a possible empty list of
   *  type argumenrts.
   */
  abstract class TypeRefExtractor {
    def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details
    def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])]
  }

  /** The API that all type refs support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait TypeRefApi extends TypeApi { this: TypeRef =>
    /** The prefix of the type reference.
     *  Is equal to `NoPrefix` if the prefix is not applicable.
     */
    val pre: Type

    /** The underlying symbol of the type reference. */
    val sym: Symbol

    /** The arguments of the type reference.
     *  Is equal to `Nil` if the arguments are not provided.
     */
    val args: List[Type]
  }

  /** A subtype of Type representing refined types as well as `ClassInfo` signatures.
   */
  type CompoundType >: Null <: AnyRef with Type

  /** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val CompoundTypeTag: ClassTag[CompoundType]

  /** The `RefinedType` type defines types of any of the forms on the left,
   *  with their RefinedType representations to the right.
   *  {{{
   *     P_1 with ... with P_m { D_1; ...; D_n}      RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n))
   *     P_1 with ... with P_m                       RefinedType(List(P_1, ..., P_m), Scope())
   *     { D_1; ...; D_n}                            RefinedType(List(AnyRef), Scope(D_1, ..., D_n))
   *  }}}
   */
  type RefinedType >: Null <: AnyRef with CompoundType with RefinedTypeApi

  /** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val RefinedTypeTag: ClassTag[RefinedType]

  /** The constructor/deconstructor for `RefinedType` instances. */
  val RefinedType: RefinedTypeExtractor

  /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)`
   *  Here, `parents` is the list of parent types of the class, and `decls` is the scope
   *  containing all declarations in the class.
   */
  abstract class RefinedTypeExtractor {
    def apply(parents: List[Type], decls: Scope): RefinedType

    /** An alternative constructor that passes in the synthetic classs symbol
     *  that backs the refined type. (Normally, a fresh class symbol is created automatically).
     */
    def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType
    def unapply(tpe: RefinedType): Option[(List[Type], Scope)]
  }

  /** The API that all refined types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait RefinedTypeApi extends TypeApi { this: RefinedType =>
    /** The superclasses of the type. */
    val parents: List[Type]

    /** The scope that holds the definitions comprising the type. */
    val decls: Scope
  }

  /** The `ClassInfo` type signature is used to define parents and declarations
   *  of classes, traits, and objects. If a class, trait, or object C is declared like this
   *  {{{
   *     C extends P_1 with ... with P_m { D_1; ...; D_n}
   *  }}}
   *  its `ClassInfo` type has the following form:
   *  {{{
   *     ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C)
   *  }}}
   */
  type ClassInfoType >: Null <: AnyRef with CompoundType with ClassInfoTypeApi

  /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]

  /** The constructor/deconstructor for `ClassInfoType` instances. */
  val ClassInfoType: ClassInfoTypeExtractor

  /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)`
   *  Here, `parents` is the list of parent types of the class, `decls` is the scope
   *  containing all declarations in the class, and `clazz` is the symbol of the class
   *  itself.
   */
  abstract class ClassInfoTypeExtractor {
    def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType
    def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)]
  }

  /** The API that all class info types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType =>
    /** The superclasses of the class type. */
    val parents: List[Type]

    /** The scope that holds the definitions comprising the class type. */
    val decls: Scope

    /** The symbol underlying the class type. */
    val typeSymbol: Symbol
  }

  /** The `MethodType` type signature is used to indicate parameters and result type of a method
   */
  type MethodType >: Null <: AnyRef with Type with MethodTypeApi

  /** A tag that preserves the identity of the `MethodType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val MethodTypeTag: ClassTag[MethodType]

  /** The constructor/deconstructor for `MethodType` instances. */
  val MethodType: MethodTypeExtractor

  /** An extractor class to create and pattern match with syntax `MethodType(params, respte)`
   *  Here, `params` is a potentially empty list of parameter symbols of the method,
   *  and `restpe` is the result type of the method. If the method is curried, `restpe` would
   *  be another `MethodType`.
   *  Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list.
   *  {{{
   *     def f(): Int
   *  }}}
   *  If the method is completely parameterless, as in
   *  {{{
   *     def f: Int
   *  }}}
   *  its type is a `NullaryMethodType`.
   */
  abstract class MethodTypeExtractor {
    def apply(params: List[Symbol], resultType: Type): MethodType
    def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
  }

  /** The API that all method types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait MethodTypeApi extends TypeApi { this: MethodType =>
    /** The symbols that correspond to the parameters of the method. */
    val params: List[Symbol]

    /** The result type of the method. */
    val resultType: Type
  }

  /** The `NullaryMethodType` type signature is used for parameterless methods
   *  with declarations of the form `def foo: T`
   */
  type NullaryMethodType >: Null <: AnyRef with Type with NullaryMethodTypeApi

  /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]

  /** The constructor/deconstructor for `NullaryMethodType` instances. */
  val NullaryMethodType: NullaryMethodTypeExtractor

  /** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`.
   *  Here, `resultType` is the result type of the parameterless method.
   */
  abstract class NullaryMethodTypeExtractor {
    def apply(resultType: Type): NullaryMethodType
    def unapply(tpe: NullaryMethodType): Option[(Type)]
  }

  /** The API that all nullary method types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType =>
    /** The result type of the method. */
    val resultType: Type
  }

  /** The `PolyType` type signature is used for polymorphic methods
   *  that have at least one type parameter.
   */
  type PolyType >: Null <: AnyRef with Type with PolyTypeApi

  /** A tag that preserves the identity of the `PolyType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val PolyTypeTag: ClassTag[PolyType]

  /** The constructor/deconstructor for `PolyType` instances. */
  val PolyType: PolyTypeExtractor

  /** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`.
   *  Here, `typeParams` are the type parameters of the method and `resultType`
   *  is the type signature following the type parameters.
   */
  abstract class PolyTypeExtractor {
    def apply(typeParams: List[Symbol], resultType: Type): PolyType
    def unapply(tpe: PolyType): Option[(List[Symbol], Type)]
  }

  /** The API that all polymorphic types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait PolyTypeApi extends TypeApi { this: PolyType =>
    /** The symbols corresponding to the type parameters. */
    val typeParams: List[Symbol]

    /** The underlying type. */
    val resultType: Type
  }

  /** The `ExistentialType` type signature is used for existential types and
   *  wildcard types.
   */
  type ExistentialType >: Null <: AnyRef with Type with ExistentialTypeApi

  /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val ExistentialTypeTag: ClassTag[ExistentialType]

  /** The constructor/deconstructor for `ExistentialType` instances. */
  val ExistentialType: ExistentialTypeExtractor

  /** An extractor class to create and pattern match with syntax
   *  `ExistentialType(quantified, underlying)`.
   *  Here, `quantified` are the type variables bound by the existential type and `underlying`
   *  is the type that's existentially quantified.
   */
  abstract class ExistentialTypeExtractor {
    def apply(quantified: List[Symbol], underlying: Type): ExistentialType
    def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)]
  }

  /** The API that all existential types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait ExistentialTypeApi extends TypeApi { this: ExistentialType =>
    /** The symbols corresponding to the `forSome` clauses of the existential type. */
    val quantified: List[Symbol]

    /** The underlying type of the existential type. */
    val underlying: Type
  }

  /** The `AnnotatedType` type signature is used for annotated types of the
   *  for `<type> @<annotation>`.
   */
  type AnnotatedType >: Null <: AnyRef with Type with AnnotatedTypeApi

  /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]

  /** The constructor/deconstructor for `AnnotatedType` instances. */
  val AnnotatedType: AnnotatedTypeExtractor

  /** An extractor class to create and pattern match with syntax
   * `AnnotatedType(annotations, underlying, selfsym)`.
   *  Here, `annotations` are the annotations decorating the underlying type `underlying`.
   *  `selfSym` is a symbol representing the annotated type itself.
   */
  abstract class AnnotatedTypeExtractor {
    def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType
    def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)]
  }

  /** The API that all annotated types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType =>
    /** The annotations. */
    val annotations: List[Annotation]

    /** The annotee. */
    val underlying: Type

    /** A symbol that represents the annotated type itself. */
    val selfsym: Symbol
  }

  /** The `TypeBounds` type signature is used to indicate lower and upper type bounds
   *  of type parameters and abstract types. It is not a first-class type.
   *  If an abstract type or type parameter is declared with any of the forms
   *  on the left, its type signature is the TypeBounds type on the right.
   *  {{{
   *     T >: L <: U               TypeBounds(L, U)
   *     T >: L                    TypeBounds(L, Any)
   *     T <: U                    TypeBounds(Nothing, U)
   *  }}}
   */
  type TypeBounds >: Null <: AnyRef with Type with TypeBoundsApi

  /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val TypeBoundsTag: ClassTag[TypeBounds]

  /** The constructor/deconstructor for `TypeBounds` instances. */
  val TypeBounds: TypeBoundsExtractor

  /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)`
   *  Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is
   *  the upper bound.
   */
  abstract class TypeBoundsExtractor {
    def apply(lo: Type, hi: Type): TypeBounds
    def unapply(tpe: TypeBounds): Option[(Type, Type)]
  }

  /** The API that all type bounds support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait TypeBoundsApi extends TypeApi { this: TypeBounds =>
    /** The lower bound.
     *  Is equal to `definitions.NothingTpe` if not specified explicitly.
     */
    val lo: Type

    /** The upper bound.
     *  Is equal to `definitions.AnyTpe` if not specified explicitly.
     */
    val hi: Type
  }

  /** An object representing an unknown type, used during type inference.
   *  If you see WildcardType outside of inference it is almost certainly a bug.
   */
  val WildcardType: Type

  /** BoundedWildcardTypes, used only during type inference, are created in
   *  two places:
   *
   *    1. If the expected type of an expression is an existential type,
   *       its hidden symbols are replaced with bounded wildcards.
   *    2. When an implicit conversion is being sought based in part on
   *       the name of a method in the converted type, a HasMethodMatching
   *       type is created: a MethodType with parameters typed as
   *       BoundedWildcardTypes.
   */
  type BoundedWildcardType >: Null <: AnyRef with Type with BoundedWildcardTypeApi

  /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
   *  Can be used for pattern matching, instance tests, serialization and likes.
   */
  implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]

  /** The constructor/deconstructor for `BoundedWildcardType` instances. */
  val BoundedWildcardType: BoundedWildcardTypeExtractor

  /** An extractor class to create and pattern match with syntax `BoundedWildcardTypeExtractor(bounds)`
   *  with `bounds` denoting the type bounds.
   */
  abstract class BoundedWildcardTypeExtractor {
    def apply(bounds: TypeBounds): BoundedWildcardType
    def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
  }

  /** The API that all this types support.
   *  The main source of information about types is the [[scala.reflect.api.Types]] page.
   */
  trait BoundedWildcardTypeApi extends TypeApi { this: BoundedWildcardType =>
    /** Type bounds for the wildcard type. */
    val bounds: TypeBounds
  }

  /** The least upper bound of a list of types, as determined by `<:<`.  */
  def lub(xs: List[Type]): Type

    /** The greatest lower bound of a list of types, as determined by `<:<`. */
  def glb(ts: List[Type]): Type

  // Creators ---------------------------------------------------------------
  // too useful and too non-trivial to be left out of public API

  /** The canonical creator for single-types */
  def singleType(pre: Type, sym: Symbol): Type

  /** the canonical creator for a refined type with a given scope */
  def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type

  /** The canonical creator for a refined type with an initially empty scope.
   */
  def refinedType(parents: List[Type], owner: Symbol): Type

  /** The canonical creator for typerefs
   */
  def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type

  /** A creator for intersection type where intersections of a single type are
   *  replaced by the type itself. */
  def intersectionType(tps: List[Type]): Type

  /** A creator for intersection type where intersections of a single type are
   *  replaced by the type itself, and repeated parent classes are merged.
   *
   *  !!! Repeated parent classes are not merged - is this a bug in the
   *  comment or in the code?
   */
  def intersectionType(tps: List[Type], owner: Symbol): Type

  /** A creator for type applications */
  def appliedType(tycon: Type, args: List[Type]): Type

  /** A creator for type parameterizations that strips empty type parameter lists.
   *  Use this factory method to indicate the type has kind * (it's a polymorphic value)
   *  until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty).
   */
  def polyType(tparams: List[Symbol], tpe: Type): Type

  /** A creator for existential types. This generates:
   *
   *  {{{
   *    tpe1 where { tparams }
   *  }}}
   *
   *  where `tpe1` is the result of extrapolating `tpe` with regard to `tparams`.
   *  Extrapolating means that type variables in `tparams` occurring
   *  in covariant positions are replaced by upper bounds, (minus any
   *  SingletonClass markers), type variables in `tparams` occurring in
   *  contravariant positions are replaced by upper bounds, provided the
   *  resulting type is legal with regard to stability, and does not contain
   *  any type variable in `tparams`.
   *
   *  The abstraction drops all type parameters that are not directly or
   *  indirectly referenced by type `tpe1`. If there are no remaining type
   *  parameters, simply returns result type `tpe`.
   */
  def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type
}