aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala6
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala2
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala2
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala80
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
11 files changed, 88 insertions, 33 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index 6152a2880..ad3764450 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -135,7 +135,7 @@ object CheckTrees {
check(finalizer.isTerm)
check(handler.isTerm)
check(handler.tpe derivesFrom defn.FunctionClass(1))
- check(handler.tpe.baseTypeArgs(defn.FunctionClass(1)).head <:< defn.ThrowableType)
+ check(handler.tpe.baseArgInfos(defn.FunctionClass(1)).head <:< defn.ThrowableType)
case Throw(expr) =>
check(expr.isValue)
check(expr.tpe.derivesFrom(defn.ThrowableClass))
@@ -210,9 +210,9 @@ object CheckTrees {
check(args.isEmpty)
else {
check(rtp isRef defn.OptionClass)
- val normArgs = rtp.typeArgs match {
+ val normArgs = rtp.argTypesHi match {
case optionArg :: Nil =>
- optionArg.typeArgs match {
+ optionArg.argTypesHi match {
case Nil =>
optionArg :: Nil
case tupleArgs if defn.isTupleType(optionArg) =>
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 8b9e0c12e..03c0f83a9 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -336,7 +336,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
/** new C(args) */
def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = {
- val targs = tp.typeArgs
+ val targs = tp.argTypes
Apply(
Select(
New(tp withoutArgs targs),
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index 4aff9da5d..fc2b07b02 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -124,7 +124,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] {
case TypedSplice(AppliedTypeTree(tycon, targs)) =>
(TypedSplice(tycon), targs map TypedSplice)
case TypedSplice(tpt1: Tree) =>
- val argTypes = tpt1.tpe.typeArgs
+ val argTypes = tpt1.tpe.argTypes
val tycon = tpt1.tpe.withoutArgs(argTypes)
def wrap(tpe: Type) = TypeTree(tpe) withPos tpt.pos
(wrap(tycon), argTypes map wrap)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 0ee0ea1e2..ef16a970d 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -286,7 +286,7 @@ class Definitions {
def unapply(ft: Type): Option[(List[Type], Type)] = { // Dotty deviation: Type annotation needed because inferred type
// is Some[(List[Type], Type)] | None, which is not a legal unapply type.
val tsym = ft.typeSymbol
- lazy val targs = ft.typeArgs
+ lazy val targs = ft.argInfos
if ((FunctionClasses contains tsym) &&
(targs.length - 1 <= MaxFunctionArity) &&
(FunctionClass(targs.length - 1) == tsym)) Some((targs.init, targs.last)) // Dotty deviation: no auto-tupling
@@ -317,7 +317,7 @@ class Definitions {
lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule)
def isTupleType(tp: Type) = {
- val arity = tp.dealias.typeArgs.length
+ val arity = tp.dealias.argInfos.length
arity <= MaxTupleArity && (tp isRef TupleClass(arity))
}
@@ -329,7 +329,7 @@ class Definitions {
0 <= arity && arity <= MaxFunctionArity && (tp isRef FunctionClass(arity))
}
- def functionArity(tp: Type) = tp.dealias.typeArgs.length - 1
+ def functionArity(tp: Type) = tp.dealias.argInfos.length - 1
// ----- Higher kinds machinery ------------------------------------------
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index e854e672f..b4c30d902 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -12,6 +12,29 @@ import Flags._
import util.Positions.Position
import collection.mutable
+object TypeApplications {
+
+ /** Assert type is not a TypeBounds instance and return it unchanged */
+ val noBounds = (tp: Type) => tp match {
+ case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed")
+ case _ => tp
+ }
+
+ /** If `tp` is a TypeBounds instance return its lower bound else return `tp` */
+ val boundsToLo = (tp: Type) => tp match {
+ case tp: TypeBounds => tp.lo
+ case _ => tp
+ }
+
+ /** If `tp` is a TypeBounds instance return its upper bound else return `tp` */
+ val boundsToHi = (tp: Type) => tp match {
+ case tp: TypeBounds => tp.hi
+ case _ => tp
+ }
+}
+
+import TypeApplications._
+
/** A decorator that provides methods for modeling type application */
class TypeApplications(val self: Type) extends AnyVal {
@@ -135,24 +158,43 @@ class TypeApplications(val self: Type) extends AnyVal {
else TypeAlias(self, v)
}
- /** The type arguments of the base type instance wrt `base` of this type */
- final def baseTypeArgs(base: Symbol)(implicit ctx: Context): List[Type] =
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are returned as TypeBounds instances.
+ */
+ final def baseArgInfos(base: Symbol)(implicit ctx: Context): List[Type] =
if (self derivesFrom base)
- base.typeParams map (param => self.member(param.name).info.argType(param))
+ base.typeParams map (param => self.member(param.name).info.argInfo(param))
else
Nil
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are disallowed.
+ */
+ final def baseArgTypes(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve noBounds
+
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are approximanted by their lower bound.
+ */
+ final def baseArgTypesLo(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToLo
+
+ /** The type arguments of this type's base type instance wrt.`base`.
+ * Existential types in arguments are approximanted by their upper bound.
+ */
+ final def baseArgTypesHi(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToHi
+
/** The first type argument of the base type instance wrt `base` of this type */
- final def firstBaseTypeArg(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
+ final def firstBaseArgInfo(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
case param :: _ if self derivesFrom base =>
- self.member(param.name).info.argType(param)
+ self.member(param.name).info.argInfo(param)
case _ =>
NoType
}
- /** The base type including all type arguments of this type */
+ /** The base type including all type arguments of this type.
+ * Existential types in arguments are returned as TypeBounds instances.
+ */
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type =
- self.baseTypeRef(base).appliedTo(baseTypeArgs(base))
+ self.baseTypeRef(base).appliedTo(baseArgInfos(base))
/** Translate a type of the form From[T] to To[T], keep other types as they are.
* `from` and `to` must be static classes, both with one type parameter, and the same variance.
@@ -163,9 +205,10 @@ class TypeApplications(val self: Type) extends AnyVal {
else self
/** If this is an encoding of a (partially) applied type, return its arguments,
- * otherwise return Nil
+ * otherwise return Nil.
+ * Existential types in arguments are returned as TypeBounds instances.
*/
- final def typeArgs(implicit ctx: Context): List[Type] = {
+ final def argInfos(implicit ctx: Context): List[Type] = {
var tparams: List[TypeSymbol] = null
def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match {
case tp @ RefinedType(tycon, name) =>
@@ -175,7 +218,7 @@ class TypeApplications(val self: Type) extends AnyVal {
if (tparams == null) tparams = tycon.typeParams
if (buf.size < tparams.length) {
val tparam = tparams(buf.size)
- if (name == tparam.name) buf += tp.refinedInfo.argType(tparam)
+ if (name == tparam.name) buf += tp.refinedInfo.argInfo(tparam)
else null
} else null
}
@@ -187,6 +230,15 @@ class TypeApplications(val self: Type) extends AnyVal {
if (buf == null) Nil else buf.toList
}
+ /** Argument types where existential types in arguments are disallowed */
+ def argTypes(implicit ctx: Context) = argInfos mapConserve noBounds
+
+ /** Argument types where existential types in arguments are approximated by their lower bound */
+ def argTypesLo(implicit ctx: Context) = argInfos mapConserve boundsToLo
+
+ /** Argument types where existential types in arguments are approximated by their upper bound */
+ def argTypesHi(implicit ctx: Context) = argInfos mapConserve boundsToHi
+
/** The core type without any type arguments.
* @param `typeArgs` must be the type arguments of this type.
*/
@@ -201,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** If this is the image of a type argument to type parameter `tparam`,
* recover the type argument, otherwise NoType.
*/
- final def argType(tparam: Symbol)(implicit ctx: Context): Type = self match {
+ final def argInfo(tparam: Symbol)(implicit ctx: Context): Type = self match {
case TypeBounds(lo, hi) =>
if (lo eq hi) hi
else {
@@ -216,7 +268,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** The element type of a sequence or array */
def elemType(implicit ctx: Context): Type =
- firstBaseTypeArg(defn.SeqClass) orElse firstBaseTypeArg(defn.ArrayClass)
+ firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass)
/** If this type is of the normalized form Array[...[Array[T]...]
* return the number of Array wrappers and T.
@@ -225,7 +277,7 @@ class TypeApplications(val self: Type) extends AnyVal {
final def splitArray(implicit ctx: Context): (Int, Type) = {
def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
case RefinedType(tycon, _) if tycon isRef defn.ArrayClass =>
- tp.typeArgs match {
+ tp.argInfos match {
case arg :: Nil => recur(n + 1, arg)
case _ => (n, tp)
}
@@ -274,7 +326,7 @@ class TypeApplications(val self: Type) extends AnyVal {
val correspondingParamName: Map[Symbol, TypeName] = {
for {
- (tparam, targ: TypeRef) <- cls.typeParams zip typeArgs
+ (tparam, targ: TypeRef) <- cls.typeParams zip argInfos
if boundSyms contains targ.symbol
} yield targ.symbol -> tparam.name
}.toMap
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 0af6ebf97..d46a8387f 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -616,7 +616,7 @@ class TypeComparer(initctx: Context) extends DotClass {
*/
def isSubTypeHK(tp1: Type, tp2: Type): Boolean = {
val tparams = tp1.typeParams
- val hkArgs = tp2.typeArgs
+ val hkArgs = tp2.argInfos
(hkArgs.length == tparams.length) && {
val base = tp1.narrow
(tparams, hkArgs).zipped.forall { (tparam, hkArg) =>
@@ -752,7 +752,7 @@ class TypeComparer(initctx: Context) extends DotClass {
/** The least upper bound of two types
* @note We do not admit singleton types in or-types as lubs.
*/
- def lub(tp1: Type, tp2: Type): Type =
+ def lub(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"lub(${tp1.show}, ${tp2.show})", typr, show = true) /*<|<*/ {
if (tp1 eq tp2) tp1
else if (!tp1.exists) tp1
else if (!tp2.exists) tp2
@@ -772,6 +772,7 @@ class TypeComparer(initctx: Context) extends DotClass {
}
}
}
+ }
/** The least upper bound of a list of types */
final def lub(tps: List[Type]): Type =
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index bc8d7dfd2..4d26a6735 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -96,7 +96,7 @@ object Types {
else thissym eq sym
case this1: RefinedType =>
// make sure all refinements are type arguments
- this1.parent.isRef(sym) && this.typeArgs.nonEmpty
+ this1.parent.isRef(sym) && this.argInfos.nonEmpty
case _ =>
false
}
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index c48e71052..c69f60758 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -76,7 +76,7 @@ object UnPickler {
case tp @ MethodType(paramNames, paramTypes) =>
val lastArg = paramTypes.last
assert(lastArg isRef defn.ArrayClass)
- val elemtp0 :: Nil = lastArg.baseTypeArgs(defn.ArrayClass)
+ val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass)
val elemtp = elemtp0 match {
case AndType(t1, t2) if t1.typeSymbol.isAbstractType && (t2 isRef defn.ObjectClass) =>
t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 6fad6738e..cb0780ae3 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -96,7 +96,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
tp match {
case tp: RefinedType =>
- val args = tp.typeArgs
+ val args = tp.argInfos
if (args.nonEmpty) {
val tycon = tp.unrefine
val cls = tycon.typeSymbol
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 4b43aa8b7..4d7bc8976 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -24,6 +24,7 @@ import EtaExpansion._
import collection.mutable
import reflect.ClassTag
import config.Printers._
+import TypeApplications._
import language.implicitConversions
object Applications {
@@ -266,7 +267,7 @@ trait Applications extends Compatibility { self: Typer =>
case arg :: Nil if isVarArg(arg) =>
addTyped(arg, formal)
case _ =>
- val elemFormal = formal.typeArgs.head
+ val elemFormal = formal.argTypesLo.head
args foreach (addTyped(_, elemFormal))
makeVarArg(args.length, elemFormal)
}
@@ -609,7 +610,7 @@ trait Applications extends Compatibility { self: Typer =>
if (extractorMemberType(unapplyResult, nme.isDefined) isRef defn.BooleanClass) {
if (getTp.exists)
if (unapply.symbol.name == nme.unapplySeq) {
- val seqArg = getTp.firstBaseTypeArg(defn.SeqClass)
+ val seqArg = boundsToHi(getTp.firstBaseArgInfo(defn.SeqClass))
if (seqArg.exists) return args map Function.const(seqArg)
}
else return getSelectors(getTp)
@@ -683,6 +684,7 @@ trait Applications extends Compatibility { self: Typer =>
}
var argTypes = unapplyArgs(unapplyApp.tpe)
+ for (argType <- argTypes) assert(!argType.isInstanceOf[TypeBounds], unapplyApp.tpe.show)
val bunchedArgs = argTypes match {
case argType :: Nil if argType.isRepeatedParam => untpd.SeqLiteral(args) :: Nil
case _ => args
@@ -770,7 +772,7 @@ trait Applications extends Compatibility { self: Typer =>
val tparams = ctx.newTypeParams(alt1.symbol.owner, tp1.paramNames, EmptyFlags, bounds)
isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
case tp1: MethodType =>
- def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.typeArgs.head else tp
+ def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.argTypesHi.head else tp
isApplicable(alt2, tp1.paramTypes map repeatedToSingle, WildcardType) ||
tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly]
case _ =>
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 400a1407a..96fe73e7d 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -438,7 +438,7 @@ class Typer extends Namer with Applications with Implicits {
}
def typedPair(tree: untpd.Pair, pt: Type)(implicit ctx: Context) = track("typedPair") {
- val (leftProto, rightProto) = pt.typeArgs match {
+ val (leftProto, rightProto) = pt.argTypesLo match {
case l :: r :: Nil if pt isRef defn.PairClass => (l, r)
case _ => (WildcardType, WildcardType)
}
@@ -561,7 +561,7 @@ class Typer extends Namer with Applications with Implicits {
val params = args.asInstanceOf[List[untpd.ValDef]]
val (protoFormals, protoResult): (List[Type], Type) = pt match {
case _ if defn.isFunctionType(pt) =>
- (pt.dealias.typeArgs.init, pt.dealias.typeArgs.last)
+ (pt.dealias.argInfos.init, pt.dealias.argInfos.last)
case SAMType(meth) =>
val mt @ MethodType(_, paramTypes) = meth.info
(paramTypes, mt.resultType)
@@ -750,7 +750,7 @@ class Typer extends Namer with Applications with Implicits {
val expr1 = typed(tree.expr, pt)
val handler1 = typed(tree.handler, defn.FunctionType(defn.ThrowableType :: Nil, pt))
val finalizer1 = typed(tree.finalizer, defn.UnitType)
- val handlerTypeArgs = handler1.tpe.baseTypeArgs(defn.FunctionClass(1))
+ val handlerTypeArgs = handler1.tpe.baseArgTypesHi(defn.FunctionClass(1))
val ownType = if (handlerTypeArgs.nonEmpty) expr1.tpe | handlerTypeArgs(1) else expr1.tpe
cpy.Try(tree, expr1, handler1, finalizer1) withType ownType
}