@@ -680,7 +680,7 @@ object Types {
680
680
* (Note: no stripTypeVar needed because TypeVar's can't refer to ExprTypes.)
681
681
*/
682
682
final def widenExpr : Type = this match {
683
- case tp : ExprType => tp.resultType
683
+ case tp : ExprType => tp.resType
684
684
case _ => this
685
685
}
686
686
@@ -858,33 +858,33 @@ object Types {
858
858
}
859
859
860
860
/** The parameter types of a PolyType or MethodType, Empty list for others */
861
- final def paramTypess : List [List [Type ]] = this match {
861
+ final def paramTypess ( implicit ctx : Context ) : List [List [Type ]] = this match {
862
862
case mt : MethodType => mt.paramTypes :: mt.resultType.paramTypess
863
863
case pt : PolyType => pt.resultType.paramTypess
864
864
case _ => Nil
865
865
}
866
866
867
867
/** The parameter types in the first parameter section of a PolyType or MethodType, Empty list for others */
868
- final def firstParamTypes : List [Type ] = this match {
868
+ final def firstParamTypes ( implicit ctx : Context ) : List [Type ] = this match {
869
869
case mt : MethodType => mt.paramTypes
870
870
case pt : PolyType => pt.resultType.firstParamTypes
871
871
case _ => Nil
872
872
}
873
873
874
874
/** Is this either not a method at all, or a parameterless method? */
875
- final def isParameterless : Boolean = this match {
875
+ final def isParameterless ( implicit ctx : Context ) : Boolean = this match {
876
876
case mt : MethodType => false
877
877
case pt : PolyType => pt.resultType.isParameterless
878
878
case _ => true
879
879
}
880
880
881
881
/** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */
882
- def resultType : Type = this
882
+ def resultType ( implicit ctx : Context ) : Type = this
883
883
884
884
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
885
885
* all parameter sections, the type itself for all others.
886
886
*/
887
- def finalResultType : Type = resultType match {
887
+ def finalResultType ( implicit ctx : Context ) : Type = resultType match {
888
888
case mt : MethodType => mt.resultType.finalResultType
889
889
case pt : PolyType => pt.resultType.finalResultType
890
890
case _ => resultType
@@ -1941,49 +1941,77 @@ object Types {
1941
1941
abstract case class MethodType (paramNames : List [TermName ], paramTypes : List [Type ])
1942
1942
(resultTypeExp : MethodType => Type )
1943
1943
extends CachedGroundType with BindingType with TermType with MethodOrPoly with NarrowCached { thisMethodType =>
1944
+ import MethodType ._
1944
1945
1945
- override val resultType = resultTypeExp(this )
1946
- assert(resultType.exists)
1947
1946
def isJava = false
1948
1947
def isImplicit = false
1948
+
1949
+ private val resType = resultTypeExp(this )
1950
+ assert(resType.exists)
1951
+
1952
+ override def resultType (implicit ctx : Context ): Type =
1953
+ if (dependencyStatus == FalseDeps ) { // dealias all false dependencies
1954
+ val dealiasMap = new TypeMap {
1955
+ def apply (tp : Type ) = tp match {
1956
+ case tp @ TypeRef (MethodParam (`thisMethodType`, _), name) => // follow type alias to avoid dependency
1957
+ val TypeAlias (alias) = tp.info
1958
+ apply(alias)
1959
+ case _ =>
1960
+ mapOver(tp)
1961
+ }
1962
+ }
1963
+ dealiasMap(resType)
1964
+ }
1965
+ else resType
1949
1966
1950
- private [this ] var myIsDependent : Boolean = _
1951
- private [this ] var myIsDepKnown = false
1952
-
1953
- /** Does result type contain references to parameters of this method type?
1954
- */
1955
- def isDependent (implicit ctx : Context ) = {
1956
- if (! myIsDepKnown) {
1957
- val isDepAcc = new TypeAccumulator [Boolean ] {
1958
- def apply (x : Boolean , tp : Type ) = x || {
1959
- tp match {
1960
- case MethodParam (`thisMethodType`, _) => true
1961
- case tp @ TypeRef (MethodParam (`thisMethodType`, _), name) =>
1962
- tp.info match { // follow type arguments to avoid dependency
1963
- case TypeAlias (tp)=> apply(x, tp)
1964
- case _ => true
1965
- }
1966
- case _ =>
1967
- foldOver(x, tp)
1967
+ private [this ] var myDependencyStatus : DependencyStatus = Unknown
1968
+
1969
+ /** The dependency status of this method. Some examples:
1970
+ *
1971
+ * class C extends { type S; type T = String }
1972
+ * def f(x: C)(y: Boolean) // dependencyStatus = NoDeps
1973
+ * def f(x: C)(y: x.S) // dependencyStatus = TrueDeps
1974
+ * def f(x: C)(y: x.T) // dependencyStatus = FalseDeps, i.e.
1975
+ * // dependency can be eliminated by dealiasing.
1976
+ */
1977
+ private def dependencyStatus (implicit ctx : Context ): DependencyStatus = {
1978
+ if (myDependencyStatus == Unknown ) {
1979
+ val isDepAcc = new TypeAccumulator [DependencyStatus ] {
1980
+ def apply (x : DependencyStatus , tp : Type ) =
1981
+ if (x == TrueDeps ) x
1982
+ else x max {
1983
+ tp match {
1984
+ case MethodParam (`thisMethodType`, _) => TrueDeps
1985
+ case tp @ TypeRef (MethodParam (`thisMethodType`, _), name) =>
1986
+ tp.info match { // follow type alias to avoid dependency
1987
+ case TypeAlias (alias) => apply(x, alias) max FalseDeps
1988
+ case _ => TrueDeps
1989
+ }
1990
+ case _ =>
1991
+ foldOver(x, tp)
1992
+ }
1968
1993
}
1969
- }
1970
1994
}
1971
- myIsDependent = isDepAcc(false , resultType)
1972
- myIsDepKnown = true
1995
+ myDependencyStatus = isDepAcc(NoDeps , resType)
1973
1996
}
1974
- myIsDependent
1997
+ myDependencyStatus
1975
1998
}
1976
1999
2000
+ /** Does result type contain references to parameters of this method type,
2001
+ * which cannot be eliminated by de-aliasing?
2002
+ */
2003
+ def isDependent (implicit ctx : Context ): Boolean = dependencyStatus == TrueDeps
2004
+
1977
2005
protected def computeSignature (implicit ctx : Context ): Signature =
1978
2006
resultSignature.prepend(paramTypes, isJava)
1979
2007
1980
- def derivedMethodType (paramNames : List [TermName ], paramTypes : List [Type ], restpe : Type )(implicit ctx : Context ) =
1981
- if ((paramNames eq this .paramNames) && (paramTypes eq this .paramTypes) && (restpe eq this .resultType )) this
2008
+ def derivedMethodType (paramNames : List [TermName ], paramTypes : List [Type ], resType : Type )(implicit ctx : Context ) =
2009
+ if ((paramNames eq this .paramNames) && (paramTypes eq this .paramTypes) && (resType eq this .resType )) this
1982
2010
else {
1983
- val restpeFn = (x : MethodType ) => restpe .subst(this , x)
1984
- if (isJava) JavaMethodType (paramNames, paramTypes)(restpeFn )
1985
- else if (isImplicit) ImplicitMethodType (paramNames, paramTypes)(restpeFn )
1986
- else MethodType (paramNames, paramTypes)(restpeFn )
2011
+ val resTypeFn = (x : MethodType ) => resType .subst(this , x)
2012
+ if (isJava) JavaMethodType (paramNames, paramTypes)(resTypeFn )
2013
+ else if (isImplicit) ImplicitMethodType (paramNames, paramTypes)(resTypeFn )
2014
+ else MethodType (paramNames, paramTypes)(resTypeFn )
1987
2015
}
1988
2016
1989
2017
def instantiate (argTypes : => List [Type ])(implicit ctx : Context ): Type =
@@ -1994,15 +2022,15 @@ object Types {
1994
2022
case that : MethodType =>
1995
2023
this .paramNames == that.paramNames &&
1996
2024
this .paramTypes == that.paramTypes &&
1997
- this .resultType == that.resultType
2025
+ this .resType == that.resType
1998
2026
case _ =>
1999
2027
false
2000
2028
}
2001
2029
2002
- override def computeHash = doHash(paramNames, resultType , paramTypes)
2030
+ override def computeHash = doHash(paramNames, resType , paramTypes)
2003
2031
2004
2032
protected def prefixString = " MethodType"
2005
- override def toString = s " $prefixString( $paramNames, $paramTypes, $resultType ) "
2033
+ override def toString = s " $prefixString( $paramNames, $paramTypes, $resType ) "
2006
2034
}
2007
2035
2008
2036
final class CachedMethodType (paramNames : List [TermName ], paramTypes : List [Type ])(resultTypeExp : MethodType => Type )
@@ -2052,6 +2080,12 @@ object Types {
2052
2080
object MethodType extends MethodTypeCompanion {
2053
2081
def apply (paramNames : List [TermName ], paramTypes : List [Type ])(resultTypeExp : MethodType => Type )(implicit ctx : Context ) =
2054
2082
unique(new CachedMethodType (paramNames, paramTypes)(resultTypeExp))
2083
+
2084
+ private type DependencyStatus = Byte
2085
+ private final val Unknown : DependencyStatus = 0 // not yet computed
2086
+ private final val NoDeps : DependencyStatus = 1 // no dependent parameters found
2087
+ private final val FalseDeps : DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
2088
+ private final val TrueDeps : DependencyStatus = 3 // some truly dependent parameters exist
2055
2089
}
2056
2090
2057
2091
object JavaMethodType extends MethodTypeCompanion {
@@ -2065,13 +2099,14 @@ object Types {
2065
2099
}
2066
2100
2067
2101
/** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
2068
- abstract case class ExprType (override val resultType : Type )
2102
+ abstract case class ExprType (resType : Type )
2069
2103
extends CachedProxyType with TermType with MethodicType {
2070
- override def underlying (implicit ctx : Context ): Type = resultType
2104
+ override def resultType (implicit ctx : Context ): Type = resType
2105
+ override def underlying (implicit ctx : Context ): Type = resType
2071
2106
protected def computeSignature (implicit ctx : Context ): Signature = resultSignature
2072
- def derivedExprType (resultType : Type )(implicit ctx : Context ) =
2073
- if (resultType eq this .resultType ) this else ExprType (resultType )
2074
- override def computeHash = doHash(resultType )
2107
+ def derivedExprType (resType : Type )(implicit ctx : Context ) =
2108
+ if (resType eq this .resType ) this else ExprType (resType )
2109
+ override def computeHash = doHash(resType )
2075
2110
}
2076
2111
2077
2112
final class CachedExprType (resultType : Type ) extends ExprType (resultType)
@@ -2087,7 +2122,9 @@ object Types {
2087
2122
extends CachedGroundType with BindingType with TermType with MethodOrPoly {
2088
2123
2089
2124
val paramBounds = paramBoundsExp(this )
2090
- override val resultType = resultTypeExp(this )
2125
+ val resType = resultTypeExp(this )
2126
+
2127
+ override def resultType (implicit ctx : Context ) = resType
2091
2128
2092
2129
protected def computeSignature (implicit ctx : Context ) = resultSignature
2093
2130
@@ -2097,21 +2134,21 @@ object Types {
2097
2134
def instantiateBounds (argTypes : List [Type ])(implicit ctx : Context ): List [TypeBounds ] =
2098
2135
paramBounds.mapConserve(_.substParams(this , argTypes).bounds)
2099
2136
2100
- def derivedPolyType (paramNames : List [TypeName ], paramBounds : List [TypeBounds ], restpe : Type )(implicit ctx : Context ) =
2101
- if ((paramNames eq this .paramNames) && (paramBounds eq this .paramBounds) && (restpe eq this .resultType )) this
2102
- else duplicate(paramNames, paramBounds, restpe )
2137
+ def derivedPolyType (paramNames : List [TypeName ], paramBounds : List [TypeBounds ], resType : Type )(implicit ctx : Context ) =
2138
+ if ((paramNames eq this .paramNames) && (paramBounds eq this .paramBounds) && (resType eq this .resType )) this
2139
+ else duplicate(paramNames, paramBounds, resType )
2103
2140
2104
- def duplicate (paramNames : List [TypeName ] = this .paramNames, paramBounds : List [TypeBounds ] = this .paramBounds, restpe : Type )(implicit ctx : Context ) =
2141
+ def duplicate (paramNames : List [TypeName ] = this .paramNames, paramBounds : List [TypeBounds ] = this .paramBounds, resType : Type )(implicit ctx : Context ) =
2105
2142
PolyType (paramNames)(
2106
2143
x => paramBounds mapConserve (_.subst(this , x).bounds),
2107
- x => restpe .subst(this , x))
2144
+ x => resType .subst(this , x))
2108
2145
2109
2146
// need to override hashCode and equals to be object identity
2110
2147
// because paramNames by itself is not discriminatory enough
2111
2148
override def equals (other : Any ) = this eq other.asInstanceOf [AnyRef ]
2112
2149
override def computeHash = identityHash
2113
2150
2114
- override def toString = s " PolyType( $paramNames, $paramBounds, $resultType ) "
2151
+ override def toString = s " PolyType( $paramNames, $paramBounds, $resType ) "
2115
2152
}
2116
2153
2117
2154
object PolyType {
0 commit comments