diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 9354e18f86a8..64fb8764ebb6 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -8,6 +8,7 @@ import collection.mutable import printing.{Printer, Showable} import printing.Texts._ import config.Config +import config.Printers._ /** Constraint over undetermined type parameters * @param myMap a map from PolyType to arrays. @@ -304,5 +305,5 @@ trait ConstraintRunInfo { self: RunInfo => maxConstraint = c } def printMaxConstraint()(implicit ctx: Context) = - if (maxSize > 0) println(s"max constraint = ${maxConstraint.show}") + if (maxSize > 0) typr.println(s"max constraint = ${maxConstraint.show}") } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 9914485ac3cb..56be3ef1ed21 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -12,36 +12,39 @@ class tests extends CompilerTest { // "-Xprompt", // "-explaintypes", // "-Yshow-suppressed-errors", - "#runs", "2", - "-pagewidth", "160") + "-pagewidth", "160" + ) + val twice = List("#runs", "2") val posDir = "./tests/pos/" val negDir = "./tests/neg/" val dotcDir = "./src/dotty/" - - @Test def pos_Coder() = compileFile(posDir, "Coder") - @Test def pos_blockescapes() = compileFile(posDir, "blockescapes") - @Test def pos_collections() = compileFile(posDir, "collections") - @Test def pos_functions1() = compileFile(posDir, "functions1") - @Test def pos_implicits1() = compileFile(posDir, "implicits1") - @Test def pos_inferred() = compileFile(posDir, "inferred") - @Test def pos_Patterns() = compileFile(posDir, "Patterns") - @Test def pos_selftypes() = compileFile(posDir, "selftypes") - @Test def pos_varargs() = compileFile(posDir, "varargs") - @Test def pos_opassign() = compileFile(posDir, "opassign") - @Test def pos_typedapply() = compileFile(posDir, "typedapply") - @Test def pos_nameddefaults() = compileFile(posDir, "nameddefaults") - @Test def pos_desugar() = compileFile(posDir, "desugar") - @Test def pos_sigs() = compileFile(posDir, "sigs") - @Test def pos_typers() = compileFile(posDir, "typers") - @Test def pos_typedidents() = compileFile(posDir, "typedIdents") - @Test def pos_assignments() = compileFile(posDir, "assignments") - @Test def pos_packageobject() = compileFile(posDir, "packageobject") - @Test def pos_overloaded() = compileFile(posDir, "overloaded") - @Test def pos_templateParents() = compileFile(posDir, "templateParents") - @Test def pos_structural() = compileFile(posDir, "structural") - @Test def pos_i39 = compileFile(posDir, "i39") - @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess") +/* + @Test def pos_Coder() = compileFile(posDir, "Coder", twice) + @Test def pos_blockescapes() = compileFile(posDir, "blockescapes", twice) + @Test def pos_collections() = compileFile(posDir, "collections", twice) + @Test def pos_functions1() = compileFile(posDir, "functions1", twice) + @Test def pos_implicits1() = compileFile(posDir, "implicits1", twice) + @Test def pos_inferred() = compileFile(posDir, "inferred", twice) + @Test def pos_Patterns() = compileFile(posDir, "Patterns", twice) + @Test def pos_selftypes() = compileFile(posDir, "selftypes", twice) + @Test def pos_varargs() = compileFile(posDir, "varargs", twice) + @Test def pos_opassign() = compileFile(posDir, "opassign", twice) + @Test def pos_typedapply() = compileFile(posDir, "typedapply", twice) + @Test def pos_nameddefaults() = compileFile(posDir, "nameddefaults", twice) + @Test def pos_desugar() = compileFile(posDir, "desugar", twice) + @Test def pos_sigs() = compileFile(posDir, "sigs", twice) + @Test def pos_typers() = compileFile(posDir, "typers", twice) + @Test def pos_typedidents() = compileFile(posDir, "typedIdents", twice) + @Test def pos_assignments() = compileFile(posDir, "assignments", twice) + @Test def pos_packageobject() = compileFile(posDir, "packageobject", twice) + @Test def pos_overloaded() = compileFile(posDir, "overloaded", twice) + @Test def pos_templateParents() = compileFile(posDir, "templateParents", twice) + @Test def pos_structural() = compileFile(posDir, "structural", twice) + @Test def pos_i39 = compileFile(posDir, "i39", twice) + @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess", twice) +*/ + @Test def pos_all = compileFiles(posDir, twice) @Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 1) @Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4) @@ -53,32 +56,34 @@ class tests extends CompilerTest { @Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3) @Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1) - @Test def dotc = compileDir(dotcDir + "tools/dotc") - @Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast") - @Test def dotc_config = compileDir(dotcDir + "tools/dotc/config") - @Test def dotc_core = compileDir(dotcDir + "tools/dotc/core") - @Test def dotc_core_pickling = compileDir(dotcDir + "tools/dotc/core/pickling") - @Test def dotc_transform = compileDir(dotcDir + "tools/dotc/core/transform") - @Test def dotc_parsing = compileDir(dotcDir + "tools/dotc/parsing") - @Test def dotc_printing = compileDir(dotcDir + "tools/dotc/printing") - @Test def dotc_reporting = compileDir(dotcDir + "tools/dotc/reporting") - @Test def dotc_typer = compileDir(dotcDir + "tools/dotc/typer") - @Test def dotc_util = compileDir(dotcDir + "tools/dotc/util") - @Test def tools_io = compileDir(dotcDir + "tools/io") - @Test def tools = compileDir(dotcDir + "tools") + @Test def dotc = compileDir(dotcDir + "tools/dotc", twice) + @Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", twice) + @Test def dotc_config = compileDir(dotcDir + "tools/dotc/config", twice) + @Test def dotc_core = compileDir(dotcDir + "tools/dotc/core", twice) + @Test def dotc_core_pickling = compileDir(dotcDir + "tools/dotc/core/pickling", twice) + @Test def dotc_transform = compileDir(dotcDir + "tools/dotc/core/transform", twice) + @Test def dotc_parsing = compileDir(dotcDir + "tools/dotc/parsing", twice) + @Test def dotc_printing = compileDir(dotcDir + "tools/dotc/printing", twice) + @Test def dotc_reporting = compileDir(dotcDir + "tools/dotc/reporting", twice) + @Test def dotc_typer = compileDir(dotcDir + "tools/dotc/typer", twice) + @Test def dotc_util = compileDir(dotcDir + "tools/dotc/util", twice) + @Test def tools_io = compileDir(dotcDir + "tools/io", twice) + @Test def tools = compileDir(dotcDir + "tools", twice) @Test def testNonCyclic = compileArgs(Array( dotcDir + "tools/dotc/CompilationUnit.scala", dotcDir + "tools/dotc/core/Types.scala", dotcDir + "tools/dotc/ast/Trees.scala", "-Ylog:frontend", - "-Xprompt")) + "-Xprompt", + "#runs", "2")) @Test def testIssue_34 = compileArgs(Array( dotcDir + "tools/dotc/config/Properties.scala", dotcDir + "tools/dotc/config/PathResolver.scala", "-Ylog:frontend", - "-Xprompt")) + "-Xprompt", + "#runs", "2")) //@Test def dotc_compilercommand = compileFile(dotcDir + "tools/dotc/config/", "CompilerCommand") } diff --git a/test/test/CompilerTest.scala b/test/test/CompilerTest.scala index 26a0b3831f97..d25cfb637eb6 100644 --- a/test/test/CompilerTest.scala +++ b/test/test/CompilerTest.scala @@ -22,12 +22,26 @@ class CompilerTest extends DottyTest { def compileFile(prefix: String, fileName: String, args: List[String] = Nil, xerrors: Int = 0): Unit = compileArgs((s"$prefix$fileName.scala" :: args).toArray, xerrors) - def compileDir(path: String, args: List[String] = Nil, xerrors: Int = 0): Unit = { - val dir = Directory(path) + def compileDir(path: String, args: List[String] = Nil, xerrors: Int = 0): Unit = + compileDir(Directory(path), args, xerrors) + + def compileDir(dir: Directory, args: List[String], xerrors: Int): Unit = { val fileNames = dir.files.toArray.map(_.toString).filter(_ endsWith ".scala") compileArgs(fileNames ++ args, xerrors) } + def compileFiles(path: String, args: List[String] = Nil): Unit = { + val dir = Directory(path) + val fileNames = dir.files.toArray.map(_.toString).filter(_ endsWith ".scala") + for (name <- fileNames) { + println(s"testing $name") + compileArgs((name :: args).toArray, 0) + } + for (subdir <- dir.dirs) { + println(s"testing $subdir") + compileDir(subdir, args, 0) + } + } } object CompilerText extends App { diff --git a/tests/pos/dotctest.scala b/tests/pos/dotctest.scala deleted file mode 100644 index b47cc921c295..000000000000 --- a/tests/pos/dotctest.scala +++ /dev/null @@ -1,264 +0,0 @@ -package dotty.tools -package dotc -package core - -import Types._, Contexts._, Symbols._ -import util.SimpleMap -import collection.mutable -import printing.{Printer, Showable} -import printing.Texts._ -import config.Config - -/** Constraint over undetermined type parameters - * @param myMap a map from PolyType to arrays. - * Each array contains twice the number of entries as there a type parameters - * in the PolyType. The first half of the array contains the type bounds that constrain the - * polytype's type parameters. The second half might contain type variables that - * track the corresponding parameters, or is left empty (filled with nulls). - * An instantiated type parameter is represented by having its instance type in - * the corresponding array entry. - */ -class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal with Showable { - - /** Does the constraint's domain contain the type parameters of `pt`? */ - def contains(pt: PolyType): Boolean = myMap(pt) != null - - /** Does the constraint's domain contain the type parameter `param`? */ - def contains(param: PolyParam): Boolean = { - val entries = myMap(param.binder) - entries != null && entries(param.paramNum).isInstanceOf[TypeBounds] - } - - /** Does this constraint contain the type variable `tvar` and is it uninstantiated? */ - def contains(tvar: TypeVar): Boolean = { - val origin = tvar.origin - val entries = myMap(origin.binder) - val pnum = origin.paramNum - entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eq tvar) - } - - /** The number of type parameters in the given entry array */ - private def paramCount(entries: Array[Type]) = entries.length >> 1 - - /** The type variable corresponding to parameter numbered `n`, null if none was created */ - private def typeVar(entries: Array[Type], n: Int): Type = - entries(paramCount(entries) + n) - - private def isBounds(tp: Type) = tp.isInstanceOf[TypeBounds] - - /** The constraint for given type parameter `param`, or NoType if `param` is not part of - * the constraint domain. - */ - def at(param: PolyParam): Type = { - val entries = myMap(param.binder) - if (entries == null) NoType else entries(param.paramNum) - } - - /** The constraint bounds for given type parameter `param`. - * @pre `param` is not part of the constraint domain. - */ - def bounds(param: PolyParam): TypeBounds = at(param).asInstanceOf[TypeBounds] - - /** The type variable corresponding to parameter `param`, or - * NoType, if `param` is not in constrained or is not paired with a type variable. - */ - def typeVarOfParam(param: PolyParam): Type = { - val entries = myMap(param.binder) - if (entries == null) NoType - else typeVar(entries, param.paramNum) - } - - /** A new constraint which is derived from this constraint by adding or replacing - * the entries corresponding to `pt` with `entries`. - */ - private def updateEntries(pt: PolyType, entries: Array[Type]): Constraint = { - import Constraint._ - val res = new Constraint(myMap.updated(pt, entries)) - if (Config.checkConstraintsNonCyclic) checkNonCyclic(pt, entries) - if (res.myMap.size > maxSize) { - maxSize = res.myMap.size - maxConstraint = res - } - res - } - - /** Check that no constrained parameter contains itself as a bound */ - def checkNonCyclic(pt: PolyType, entries: Array[Type]) = - for ((entry, i) <- entries.zipWithIndex) { - val param = PolyParam(pt, i) - entry match { - case TypeBounds(lo, hi) => - assert(!param.occursIn(lo, fromBelow = false), s"$param occurs above $lo") - assert(!param.occursIn(hi, fromBelow = true), s"$param occurs below $hi") - case _ => - } - } - - /** A new constraint which is derived from this constraint by updating - * the entry for parameter `param` to `tpe`. - * @pre `this contains param`. - */ - def updated(param: PolyParam, tpe: Type): Constraint = { - val newEntries = myMap(param.binder).clone - newEntries(param.paramNum) = tpe - updateEntries(param.binder, newEntries) - } - - /** A new constraint which is derived from this constraint by mapping - * `op` over all entries of type `poly`. - * @pre `this contains poly`. - */ - def transformed(poly: PolyType, op: Type => Type): Constraint = - updateEntries(poly, myMap(poly) map op) - - /** A new constraint with all entries coming from `pt` removed. */ - def remove(pt: PolyType) = new Constraint(myMap remove pt) - - /** Is entry associated with `pt` removable? - * @param removedParam The index of a parameter which is still present in the - * entry array, but is going to be removed at the same step, - * or -1 if no such parameter exists. - */ - def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean = { - val entries = myMap(pt) - var noneLeft = true - var i = paramCount(entries) - while (noneLeft && i > 0) { - i -= 1 - if (i != removedParam && isBounds(entries(i))) noneLeft = false - else typeVar(entries, i) match { - case tv: TypeVar => - if (!tv.inst.exists) noneLeft = false // need to keep line around to compute instType - case _ => - } - } - noneLeft - } - - /** Drop parameter `PolyParam(poly, n)` from `bounds`, - * replacing with Nothing in the lower bound and by `Any` in the upper bound. - */ - def dropParamIn(bounds: TypeBounds, poly: PolyType, n: Int)(implicit ctx: Context): TypeBounds = { - def drop(tp: Type): Type = tp match { - case tp: AndOrType => - val tp1 = drop(tp.tp1) - val tp2 = drop(tp.tp2) - if (!tp1.exists) tp2 - else if (!tp2.exists) tp1 - else tp - case PolyParam(`poly`, `n`) => NoType - case _ => tp - } - def approx(tp: Type, limit: Type): Type = { - val tp1 = drop(tp) - if (tp1.exists || !tp.exists) tp1 else limit - } - bounds.derivedTypeBounds( - approx(bounds.lo, defn.NothingType), approx(bounds.hi, defn.AnyType)) - } - - /** A new constraint which is derived from this constraint by removing - * the type parameter `param` from the domain and replacing all occurrences - * of the parameter elsewhere in the constraint by type `tp`. - */ - def replace(param: PolyParam, tp: Type)(implicit ctx: Context): Constraint = { - - def subst(poly: PolyType, entries: Array[Type]) = { - var result = entries - var i = 0 - while (i < paramCount(entries)) { - entries(i) match { - case oldBounds: TypeBounds => - val newBounds = oldBounds.substParam(param, tp).asInstanceOf[TypeBounds] - if (oldBounds ne newBounds) { - if (result eq entries) result = entries.clone - result(i) = dropParamIn(newBounds, poly, i) - } - case _ => - } - i += 1 - } - result - } - - val pt = param.binder - val constr1 = if (isRemovable(pt, param.paramNum)) remove(pt) else updated(param, tp) - new Constraint(constr1.myMap mapValues subst) - } - - /** A new constraint which is derived from this constraint by adding - * entries for all type parameters of `poly`. - */ - def add(poly: PolyType, tvars: List[TypeVar] = Nil): Constraint = { - val nparams = poly.paramNames.length - val entries = new Array[Type](nparams * 2) - poly.paramBounds.copyToArray(entries, 0) - tvars.copyToArray(entries, nparams) - updateEntries(poly, entries) - } - - /** The polytypes constrained by this constraint */ - def domainPolys: List[PolyType] = myMap.keys - - /** The polytype parameters constrained by this constraint */ - def domainParams: List[PolyParam] = - for { - (poly, entries) <- myMap.toList - n <- 0 until paramCount(entries) - if isBounds(entries(n)) - } yield PolyParam(poly, n) - - /** Perform operation `op` on all typevars, or only on uninstantiated - * typevars, depending on whether `uninstOnly` is set or not. - */ - def foreachTypeVar(op: TypeVar => Unit, uninstOnly: Boolean = false): Unit = - myMap.foreachBinding { (poly, entries) => - for (i <- 0 until paramCount(entries)) { - def qualifies(tv: TypeVar) = - if (uninstOnly) isBounds(entries(i)) else !tv.inst.exists - typeVar(entries, i) match { - case tv: TypeVar if qualifies(tv) => op(tv) - case _ => - } - } - } - - /** Perform operation `op` on all uninstantiated typevars. - */ - def foreachUninstVar(op: TypeVar => Unit): Unit = foreachTypeVar(op, uninstOnly = true) - - /** The uninstantiated typevars of this constraint */ - def uninstVars: collection.Seq[TypeVar] = { - val buf = new mutable.ArrayBuffer[TypeVar] - foreachUninstVar(buf += _) - buf - } - - def constrainedTypesText(printer: Printer): Text = - Text(domainPolys map (_.toText(printer)), ", ") - - def constraintText(indent: Int, printer: Printer): Text = { - val assocs = - for (param <- domainParams) - yield (" " * indent) ~ param.toText(printer) ~ at(param).toText(printer) - Text(assocs, "\n") - } - - override def toText(printer: Printer): Text = { - val header: Text = "Constraint(" - val uninstVarsText = " uninstVars = " ~ - Text(uninstVars map (_.toText(printer)), ", ") ~ ";" - val constrainedText = - " constrained types = " ~ constrainedTypesText(printer) ~ ";" - val constraintsText = - " constraint = " ~ constraintText(3, printer) ~ ")" - Text.lines(List(header, uninstVarsText, constrainedText, constraintsText)) - } -} - -object Constraint { - var maxSize = 0 - var maxConstraint: Constraint = _ - def printMax()(implicit ctx: Context) = - if (maxSize > 0) println(s"max constraint = ${maxConstraint.show}") -}