class TypeComparer
extends DotClass with ConstraintHandling

Provides methods to compare types.

Constructors

TypeComparer ( initctx: Context )

Members

var GADTused : Boolean

Indicates whether a previous subtype check used GADT bounds

Indicates whether a previous subtype check used GADT bounds

implicit val ctx : Context
private val initctx : Context
private var myAnyClass : ClassSymbol
private var myAnyType : TypeRef
private var myNothingClass : ClassSymbol
private var myNothingType : TypeRef
private var myNullClass : ClassSymbol
private var myObjectClass : ClassSymbol
private var needsGc : Boolean
private var pendingSubTypes : Set [ ( Type, Type ) ]
private var recCount : Int
val state : TyperState
private var successCount : Int

For statistics: count how many isSubTypes are part of successful comparisons

For statistics: count how many isSubTypes are part of successful comparisons

private var totalCount : Int
def AnyClass : ClassSymbol
def AnyType : TypeRef
[+] private def GADTusage ( sym: Symbol ) : Boolean

Record that GADT bounds of sym were used in a subtype check. But exclude constructor type parameters, as these are aliased to the corresponding class pa...

Record that GADT bounds of sym were used in a subtype check. But exclude constructor type parameters, as these are aliased to the corresponding class parameters, which does not constitute a true usage of a GADT symbol.

def GADTused_= ( x$1: Boolean ) : Unit

Indicates whether a previous subtype check used GADT bounds

Indicates whether a previous subtype check used GADT bounds

def NothingClass : ClassSymbol
def NothingType : TypeRef
def NullClass : ClassSymbol
def ObjectClass : ClassSymbol
[+] final def andType ( tp1: Type , tp2: Type , erased: Boolean ) : Type

