diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 77885417a443..e5021e5b955e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -88,8 +88,8 @@ object desugar { else { def msg = s"no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope.toList}" - ErrorType(msg).assertingErrorsReported(msg) - } + ErrorType(msg).assertingErrorsReported(msg) + } case _ => mapOver(tp) } @@ -366,6 +366,12 @@ object desugar { (if (args.isEmpty) tycon else AppliedTypeTree(tycon, args)) .withPos(cdef.pos.startPos) + def isHK(tparam: Tree): Boolean = tparam match { + case TypeDef(_, LambdaTypeTree(tparams, body)) => true + case TypeDef(_, rhs: DerivedTypeTree) => isHK(rhs.watched) + case _ => false + } + def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams, widenHK: Boolean = false) = { val targs = for (tparam <- tparams) yield { val targ = refOfDef(tparam) @@ -467,18 +473,29 @@ object desugar { // ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]]) // : Eq[C[T1$, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq // - // If any of the T_i are higher-kinded, say `Ti[X1 >: L1 <: U1, ..., Xm >: Lm <: Um]`, - // the corresponding type parameters for $ev_i are `Ti$1[_, ..., _], Ti$2[_, ..., _]` - // (with m underscores `_`). + // Higher-kinded type arguments `Ti` are omitted as evidence parameters. + // + // FIXME: This is too simplistic. Instead of just generating evidence arguments + // for every first-kinded type parameter, we should look instead at the + // actual types occurring in cases and derive parameters from these. E.g. in + // + // enum HK[F[_]] { + // case C1(x: F[Int]) extends HK[F[Int]] + // case C2(y: F[String]) extends HL[F[Int]] + // + // we would need evidence parameters for `F[Int]` and `F[String]` + // We should generate Eq instances with the techniques + // of typeclass derivation once that is available. def eqInstance = { val leftParams = constrTparams.map(derivedTypeParam(_, "$1")) val rightParams = constrTparams.map(derivedTypeParam(_, "$2")) - val subInstances = (leftParams, rightParams).zipped.map((param1, param2) => - appliedRef(ref(defn.EqType), List(param1, param2), widenHK = true)) + val subInstances = + for ((param1, param2) <- leftParams `zip` rightParams if !isHK(param1)) + yield appliedRef(ref(defn.EqType), List(param1, param2), widenHK = true) DefDef( name = nme.eqInstance, tparams = leftParams ++ rightParams, - vparamss = List(makeImplicitParameters(subInstances)), + vparamss = if (subInstances.isEmpty) Nil else List(makeImplicitParameters(subInstances)), tpt = appliedTypeTree(ref(defn.EqType), appliedRef(classTycon, leftParams) :: appliedRef(classTycon, rightParams) :: Nil), rhs = ref(defn.EqModule.termRef)).withFlags(Synthetic | Implicit) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index bfad8f6739f6..674b9d232502 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -9,7 +9,6 @@ import Symbols._ import Contexts._ import Decorators.PreNamedString import util.NameTransformer -import scala.collection.breakOut object StdNames { diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 6db3ecf9f1a9..6e4df46b6530 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -31,6 +31,7 @@ import io.AbstractFile import language.implicitConversions import util.{NoSource, DotClass, Property} import scala.collection.JavaConverters._ +import config.Printers.typr /** Creation methods for symbols */ trait Symbols { this: Context => @@ -234,8 +235,8 @@ trait Symbols { this: Context => def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null): Symbol = { def stubCompleter = new StubInfo() val normalizedOwner = if (owner is ModuleVal) owner.moduleClass else owner - println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") - println(s"decls = ${normalizedOwner.unforcedDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG + typr.println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") + typr.println(s"decls = ${normalizedOwner.unforcedDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG //if (base.settings.debug.value) throw new Error() val stub = name match { case name: TermName => diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 91c669edbf07..d2e122b7bfe8 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -631,7 +631,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case EtaExpansion(tycon1) => recur(tycon1, tp2) case _ => tp2 match { case tp2: HKTypeLambda => false // this case was covered in thirdTry - case _ => tp2.isLambdaSub && isSubType(tp1.resultType, tp2.appliedTo(tp1.paramRefs)) + case _ => tp2.typeParams.hasSameLengthAs(tp1.paramRefs) && isSubType(tp1.resultType, tp2.appliedTo(tp1.paramRefs)) } } compareHKLambda diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 3de52cb16f87..9e08d013b1b8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -29,7 +29,7 @@ import dotty.tools.dotc.transform.Erasure import printing.Printer import Hashable._ import Uniques._ -import collection.{mutable, Seq, breakOut} +import collection.{mutable, Seq} import config.Config import annotation.tailrec import Flags.FlagSet diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 291d3102a235..1fedfa37f219 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -86,15 +86,11 @@ object Checking { if (boundsCheck) checkBounds(orderedArgs, bounds, instantiate) def checkWildcardApply(tp: Type, pos: Position): Unit = tp match { - case tp @ AppliedType(tycon, args) if args.exists(_.isInstanceOf[TypeBounds]) => - tycon match { - case tycon: TypeLambda => - ctx.errorOrMigrationWarning( - ex"unreducible application of higher-kinded type $tycon to wildcard arguments", - pos) - case _ => - checkWildcardApply(tp.superType, pos) - } + case tp @ AppliedType(tycon, args) => + if (tycon.isLambdaSub && args.exists(_.isInstanceOf[TypeBounds])) + ctx.errorOrMigrationWarning( + ex"unreducible application of higher-kinded type $tycon to wildcard arguments", + pos) case _ => } def checkValidIfApply(implicit ctx: Context): Unit = diff --git a/tests/neg/i3976.scala b/tests/neg/i3976.scala index 9462ce583fa6..d1892749dc0a 100644 --- a/tests/neg/i3976.scala +++ b/tests/neg/i3976.scala @@ -8,7 +8,7 @@ object Test { A == A A == (B: Hoge[_]) - A == B // error: cannot be compared + A == B // should be error: cannot be compared, needs proper typeclass drivation of `Eq` to get there. class C diff --git a/tests/neg/i4382.scala b/tests/neg/i4382.scala new file mode 100644 index 000000000000..aefe23094ce9 --- /dev/null +++ b/tests/neg/i4382.scala @@ -0,0 +1,13 @@ +object App { + type Id[A] >: A <: A + def v1: Id[_] = ??? // error + + type HkL[A] >: A + def v2: HkL[_] = ??? // error + + type HkU[A] <: A + def v3: HkU[_] = ??? // error + + type HkAbs[A] + def v4: HkAbs[_] = ??? // error +} diff --git a/tests/pos/hk-infer.scala b/tests/pos-scala2/hk-infer.scala similarity index 100% rename from tests/pos/hk-infer.scala rename to tests/pos-scala2/hk-infer.scala diff --git a/tests/pos/hkwild.scala b/tests/pos-scala2/hkwild.scala similarity index 100% rename from tests/pos/hkwild.scala rename to tests/pos-scala2/hkwild.scala diff --git a/tests/pos/i2201b.scala b/tests/pos-scala2/i2201b.scala similarity index 100% rename from tests/pos/i2201b.scala rename to tests/pos-scala2/i2201b.scala diff --git a/tests/pos/i2219.scala b/tests/pos-scala2/i2219.scala similarity index 100% rename from tests/pos/i2219.scala rename to tests/pos-scala2/i2219.scala