From 0d532d5f3384c769c2a620b0ace04f89b2ce09ac Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 30 Apr 2018 18:14:46 +0200 Subject: [PATCH 1/4] Don't be noise when generating stubs Use typr printer instead. --- compiler/src/dotty/tools/dotc/core/Symbols.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 => From 1d044273926e48e70af90b6b584854ca4d1e5e10 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 30 Apr 2018 18:19:02 +0200 Subject: [PATCH 2/4] Fix #4382: Fix checking that hk types cannot take wildcard arguments Four existing test cases had to be reclassified to require -language:Scala2. --- compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 - compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Checking.scala | 14 +++++--------- tests/neg/i4382.scala | 13 +++++++++++++ tests/{pos => pos-scala2}/hk-infer.scala | 0 tests/{pos => pos-scala2}/hkwild.scala | 0 tests/{pos => pos-scala2}/i2201b.scala | 0 tests/{pos => pos-scala2}/i2219.scala | 0 8 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 tests/neg/i4382.scala rename tests/{pos => pos-scala2}/hk-infer.scala (100%) rename tests/{pos => pos-scala2}/hkwild.scala (100%) rename tests/{pos => pos-scala2}/i2201b.scala (100%) rename tests/{pos => pos-scala2}/i2219.scala (100%) 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/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/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 From c2d8fa60248652838e2ccabd964c1a930f05508e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 30 Apr 2018 18:23:51 +0200 Subject: [PATCH 3/4] Fix desugaring of higher-kinded enums This previous encoding used a higher-kinded type applied to a wildcard argument, which is no longer supported. The new encoding is a temporary fix. To get it right, it's best if we can base it on the future typeclass derivation mechanism. --- .../src/dotty/tools/dotc/ast/Desugar.scala | 29 +++++++++++++++---- tests/neg/i3976.scala | 2 +- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 77885417a443..2223e7649f7d 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -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/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 From 5636765cb5e6ac40855c477e2a1bee8814e649cd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 30 Apr 2018 20:34:16 +0200 Subject: [PATCH 4/4] Generalize condition in TypeComparer I don't have a test, but it makes more sense this way. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 2223e7649f7d..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) } 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