Form a normalized conjunction of two types. Note: For certain types, & is distributed inside the type. This holds for all types which are not value type...

    Form a normalized conjunction of two types. Note: For certain types, & is distributed inside the type. This holds for all types which are not value types (e.g. TypeBounds, ClassInfo, ExprType, LambdaType). Also, when forming an &, instantiated TypeVars are dereferenced and annotations are stripped. Finally, refined types with the same refined name are opportunistically merged.

    Sometimes, the conjunction of two types cannot be formed because the types are in conflict of each other. In particular:

    1. Two different class types are conflicting.
    2. A class type conflicts with a type bounds that does not include the class reference.
    3. Two method or poly types with different (type) parameters but the same signature are conflicting

    In these cases, a MergeError is thrown.

    [+] def andType$default$3 : Boolean

    Form a normalized conjunction of two types. Note: For certain types, & is distributed inside the type. This holds for all types which are not value type...

      Form a normalized conjunction of two types. Note: For certain types, & is distributed inside the type. This holds for all types which are not value types (e.g. TypeBounds, ClassInfo, ExprType, LambdaType). Also, when forming an &, instantiated TypeVars are dereferenced and annotations are stripped. Finally, refined types with the same refined name are opportunistically merged.

      Sometimes, the conjunction of two types cannot be formed because the types are in conflict of each other. In particular:

      1. Two different class types are conflicting.
      2. A class type conflicts with a type bounds that does not include the class reference.
      3. Two method or poly types with different (type) parameters but the same signature are conflicting

      In these cases, a MergeError is thrown.

      def compareHkApply1 ( tp1: HKApply , tycon1: Type , args1: List [ Type ] , tp2: Type ) : Boolean

      Subtype test for the hk application tp1 = tycon1[args1].

      Subtype test for the hk application tp1 = tycon1[args1].

      def compareHkApply2 ( tp1: Type , tp2: HKApply , tycon2: Type , args2: List [ Type ] ) : Boolean

      Subtype test for the hk application tp2 = tycon2[args2].

      Subtype test for the hk application tp2 = tycon2[args2].

      def copyIn ( ctx: Context ) : TypeComparer

      A new type comparer of the same type as this one, using the given context.

      A new type comparer of the same type as this one, using the given context.

      private def distributeAnd ( tp1: Type , tp2: Type ) : Type
      [+] private def distributeOr ( tp1: Type , tp2: Type ) : Type

      Try to distribute | inside type, detect and handle conflicts Note that, unlike for &, a disjunction cannot be pushed into a refined or applied type. Exa...

      [T][U][T | U]

      Try to distribute | inside type, detect and handle conflicts Note that, unlike for &, a disjunction cannot be pushed into a refined or applied type. Example:

      List[T] | List[U] is not the same as List[T | U].

      The rhs is a proper supertype of the lhs.

      [+] private def either ( op1: => Boolean , op2: => Boolean ) : Boolean

      Returns true iff the result of evaluating either op1 or op2 is true, trying at the same time to keep the constraint as wide as possible. E.g, if

      tp11 <:<...

      Returns true iff the result of evaluating either op1 or op2 is true, trying at the same time to keep the constraint as wide as possible. E.g, if

      tp11 <:< tp12 = true with post-constraint c1 tp12 <:< tp22 = true with post-constraint c2

      and c1 subsumes c2, then c2 is kept as the post-constraint of the result, otherwise c1 is kept.

      This method is used to approximate a solution in one of the following cases

      T1 & T2 <:< T3 T1 <:< T2 | T3

      In the first case (the second one is analogous), we have a choice whether we want to establish the subtyping judgement using

      T1 <:< T3 or T2 <:< T3

      as a precondition. Either precondition might constrain type variables. The purpose of this method is to pick the precondition that constrains less. The method is not complete, because sometimes there is no best solution. Example:

      A? & B? <: T

      Here, each precondition leads to a different constraint, and neither of the two post-constraints subsumes the other.

      final def ensureStableSingleton ( tp: Type ) : SingletonType
      private def firstTry ( tp1: Type , tp2: Type ) : Boolean
      private def fixRecs ( anchor: SingletonType , tp: Type ) : Type

      Replace any top-level recursive type { z => T } in tp with [z := anchor]T.

      Replace any top-level recursive type { z => T } in tp with [z := anchor]T.

      private def fourthTry ( tp1: Type , tp2: Type ) : Boolean
      def glb ( tp1: Type , tp2: Type ) : Type

      The greatest lower bound of two types

      The greatest lower bound of two types

      final def glb ( tps: List [ Type ] ) : Type

      The greatest lower bound of a list types

      The greatest lower bound of a list types

      [+] protected def hasMatchingMember ( name: Name , tp1: Type , tp2: RefinedType ) : Boolean

      Does type tp1 have a member with name name whose normalized type is a subtype of the normalized type of the refinement tp2? Normalization is as follows:...

      Does type tp1 have a member with name name whose normalized type is a subtype of the normalized type of the refinement tp2? Normalization is as follows: If tp2 contains a skolem to its refinement type, rebase both itself and the member info of tp on a freshly created skolem type.

      private def isAsGood ( tp1: Type , tp2: Type ) : Boolean

      A comparison function to pick a winner in case of a merge conflict

      A comparison function to pick a winner in case of a merge conflict

      [+] private def isCappable ( tp: Type ) : Boolean

      Can type tp be constrained from above by adding a constraint to a typevar that it refers to? In that case we have to be careful not to approximate with...

      Can type tp be constrained from above by adding a constraint to a typevar that it refers to? In that case we have to be careful not to approximate with the lower bound of a type in thirdTry. Instead, we should first unroll tp1 until we hit the type variable and bind the type variable with (the corresponding type in) tp2 instead.

      [+] private def isCovered ( tp: Type ) : Boolean

      A type has been covered previously in subtype checking if it is some combination of TypeRefs that point to classes, where the combiners are RefinedTypes...

      A type has been covered previously in subtype checking if it is some combination of TypeRefs that point to classes, where the combiners are RefinedTypes, RecTypes, AndTypes or AnnotatedTypes. One exception: Refinements referring to basetype args are never considered to be already covered. This is necessary because such refined types might still need to be compared with a compareAliasRefined.

      def isMatchedByProto ( proto: ProtoType , tp: Type ) : Boolean

      Defer constraining type variables when compared against prototypes

      Defer constraining type variables when compared against prototypes

      private def isNewSubType ( tp1: Type , tp2: Type ) : Boolean

      Like tp1 <:< tp2, but returns false immediately if we know that the case was covered previously during subtyping.

      Like tp1 <:< tp2, but returns false immediately if we know that the case was covered previously during subtyping.

      def isSameRef ( tp1: Type , tp2: Type ) : Boolean

      Same as isSameType but also can be applied to overloaded TermRefs, where two overloaded refs are the same if they have pairwise equal alternatives

      Same as isSameType but also can be applied to overloaded TermRefs, where two overloaded refs are the same if they have pairwise equal alternatives

      def isSameType ( tp1: Type , tp2: Type ) : Boolean

      Two types are the same if are mutual subtypes of each other

      Two types are the same if are mutual subtypes of each other

      def isSubArgs ( args1: List [ Type ] , args2: List [ Type ] , tparams: List [ ParamInfo ] ) : Boolean

      Subtype test for corresponding arguments in args1, args2 according to variances in type parameters tparams.

      Subtype test for corresponding arguments in args1, args2 according to variances in type parameters tparams.

      private def isSubRefinements ( tp1: RefinedType , tp2: RefinedType , limit: Type ) : Boolean

      Are refinements in tp1 pairwise subtypes of the refinements of tp2 up to parent type limit?

      Are refinements in tp1 pairwise subtypes of the refinements of tp2 up to parent type limit?

      protected def isSubType ( tp1: Type , tp2: Type ) : Boolean
      [+] private def liftIfHK ( tp1: Type , tp2: Type , op: (Type, Type) => Type , original: (Type, Type) => Type ) : R

      op(tp1, tp2) unless tp1 and tp2 are type-constructors. In the latter case, combine tp1 and tp2 under a type lambda like this:

      [X1, ..., Xn] -> op(tp1X1, ....[X1, ..., Xn]

      op(tp1, tp2) unless tp1 and tp2 are type-constructors. In the latter case, combine tp1 and tp2 under a type lambda like this:

      [X1, ..., Xn] -> op(tp1[X1, ..., Xn], tp2[X1, ..., Xn])

      def lub ( tp1: Type , tp2: Type , canConstrain: Boolean ) : Type
      final def lub ( tps: List [ Type ] ) : Type

      The least upper bound of a list of types

      The least upper bound of a list of types

      def lub$default$3 : Boolean
      final def matchesType ( tp1: Type , tp2: Type , relaxed: Boolean ) : Boolean

      A function implementing tp1 matches tp2.

      A function implementing tp1 matches tp2.

      def matchingParams ( lam1: MethodOrPoly , lam2: MethodOrPoly ) : Boolean

      Do lambda types lam1 and lam2 have parameters that have the same types and the same implicit status? (after renaming one set to the other)

      Do lambda types lam1 and lam2 have parameters that have the same types and the same implicit status? (after renaming one set to the other)

      private def mergeIfSub ( tp1: Type , tp2: Type ) : Type
      private def mergeIfSuper ( tp1: Type , tp2: Type , canConstrain: Boolean ) : Type

      Merge tp1 into tp2 if tp1 is a supertype of some |-summand of tp2.

      Merge tp1 into tp2 if tp1 is a supertype of some |-summand of tp2.

      private def monitoredIsSubType ( tp1: Type , tp2: Type ) : Boolean
      private def myAnyClass_= ( x$1: ClassSymbol ) : Unit
      private def myAnyType_= ( x$1: TypeRef ) : Unit
      private def myNothingClass_= ( x$1: ClassSymbol ) : Unit
      private def myNothingType_= ( x$1: TypeRef ) : Unit
      private def myNullClass_= ( x$1: ClassSymbol ) : Unit
      private def myObjectClass_= ( x$1: ClassSymbol ) : Unit
      [+] private def narrowGADTBounds ( tr: NamedType , bound: Type , isUpper: Boolean ) : Boolean

      Narrow gadt.bounds for the type parameter referenced by tr to include bound as an upper or lower bound (which depends on isUpper). Test that the resulti...

      Narrow gadt.bounds for the type parameter referenced by tr to include bound as an upper or lower bound (which depends on isUpper). Test that the resulting bounds are still satisfiable.

      private def needsGc_= ( x$1: Boolean ) : Unit
      [+] final def orType ( tp1: Type , tp2: Type , erased: Boolean ) : Type

      Form a normalized conjunction of two types. Note: For certain types, | is distributed inside the type. This holds for all types which are not value type...

      Form a normalized conjunction of two types. Note: For certain types, | is distributed inside the type. This holds for all types which are not value types (e.g. TypeBounds, ClassInfo, ExprType, LambdaType). Also, when forming an |, instantiated TypeVars are dereferenced and annotations are stripped.

      Sometimes, the disjunction of two types cannot be formed because the types are in conflict of each other. (@see andType for an enumeration of these cases). In cases of conflict a MergeError is raised.

      [+] def orType$default$3 : Boolean

      Form a normalized conjunction of two types. Note: For certain types, | is distributed inside the type. This holds for all types which are not value type...

      Form a normalized conjunction of two types. Note: For certain types, | is distributed inside the type. This holds for all types which are not value types (e.g. TypeBounds, ClassInfo, ExprType, LambdaType). Also, when forming an |, instantiated TypeVars are dereferenced and annotations are stripped.

      Sometimes, the disjunction of two types cannot be formed because the types are in conflict of each other. (@see andType for an enumeration of these cases). In cases of conflict a MergeError is raised.

      private def pendingSubTypes_= ( x$1: Set [ ( Type, Type ) ] ) : Unit
      private def recCount_= ( x$1: Int ) : Unit
      [+] def recordStatistics ( result: Boolean , prevSuccessCount: Int ) : Unit

      Record statistics about the total number of subtype checks and the number of "successful" subtype checks, i.e. checks that form part of a subtype deriva...

      Record statistics about the total number of subtype checks and the number of "successful" subtype checks, i.e. checks that form part of a subtype derivation tree that's ultimately successful.

      private def secondTry ( tp1: Type , tp2: Type ) : Boolean
      def showGoal ( tp1: Type , tp2: Type ) ( implicit ctx: Context ) : Unit

      Show subtype goal that led to an assertion failure

      Show subtype goal that led to an assertion failure

      private def showType ( tp: Type ) ( implicit ctx: Context ) : String

      Show type, handling type types better than the default

      Show type, handling type types better than the default

      [+] private def skipMatching ( tp1: Type , tp2: RefinedType ) : Type

      Skip refinements in tp2 which match corresponding refinements in tp1. "Match" means: - they appear in the same order, - they refine the same names, - the...

      Skip refinements in tp2 which match corresponding refinements in tp1. "Match" means: - they appear in the same order, - they refine the same names, - the refinement in tp1 is an alias type, and - neither refinement refers back to the refined type via a refined this.

      [+] def subtypeCheckInProgress : Boolean

      Is a subtype check in progress? In that case we may not permanently instantiate type variables, because the corresponding constraint might still be retr...

      Is a subtype check in progress? In that case we may not permanently instantiate type variables, because the corresponding constraint might still be retracted and the instantiation should then be reversed.

      private def successCount_= ( x$1: Int ) : Unit

      For statistics: count how many isSubTypes are part of successful comparisons

      For statistics: count how many isSubTypes are part of successful comparisons

      [+] private def testLifted ( tp1: Type , tp2: Type , tparams: List [ TypeParamInfo ] , p: Type => Boolean ) : Boolean

      Test whether tp1 has a base type of the form B[T1, ..., Tn] where - B derives from one of the class symbols of tp2, - the type parameters of B match one...

      Test whether tp1 has a base type of the form B[T1, ..., Tn] where - B derives from one of the class symbols of tp2, - the type parameters of B match one-by-one the variances of tparams, - B satisfies predicate p.

      private def thirdTry ( tp1: Type , tp2: Type ) : Boolean
      private def thirdTryNamed ( tp1: Type , tp2: NamedType ) : Boolean
      def topLevelSubType ( tp1: Type , tp2: Type ) : Boolean
      private def totalCount_= ( x$1: Int ) : Unit
      def traceIndented ( str: String ) ( op: => T ) : T

      A hook for showing subtype traces. Overridden in ExplainingTypeComparer

      A hook for showing subtype traces. Overridden in ExplainingTypeComparer

      private def traceInfo ( tp1: Type , tp2: Type ) : String