aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala8
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala17
-rw-r--r--tests/neg/kinds.scala18
-rw-r--r--tests/pos/jon.scala2
-rw-r--r--tests/pos/range.scala4
-rw-r--r--tests/pos/t2613.scala2
-rw-r--r--tests/pos/tycons.scala22
11 files changed, 58 insertions, 39 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index be0eb9230..1700a9c9c 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -378,15 +378,18 @@ class TypeApplications(val self: Type) extends AnyVal {
}
}
+ /** If `self` is a higher-kinded type, its type parameters $hk_i, otherwise Nil */
final def hkTypeParams(implicit ctx: Context): List[MemberBinding] =
if (Config.newHK)
if (isHK) typeParams else Nil
else LambdaTraitOBS.typeParams
- final def typeParamSymbols(implicit ctx: Context): List[TypeSymbol] = {
- val tparams = typeParams
- assert(tparams.isEmpty || tparams.head.isInstanceOf[Symbol], self)
- tparams.asInstanceOf[List[TypeSymbol]]
+ /** If `self` is a generic class, its type parameter symbols, otherwise Nil */
+ final def typeParamSymbols(implicit ctx: Context): List[TypeSymbol] = typeParams match {
+ case (_: Symbol) :: _ =>
+ assert(typeParams.forall(_.isInstanceOf[Symbol]))
+ typeParams.asInstanceOf[List[TypeSymbol]]
+ case _ => Nil
}
/** The named type parameters declared or inherited by this type.
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 14071e27c..cdbf692cd 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -17,6 +17,7 @@ import Types._
import Decorators._
import ErrorReporting._
import Trees._
+import config.Config
import Names._
import StdNames._
import ProtoTypes._
@@ -644,7 +645,7 @@ trait Applications extends Compatibility { self: Typer =>
}
def adaptTypeArg(tree: tpd.Tree, bound: Type)(implicit ctx: Context): tpd.Tree =
- tree.withType(tree.tpe.etaExpandIfHK(bound))
+ if (Config.newHK) tree else tree.withType(tree.tpe.etaExpandIfHK(bound))
/** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray.
* It is performed during typer as creation of generic arrays needs a classTag.
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 6944197a1..cfad4e77e 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -36,11 +36,16 @@ object Checking {
/** A general checkBounds method that can be used for TypeApply nodes as
* well as for AppliedTypeTree nodes.
*/
- def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context) =
+ def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context) = {
+ (args, boundss).zipped.foreach { (arg, bound) =>
+ if (!bound.isHK && arg.tpe.isHK)
+ ctx.error(d"missing type parameter(s) for $arg", arg.pos)
+ }
for ((arg, which, bound) <- ctx.boundsViolations(args, boundss, instantiate))
ctx.error(
d"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}",
arg.pos)
+ }
/** Check that type arguments `args` conform to corresponding bounds in `poly`
* Note: This does not check the bounds of AppliedTypeTrees. These
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index a8f3b8918..7982f288d 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -14,6 +14,7 @@ import collection.mutable
import annotation.tailrec
import ErrorReporting._
import tpd.ListOfTreeDecorator
+import config.Config
import config.Printers._
import Annotations._
import Inferencing._
@@ -591,7 +592,7 @@ class Namer { typer: Typer =>
*/
def parentType(parent: untpd.Tree)(implicit ctx: Context): Type =
if (parent.isType) {
- typedAheadType(parent).tpe
+ typedAheadType(parent, AnyTypeConstructorProto).tpe
} else {
val (core, targs) = stripApply(parent) match {
case TypeApply(core, targs) => (core, targs)
@@ -973,7 +974,8 @@ class Namer { typer: Typer =>
ensureUpToDate(sym.typeRef, dummyInfo)
ensureUpToDate(sym.typeRef.appliedTo(tparamSyms.map(_.typeRef)), TypeBounds.empty)
- etaExpandArgs.apply(sym.info)
+ if (Config.newHK) sym.info
+ else etaExpandArgsOBS.apply(sym.info)
}
/** Eta expand all class types C appearing as arguments to a higher-kinded
@@ -982,7 +984,7 @@ class Namer { typer: Typer =>
* of arguments in F-bounds, because the recursive type was initialized with
* TypeBounds.empty.
*/
- def etaExpandArgs(implicit ctx: Context) = new TypeMap {
+ def etaExpandArgsOBS(implicit ctx: Context) = new TypeMap {
def apply(tp: Type): Type = tp match {
case tp: RefinedType =>
val args = tp.argInfos.mapconserve(this)
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index 740258821..68fd99b3f 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -311,6 +311,9 @@ object ProtoTypes {
*/
@sharable object AnyFunctionProto extends UncachedGroundType with MatchAlways
+ /** A prototype for type constructors that are followed by a type application */
+ @sharable object AnyTypeConstructorProto extends UncachedGroundType with MatchAlways
+
/** Add all parameters in given polytype `pt` to the constraint's domain.
* If the constraint contains already some of these parameters in its domain,
* make a copy of the polytype and add the copy's type parameters instead.
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 225516503..33a94f5c7 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -928,7 +928,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(implicit ctx: Context): Tree = track("typedAppliedTypeTree") {
- val tpt1 = typed(tree.tpt)(ctx retractMode Mode.Pattern)
+ val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(ctx.retractMode(Mode.Pattern))
val tparams = tpt1.tpe.typeParams
if (tparams.isEmpty) {
ctx.error(d"${tpt1.tpe} does not take type parameters", tree.pos)
@@ -1672,6 +1672,17 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
+ def adaptType(tp: Type): Tree = {
+ val tree1 =
+ if (pt != AnyTypeConstructorProto && tp.typeParamSymbols.nonEmpty) {
+ println(i"lam abs $tp with tparams ${tp.typeParamSymbols}%, %")
+ tree.withType(tree.tpe.EtaExpand(tp.typeParamSymbols))
+ }
+ else tree
+ if ((ctx.mode is Mode.Pattern) || tree1.tpe <:< pt) tree1
+ else err.typeMismatch(tree1, pt)
+ }
+
tree match {
case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[_] => tree
case _ => tree.tpe.widen match {
@@ -1705,9 +1716,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
(_, _) => tree // error will be reported in typedTypeApply
}
case _ =>
- if (ctx.mode is Mode.Type)
- if ((ctx.mode is Mode.Pattern) || tree.tpe <:< pt) tree
- else err.typeMismatch(tree, pt)
+ if (ctx.mode is Mode.Type) adaptType(tree.tpe)
else adaptNoArgs(wtp)
}
}
diff --git a/tests/neg/kinds.scala b/tests/neg/kinds.scala
new file mode 100644
index 000000000..312c5d45e
--- /dev/null
+++ b/tests/neg/kinds.scala
@@ -0,0 +1,18 @@
+object Test {
+
+ class C[T]
+ class C2[T[X]]
+
+ class B
+
+ val x: C[C] = ??? // error: missing type parameter(s)
+ val y: C2[C] = ???
+
+ def f[T] = ???
+
+ def f2[T[X]] = ???
+
+ f[C] // error: missing type parameter(s)
+ f2[C]
+
+}
diff --git a/tests/pos/jon.scala b/tests/pos/jon.scala
index d4ea74f02..224486945 100644
--- a/tests/pos/jon.scala
+++ b/tests/pos/jon.scala
@@ -4,5 +4,5 @@ object Test {
val x = List(List, Vector)
- val y: List[scala.collection.generic.SeqFactory] = x
+ val y: List[scala.collection.generic.SeqFactory[_]] = x
}
diff --git a/tests/pos/range.scala b/tests/pos/range.scala
index 9e7b5d1c9..a33f7fcee 100644
--- a/tests/pos/range.scala
+++ b/tests/pos/range.scala
@@ -1,8 +1,8 @@
import scala.math._
import collection.immutable.NumericRange
object Test {
- val r1: scala.collection.immutable.Range.Partial = ???
- val r2: scala.Range.Partial = r1
+ val r1: scala.collection.immutable.Range.Partial[_, _] = ???
+ val r2: scala.Range.Partial[_, _] = r1
def until(d: BigDecimal, end: BigDecimal): Range.Partial[BigDecimal, NumericRange.Exclusive[BigDecimal]] =
new Range.Partial(until(d, end, _))
def until(d: BigDecimal, end: BigDecimal, step: BigDecimal) = Range.BigDecimal(d, end, step)
diff --git a/tests/pos/t2613.scala b/tests/pos/t2613.scala
index c234d4c0d..17ebe2d7e 100644
--- a/tests/pos/t2613.scala
+++ b/tests/pos/t2613.scala
@@ -5,7 +5,7 @@ object Test {
abstract class MyRelation [R <: Row, +Relation <: MyRelation[R, Relation]]
- type M = MyRelation[_ <: Row, _ <: MyRelation]
+ type M = MyRelation[_ <: Row, _ <: MyRelation[_, _]]
val (x,y): (String, M) = null
}
diff --git a/tests/pos/tycons.scala b/tests/pos/tycons.scala
deleted file mode 100644
index 1ed4d2855..000000000
--- a/tests/pos/tycons.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-class TypeConstructor {
- type TypeArg
-}
-
-trait List[+T] extends TypeConstructor { type TypeArg <: T }
-
-trait Set[T] extends TypeConstructor { type TypeArg <: T }
-
-object obj extends List[Number] with Set[Exception] {
- val x: TypeArg = ???
- val n: Number = x
- val e: Exception = x
-}
-
-abstract class Functor[F <: TypeConstructor] {
- def map[A, B](f: F { type TypeArg <: A }): F { type TypeArg <: B }
-}
-
-object ListFunctor extends Functor[List] {
- override def map[A, B](f: List { type TypeArg <: A }): List { type TypeArg <: B } = ???
-}
-