aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-05 16:09:17 +0200
committerGuillaume Martres <smarter@ubuntu.com>2016-10-12 03:36:57 +0200
commitbafc0a397e28c6e46619f413c9a5648026eac303 (patch)
tree51207f7e43beb19ced1260bce99b85977b155709
parent8897b46fd41437c8ff1a91fad4a58ed452c3c35c (diff)
downloaddotty-bafc0a397e28c6e46619f413c9a5648026eac303.tar.gz
dotty-bafc0a397e28c6e46619f413c9a5648026eac303.tar.bz2
dotty-bafc0a397e28c6e46619f413c9a5648026eac303.zip
Harmonize PolyType and TypeLambda
Let them inherit the same traits and push as much functionality as possibly into the common superclass GenericType.
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeErasure.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala1
-rw-r--r--src/dotty/tools/dotc/core/Types.scala133
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala2
-rw-r--r--src/dotty/tools/dotc/transform/ElimRepeated.scala4
-rw-r--r--src/dotty/tools/dotc/transform/SuperAccessors.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala2
-rw-r--r--tests/pos/sams.scala13
12 files changed, 89 insertions, 84 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index f32a591a6..8a4b47efb 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -485,7 +485,7 @@ class TypeApplications(val self: Type) extends AnyVal {
// In this case we should always dealias since we cannot handle
// higher-kinded applications to wildcard arguments.
dealiased
- .derivedTypeLambda(resType = tycon.safeDealias.appliedTo(args1))
+ .derivedGenericType(resType = tycon.safeDealias.appliedTo(args1))
.appliedTo(args)
case _ =>
val reducer = new Reducer(dealiased, args)
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index b518bf9d9..4c962747a 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -1344,7 +1344,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case tp1: PolyType =>
tp2 match {
case tp2: PolyType if matchingTypeParams(tp1, tp2) =>
- tp1.derivedPolyType(
+ tp1.derivedGenericType(
mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName),
tp1.paramBounds, tp1.resultType & tp2.resultType.subst(tp2, tp1))
case _ =>
diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala
index 1a7342a12..bd1b9b1d3 100644
--- a/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -169,7 +169,7 @@ object TypeErasure {
val erase = erasureFn(isJava, semiEraseVCs, sym.isConstructor, wildcardOK = false)
def eraseParamBounds(tp: PolyType): Type =
- tp.derivedPolyType(
+ tp.derivedGenericType(
tp.paramNames, tp.paramNames map (Function.const(TypeBounds.upper(defn.ObjectType))), tp.resultType)
if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
@@ -356,8 +356,6 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
SuperType(this(thistpe), this(supertpe))
case ExprType(rt) =>
defn.FunctionClass(0).typeRef
- case tp: TypeProxy =>
- this(tp.underlying)
case AndType(tp1, tp2) =>
erasedGlb(this(tp1), this(tp2), isJava)
case OrType(tp1, tp2) =>
@@ -398,6 +396,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
tp
case tp: WildcardType if wildcardOK =>
tp
+ case tp: TypeProxy =>
+ this(tp.underlying)
}
private def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index d480a792b..92e5f9d57 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -136,7 +136,6 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
finally seen = saved
}
case _ =>
- if (tp.isInstanceOf[MethodicType]) assert(variance != 0, tp)
mapOver(tp)
}
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ce1460980..8548a517e 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2504,24 +2504,24 @@ object Types {
}
/** A common supertrait of PolyType and TypeLambda */
- trait GenericType extends BindingType with TermType {
-
- /** The names of the type parameters */
- val paramNames: List[TypeName]
+ abstract class GenericType(val paramNames: List[TypeName])
+ (paramBoundsExp: GenericType => List[TypeBounds],
+ resultTypeExp: GenericType => Type)
+ extends CachedProxyType with BindingType with TermType {
+ type This <: GenericType
+ protected[this] def companion: GenericCompanion[This]
/** The bounds of the type parameters */
- val paramBounds: List[TypeBounds]
+ val paramBounds: List[TypeBounds] = paramBoundsExp(this)
/** The result type of a PolyType / body of a type lambda */
- val resType: Type
+ val resType: Type = resultTypeExp(this)
/** If this is a type lambda, the variances of its parameters, otherwise Nil.*/
- def variances: List[Int]
+ def variances: List[Int] = Nil
override def resultType(implicit ctx: Context) = resType
-
- /** Unconditionally create a new generic type like this one with given elements */
- def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): GenericType
+ override def underlying(implicit ctx: Context) = resType
/** Instantiate result type by substituting parameters with given arguments */
final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type =
@@ -2531,9 +2531,17 @@ object Types {
def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] =
paramBounds.mapConserve(_.substParams(this, argTypes).bounds)
- def derivedGenericType(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context) =
+ /** Unconditionally create a new generic type like this one with given elements */
+ def newLikeThis(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): This =
+ companion.apply(paramNames, variances)(
+ x => paramBounds mapConserve (_.subst(this, x).bounds),
+ x => resType.subst(this, x))
+
+ def derivedGenericType(paramNames: List[TypeName] = this.paramNames,
+ paramBounds: List[TypeBounds] = this.paramBounds,
+ resType: Type = this.resType)(implicit ctx: Context) =
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (resType eq this.resType)) this
- else duplicate(paramNames, paramBounds, resType)
+ else newLikeThis(paramNames, paramBounds, resType)
/** PolyParam references to all type parameters of this type */
lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
@@ -2555,14 +2563,28 @@ object Types {
other.variances == this.variances
case _ => false
}
+
+ override def computeHash = doHash(variances ::: paramNames, resType, paramBounds)
+ }
+
+ abstract class GenericCompanion[GT <: GenericType] {
+ def apply(paramNames: List[TypeName], variances: List[Int])(
+ paramBoundsExp: GenericType => List[TypeBounds],
+ resultTypeExp: GenericType => Type)(implicit ctx: Context): GT
+
+ def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context): Type =
+ if (tparams.isEmpty) resultType
+ else apply(tparams map (_.name.asTypeName), tparams.map(_.variance))(
+ pt => tparams.map(tparam => pt.lifted(tparams, tparam.info).bounds),
+ pt => pt.lifted(tparams, resultType))
}
/** A type for polymorphic methods */
- class PolyType(val paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)
- extends CachedGroundType with GenericType with MethodOrPoly {
- val paramBounds: List[TypeBounds] = paramBoundsExp(this)
- val resType: Type = resultTypeExp(this)
- def variances = Nil
+ class PolyType(paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)
+ extends GenericType(paramNames)(paramBoundsExp, resultTypeExp) with MethodOrPoly {
+
+ type This = PolyType
+ def companion = PolyType
protected def computeSignature(implicit ctx: Context) = resultSignature
@@ -2571,14 +2593,6 @@ object Types {
case _ => false
}
- def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType =
- derivedGenericType(paramNames, paramBounds, resType).asInstanceOf[PolyType]
-
- def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): PolyType =
- PolyType(paramNames)(
- x => paramBounds mapConserve (_.subst(this, x).bounds),
- x => resType.subst(this, x))
-
/** Merge nested polytypes into one polytype. nested polytypes are normally not supported
* but can arise as temporary data structures.
*/
@@ -2598,34 +2612,26 @@ object Types {
}
override def toString = s"PolyType($paramNames, $paramBounds, $resType)"
-
- override def computeHash = doHash(paramNames, resType, paramBounds)
}
- object PolyType {
- def apply(paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)(implicit ctx: Context): PolyType = {
+ object PolyType extends GenericCompanion[PolyType] {
+ def apply(paramNames: List[TypeName], variances: List[Int] = Nil)(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)(implicit ctx: Context): PolyType = {
unique(new PolyType(paramNames)(paramBoundsExp, resultTypeExp))
}
-
- def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) =
- if (tparams.isEmpty) resultType
- else apply(tparams map (_.name.asTypeName))(
- pt => tparams.map(tparam => pt.lifted(tparams, tparam.info).bounds),
- pt => pt.lifted(tparams, resultType))
}
// ----- HK types: TypeLambda, LambdaParam, HKApply ---------------------
/** A type lambda of the form `[v_0 X_0, ..., v_n X_n] => T` */
- class TypeLambda(val paramNames: List[TypeName], val variances: List[Int])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)
- extends CachedProxyType with GenericType with ValueType {
- val paramBounds = paramBoundsExp(this)
- val resType = resultTypeExp(this)
+ class TypeLambda(paramNames: List[TypeName], override val variances: List[Int])(
+ paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)
+ extends GenericType(paramNames)(paramBoundsExp, resultTypeExp) {
assert(resType.isInstanceOf[TermType], this)
assert(paramNames.nonEmpty)
- override def underlying(implicit ctx: Context) = resType
+ type This = TypeLambda
+ def companion = TypeLambda
lazy val typeParams: List[LambdaParam] =
paramNames.indices.toList.map(new LambdaParam(this, _))
@@ -2633,26 +2639,31 @@ object Types {
def derivedLambdaAbstraction(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): Type =
resType match {
case resType @ TypeAlias(alias) =>
- resType.derivedTypeAlias(duplicate(paramNames, paramBounds, alias))
+ resType.derivedTypeAlias(newLikeThis(paramNames, paramBounds, alias))
case resType @ TypeBounds(lo, hi) =>
resType.derivedTypeBounds(
- if (lo.isRef(defn.NothingClass)) lo else duplicate(paramNames, paramBounds, lo),
- duplicate(paramNames, paramBounds, hi))
+ if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramBounds, lo),
+ newLikeThis(paramNames, paramBounds, hi))
case _ =>
- derivedTypeLambda(paramNames, paramBounds, resType)
+ derivedGenericType(paramNames, paramBounds, resType)
}
- def derivedTypeLambda(paramNames: List[TypeName] = paramNames, paramBounds: List[TypeBounds] = paramBounds, resType: Type)(implicit ctx: Context): TypeLambda =
- derivedGenericType(paramNames, paramBounds, resType).asInstanceOf[TypeLambda]
+ override def toString = s"TypeLambda($variances, $paramNames, $paramBounds, $resType)"
+ }
- def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): TypeLambda =
- TypeLambda(paramNames, variances)(
- x => paramBounds mapConserve (_.subst(this, x).bounds),
- x => resType.subst(this, x))
+ object TypeLambda extends GenericCompanion[TypeLambda] {
+ def apply(paramNames: List[TypeName], variances: List[Int])(
+ paramBoundsExp: GenericType => List[TypeBounds],
+ resultTypeExp: GenericType => Type)(implicit ctx: Context): TypeLambda = {
+ unique(new TypeLambda(paramNames, variances)(paramBoundsExp, resultTypeExp))
+ }
- override def toString = s"TypeLambda($variances, $paramNames, $paramBounds, $resType)"
+ def unapply(tl: TypeLambda): Some[(List[LambdaParam], Type)] =
+ Some((tl.typeParams, tl.resType))
- override def computeHash = doHash(variances ::: paramNames, resType, paramBounds)
+ def any(n: Int)(implicit ctx: Context) =
+ apply(tpnme.syntheticLambdaParamNames(n), List.fill(n)(0))(
+ pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
}
/** The parameter of a type lambda */
@@ -2667,24 +2678,6 @@ object Types {
def paramRef(implicit ctx: Context): Type = PolyParam(tl, n)
}
- object TypeLambda {
- def apply(paramNames: List[TypeName], variances: List[Int])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)(implicit ctx: Context): TypeLambda = {
- unique(new TypeLambda(paramNames, variances)(paramBoundsExp, resultTypeExp))
- }
-
- def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) =
- if (tparams.isEmpty) resultType
- else apply(tparams map (_.name.asTypeName), tparams.map(_.variance))(
- pt => tparams.map(tparam => pt.lifted(tparams, tparam.info).bounds),
- pt => pt.lifted(tparams, resultType))
- def unapply(tl: TypeLambda): Some[(List[LambdaParam], Type)] =
- Some((tl.typeParams, tl.resType))
-
- def any(n: Int)(implicit ctx: Context) =
- apply(tpnme.syntheticLambdaParamNames(n), List.fill(n)(0))(
- pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
- }
-
/** A higher kinded type application `C[T_1, ..., T_n]` */
abstract case class HKApply(tycon: Type, args: List[Type])
extends CachedProxyType with ValueType {
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 70148b3e2..0003459e0 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -84,7 +84,7 @@ object Scala2Unpickler {
paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
tp.resultType)
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
+ tp.derivedGenericType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
}
def ensureConstructor(cls: ClassSymbol, scope: Scope)(implicit ctx: Context) =
diff --git a/src/dotty/tools/dotc/transform/ElimRepeated.scala b/src/dotty/tools/dotc/transform/ElimRepeated.scala
index 258b7f234..1450ff832 100644
--- a/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -44,7 +44,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
} else paramTypes
tp.derivedMethodType(paramNames, paramTypes1, resultType1)
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, elimRepeated(tp.resultType))
+ tp.derivedGenericType(tp.paramNames, tp.paramBounds, elimRepeated(tp.resultType))
case tp =>
tp
}
@@ -126,7 +126,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
/** Convert type from Scala to Java varargs method */
private def toJavaVarArgs(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, toJavaVarArgs(tp.resultType))
+ tp.derivedGenericType(tp.paramNames, tp.paramBounds, toJavaVarArgs(tp.resultType))
case tp: MethodType =>
val inits :+ last = tp.paramTypes
val last1 = last.underlyingIfRepeated(isJava = true)
diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 10be6db65..79dbd9fe7 100644
--- a/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -175,7 +175,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
val accType = {
def accTypeOf(tpe: Type): Type = tpe match {
case tpe: PolyType =>
- tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
+ tpe.derivedGenericType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
case _ =>
MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0)))
}
@@ -227,7 +227,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
else clazz.classInfo.selfType
def accTypeOf(tpe: Type): Type = tpe match {
case tpe: PolyType =>
- tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
+ tpe.derivedGenericType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
case _ =>
MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0)))
}
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 56595a637..e2779e758 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -1019,7 +1019,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// todo: make sure implicit method types are not dependent?
// but check test case in /tests/pos/depmet_implicit_chaining_zw.scala
case pt: PolyType =>
- pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
+ pt.derivedGenericType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
case _ =>
tp
}
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index dd5705fbf..4fe2ea6bf 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -363,7 +363,7 @@ object ProtoTypes {
yield new TypeVar(PolyParam(pt, n), state, owningTree, ctx.owner)
val added =
- if (state.constraint contains pt) pt.duplicate(pt.paramNames, pt.paramBounds, pt.resultType)
+ if (state.constraint contains pt) pt.newLikeThis(pt.paramNames, pt.paramBounds, pt.resultType)
else pt
val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added)
ctx.typeComparer.addToConstraint(added, tvars)
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 262d3f731..aecdcbee6 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -360,7 +360,7 @@ trait TypeAssigner {
if (gapBuf.isEmpty) resultType1
else {
val gaps = gapBuf.toList
- pt.derivedPolyType(
+ pt.derivedGenericType(
gaps.map(paramNames),
gaps.map(idx => transform(pt.paramBounds(idx)).bounds),
resultType1)
diff --git a/tests/pos/sams.scala b/tests/pos/sams.scala
index b7ef7dd2d..20338b95c 100644
--- a/tests/pos/sams.scala
+++ b/tests/pos/sams.scala
@@ -73,3 +73,16 @@ class T {
def app[T, U](x: T)(f: F[T, U]): U = f(x)
app(1)(x => List(x))
}
+
+object SI9943 {
+
+class Foo[T] {
+ def toMap[K, V](implicit ev: Foo[T] <:< Foo[(K, V)]): Foo[Map[K, V]] = null
+ def toMap[K](keySelector: T => K): Foo[Map[K, T]] = null
+}
+
+object Foo {
+ val f: Foo[Int] = null
+ val m = f.toMap(_ % 2)
+}
+}