Skip to content

Commit

Permalink
Refactor ParamRef so that no type params are needed
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Apr 6, 2017
1 parent 30af0b5 commit 2b5d1a8
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 51 deletions.
76 changes: 28 additions & 48 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2334,7 +2334,7 @@ object Types {
def resType: Type
def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type)
(implicit ctx: Context): LambdaType { type ThisName = self.ThisName; type PInfo = self.PInfo }
def newParamRef(n: Int): ParamRef[This]
def newParamRef(n: Int): ParamRef

override def resultType(implicit ctx: Context) = resType

Expand All @@ -2344,7 +2344,7 @@ object Types {
final def isTypeLambda = paramNames.head.isTypeName
final def isHigherKinded = isInstanceOf[TypeProxy]

lazy val paramRefs: List[ParamRef[This]] = paramNames.indices.toList.map(newParamRef)
lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef)

def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
if (isDependent) resultType.substParams(this, argTypes)
Expand Down Expand Up @@ -2405,7 +2405,7 @@ object Types {
if (status == TrueDeps) status
else
tp match {
case ParamRef(binder, _) if binder eq thisLambdaType => TrueDeps
case TermParamRef(`thisLambdaType`, _) => TrueDeps
case tp: TypeRef =>
val status1 = foldOver(status, tp)
tp.info match { // follow type alias to avoid dependency
Expand Down Expand Up @@ -2462,7 +2462,7 @@ object Types {
*/
def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps

def newParamRef(n: Int) = new TermParamRef(this, n)
def newParamRef(n: Int) = TermParamRef(this, n)
}

object LambdaOverTerms {
Expand Down Expand Up @@ -2584,7 +2584,7 @@ object Types {
if (Config.checkMethodTypes)
for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex)
paramInfo.foreachPart {
case ParamRef(binder, j) if binder eq mt => assert(j < idx, mt)
case TermParamRef(`mt`, j) => assert(j < idx, mt)
case _ =>
}
mt
Expand Down Expand Up @@ -2850,11 +2850,7 @@ object Types {

abstract class BoundType extends CachedProxyType with ValueType {
type BT <: Type
def binder: BT
// Dotty deviation: copyBoundType was copy, but
// dotty generates copy methods always automatically, and therefore
// does not accept same-named method definitions in subclasses.
// Scala2x, on the other hand, requires them (not sure why!)
val binder: BT
def copyBoundType(bt: BT): Type
}

Expand All @@ -2863,34 +2859,19 @@ object Types {
def paramName: Name
}

abstract case class ParamRef[LT <: LambdaType]
(binder: LT, paramNum: Int) extends ParamType {
type BT = LT

def paramName = binder.paramNames(paramNum)
abstract class ParamRef extends ParamType {
type BT <: LambdaType
def paramName: binder.ThisName = binder.paramNames(paramNum)

override def underlying(implicit ctx: Context): Type = {
val infos = binder.paramInfos
if (infos == null) NoType // this can happen if the referenced generic type is not initialized yet
else infos(paramNum)
}

/** Looking only at the structure of `bound`, is one of the following true?
* - fromBelow and param <:< bound
* - !fromBelow and param >:> bound
*/
def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match {
case bound: ParamRef[_] => bound == this
case bound: AndOrType =>
def occ1 = occursIn(bound.tp1, fromBelow)
def occ2 = occursIn(bound.tp2, fromBelow)
if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2
case _ => false
}

override def computeHash = doHash(paramNum, binder.identityHash)
override def equals(that: Any) = that match {
case that: ParamRef[_] =>
case that: ParamRef =>
(this.binder eq that.binder) && this.paramNum == that.paramNum
case _ =>
false
Expand All @@ -2903,27 +2884,26 @@ object Types {
}
}

class TermParamRef(binder: LambdaOverTerms, paramNum: Int)
extends ParamRef[LambdaOverTerms](binder, paramNum) with SingletonType {
def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum)
case class TermParamRef(binder: LambdaOverTerms, paramNum: Int) extends ParamRef {
type BT = LambdaOverTerms
def copyBoundType(bt: BT) = TermParamRef(bt, paramNum)
}

object TermParamRef {
def apply(binder: LambdaOverTerms, paramNum: Int)(implicit ctx: Context): TermParamRef = {
assertUnerased()
new TermParamRef(binder, paramNum)
}
}

class TypeParamRef(binder: LambdaOverTypes, paramNum: Int)
extends ParamRef[LambdaOverTypes](binder, paramNum) {
def copyBoundType(bt: BT) = new TypeParamRef(bt, paramNum)
}
case class TypeParamRef(binder: LambdaOverTypes, paramNum: Int) extends ParamRef {
type BT = LambdaOverTypes
def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum)

object TypeParamRef {
def apply(binder: LambdaOverTypes, paramNum: Int)(implicit ctx: Context): TypeParamRef = {
assertUnerased()
new TypeParamRef(binder, paramNum)
/** Looking only at the structure of `bound`, is one of the following true?
* - fromBelow and param <:< bound
* - !fromBelow and param >:> bound
*/
def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match {
case bound: ParamRef => bound == this
case bound: AndOrType =>
def occ1 = occursIn(bound.tp1, fromBelow)
def occ2 = occursIn(bound.tp2, fromBelow)
if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2
case _ => false
}
}

Expand Down Expand Up @@ -3872,7 +3852,7 @@ object Types {
apply(x, tp.tref)
case tp: ConstantType =>
apply(x, tp.underlying)
case tp: ParamRef[_] =>
case tp: TermParamRef =>
apply(x, tp.underlying)
case tp: PolyParam =>
apply(x, tp.underlying)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) {
case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes)
case _ => assert(false, s"orphan poly parameter: $tpe")
}
case tpe: ParamRef[_] =>
case tpe: TermParamRef =>
assert(pickleParamType(tpe), s"orphan method parameter: $tpe")
case tpe: LazyRef =>
pickleType(tpe.ref)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp
traverse(tp.underlying)
case tp: ConstantType =>
traverse(tp.underlying)
case tp: ParamRef[_] =>
case tp: TermParamRef =>
traverse(tp.underlying)
case tp: PolyParam =>
traverse(tp.underlying)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ object ProtoTypes {
case inst => wildApprox(inst, theMap, seen)
}
approxPoly
case ParamRef(mt, pnum) =>
case TermParamRef(mt, pnum) =>
WildcardType(TypeBounds.upper(wildApprox(mt.paramInfos(pnum), theMap, seen)))
case tp: TypeVar =>
wildApprox(tp.underlying, theMap, seen)
Expand Down

0 comments on commit 2b5d1a8

Please sign in to comment.