diff options
61 files changed, 395 insertions, 242 deletions
diff --git a/project/Build.scala b/project/Build.scala index 79cb7d9b7..473ef2443 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -42,7 +42,7 @@ object DottyBuild extends Build { resolvers += Resolver.sonatypeRepo("releases"), // get libraries onboard - partestDeps := Seq("me.d-d" % "scala-compiler" % "2.11.5-20150506-175515-8fc7635b56", + partestDeps := Seq("me.d-d" % "scala-compiler" % "2.11.5-20150619-173733-3bcd390afa", "org.scala-lang" % "scala-reflect" % scalaVersion.value, "org.scala-lang" % "scala-library" % scalaVersion.value % "test"), libraryDependencies ++= partestDeps.value, diff --git a/src/dotty/runtime/Arrays.scala b/src/dotty/runtime/Arrays.scala index 1fb4fe5eb..4469dced7 100644 --- a/src/dotty/runtime/Arrays.scala +++ b/src/dotty/runtime/Arrays.scala @@ -7,6 +7,8 @@ import scala.reflect.ClassTag */ object Arrays { + // note: this class is magical. Do not touch it unless you know what you are doing.` + /** Creates an array of some element type determined by the given `ClassTag` * argument. The erased type of applications of this method is `Object`. */ diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 855147ac4..4a828c5bd 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -157,9 +157,16 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ }.toMap def unboxMethods: Map[Symbol, Symbol] = defn.ScalaValueClasses.map(x => (x, Erasure.Boxing.unboxMethod(x.asClass))).toMap - private val mkArrayNames: Set[String] = Set("Byte", "Float", "Char", "Double", "Boolean", "Unit", "Long", "Int", "Short", "Ref") + private val mkArrayNames: Set[Name] = Set("Byte", "Float", "Char", "Double", "Boolean", "Unit", "Long", "Int", "Short", "Ref").map{ x=> + ("new" + x + "Array").toTermName + } + + val dottyArraysModuleClass = toDenot(defn.DottyArraysModule).moduleClass.asClass - override lazy val syntheticArrayConstructors: Set[Symbol] = mkArrayNames.map(nm => ctx.requiredMethod(toDenot(defn.DottyArraysModule).moduleClass.asClass, s"new${nm}Array")) + + override def isSyntheticArrayConstructor(s: Symbol) = { + (toDenot(s).maybeOwner eq dottyArraysModuleClass) && mkArrayNames.contains(s.name) + } def isBox(sym: Symbol): Boolean = Erasure.Boxing.isBox(sym) def isUnbox(sym: Symbol): Boolean = Erasure.Boxing.isUnbox(sym) @@ -480,7 +487,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ implicit def positionHelper(a: Position): PositionHelper = new PositionHelper { def isDefined: Boolean = a.exists - def line: Int = sourcePos(a).line + def line: Int = sourcePos(a).line + 1 def finalPosition: Position = a } diff --git a/src/dotty/tools/dotc/Bench.scala b/src/dotty/tools/dotc/Bench.scala index 2e0e15e83..417054dce 100644 --- a/src/dotty/tools/dotc/Bench.scala +++ b/src/dotty/tools/dotc/Bench.scala @@ -8,19 +8,7 @@ package dotc import core.Contexts.Context import reporting.Reporter -/* To do: - * - simplify hk types - * - have a second look at normalization (leave at method types if pt is method type?) - * - Don't open package objects from class files if they are present in source - * - Revise the way classes are inherited - when not followed by [...] or (...), - * assume the unparameterized type and forward type parameters as we do now for the synthetic head class. - */ object Bench extends Driver { - def resident(compiler: Compiler): Reporter = unsupported("resident") /*loop { line => - val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError)) - compiler.reporter.reset() - new compiler.Run() compile command.files - }*/ private var numRuns = 1 @@ -30,15 +18,12 @@ object Bench extends Driver { (emptyReporter /: (0 until n)) ((_, _) => op) override def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter = - if (new config.Settings.Setting.SettingDecorator[Boolean](ctx.base.settings.resident).value(ctx)) - resident(compiler) - else - ntimes(numRuns) { - val start = System.nanoTime() - val r = super.doCompile(compiler, fileNames) - println(s"time elapsed: ${(System.nanoTime - start) / 1000000}ms") - r - } + ntimes(numRuns) { + val start = System.nanoTime() + val r = super.doCompile(compiler, fileNames) + println(s"time elapsed: ${(System.nanoTime - start) / 1000000}ms") + r + } def extractNumArg(args: Array[String], name: String, default: Int = 1): (Int, Array[String]) = { val pos = args indexOf name diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index a10201bd0..a14aa3655 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -7,7 +7,7 @@ import Periods._ import Symbols._ import Scopes._ import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks} -import reporting.ConsoleReporter +import reporting.{Reporter, ConsoleReporter} import Phases.Phase import dotty.tools.dotc.transform._ import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer} @@ -76,8 +76,7 @@ class Compiler { List(/*new PrivateToStatic,*/ new ExpandPrivate, new CollectEntryPoints, - new LabelDefs, - new TraitConstructors), + new LabelDefs), List(new GenBCode) ) @@ -106,13 +105,15 @@ class Compiler { .setOwner(defn.RootClass) .setTyper(new Typer) .setMode(Mode.ImplicitsEnabled) - .setTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx), isCommittable = true)) + .setTyperState(new MutableTyperState(ctx.typerState, rootReporter(ctx), isCommittable = true)) ctx.definitions.init(start) // set context of definitions to start def addImport(ctx: Context, symf: () => Symbol) = ctx.fresh.setImportInfo(ImportInfo.rootImport(symf)(ctx)) (start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport) } + protected def rootReporter(implicit ctx: Context): Reporter = new ConsoleReporter()(ctx) + def reset()(implicit ctx: Context): Unit = { ctx.base.reset() ctx.runInfo.clear() diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala index dc1431aca..7e9d4a5e4 100644 --- a/src/dotty/tools/dotc/Driver.scala +++ b/src/dotty/tools/dotc/Driver.scala @@ -8,32 +8,40 @@ import scala.util.control.NonFatal abstract class Driver extends DotClass { - val prompt = "\ndotc>" + val prompt = "\ndotc> " protected def newCompiler(): Compiler protected def emptyReporter: Reporter = new StoreReporter protected def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter = - if (fileNames.nonEmpty) { - val run = compiler.newRun - run.compile(fileNames) - run.printSummary() - } else emptyReporter + if (fileNames.nonEmpty) + try { + val run = compiler.newRun + run.compile(fileNames) + run.printSummary() + } + catch { + case ex: FatalError => + ctx.error(ex.getMessage) // signals that we should fail compilation. + ctx.typerState.reporter + } + else emptyReporter protected def initCtx = (new ContextBase).initialCtx - def process(args: Array[String], rootCtx: Context): Reporter = { + protected def sourcesRequired = true + + def setup(args: Array[String], rootCtx: Context): (List[String], Context) = { val summary = CompilerCommand.distill(args)(rootCtx) implicit val ctx: Context = initCtx.fresh.setSettings(summary.sstate) - val fileNames = CompilerCommand.checkUsage(summary) - try { - doCompile(newCompiler(), fileNames) - } catch { - case ex: FatalError => - ctx.error(ex.getMessage) // signals that we should fail compilation. - ctx.typerState.reporter - } + val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired) + (fileNames, ctx) + } + + def process(args: Array[String], rootCtx: Context): Reporter = { + val (fileNames, ctx) = setup(args, rootCtx) + doCompile(newCompiler(), fileNames)(ctx) } def main(args: Array[String]): Unit = diff --git a/src/dotty/tools/dotc/FromTasty.scala b/src/dotty/tools/dotc/FromTasty.scala index 019846396..705deedd3 100644 --- a/src/dotty/tools/dotc/FromTasty.scala +++ b/src/dotty/tools/dotc/FromTasty.scala @@ -12,6 +12,7 @@ import SymDenotations._ import typer.FrontEnd import Phases.Phase import util._ +import reporting.Reporter import Decorators._ import dotty.tools.dotc.transform.Pickler import tasty.DottyUnpickler diff --git a/src/dotty/tools/dotc/Main.scala b/src/dotty/tools/dotc/Main.scala index 0b136d72f..699a57234 100644 --- a/src/dotty/tools/dotc/Main.scala +++ b/src/dotty/tools/dotc/Main.scala @@ -1,7 +1,3 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Martin Odersky - */ package dotty.tools package dotc @@ -11,18 +7,5 @@ import reporting.Reporter /* To do: */ object Main extends Driver { - def resident(compiler: Compiler): Reporter = unsupported("resident") /*loop { line => - val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError)) - compiler.reporter.reset() - new compiler.Run() compile command.files - }*/ - override def newCompiler(): Compiler = new Compiler - - override def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter = { - if (new config.Settings.Setting.SettingDecorator[Boolean](ctx.base.settings.resident).value(ctx)) - resident(compiler) - else - super.doCompile(compiler, fileNames) - } } diff --git a/src/dotty/tools/dotc/Resident.scala b/src/dotty/tools/dotc/Resident.scala new file mode 100644 index 000000000..d671ea259 --- /dev/null +++ b/src/dotty/tools/dotc/Resident.scala @@ -0,0 +1,55 @@ +package dotty.tools +package dotc + +import core.Contexts.Context +import reporting.Reporter +import java.io.EOFException +import scala.annotation.tailrec + +/** A compiler which stays resident between runs. + * Usage: + * + * > scala dotty.tools.dotc.Resident <options> <initial files> + * + * dotc> "more options and files to compile" + * + * ... + * + * dotc> :reset // reset all options to the ones passed on the command line + * + * ... + * + * dotc> :q // quit + */ +object Resident extends Driver { + + object residentCompiler extends Compiler + + override def newCompiler(): Compiler = ??? + + override def sourcesRequired = false + + private val quit = ":q" + private val reset = ":reset" + + private def getLine() = { + Console.print(prompt) + try scala.io.StdIn.readLine() catch { case _: EOFException => quit } + } + + final override def process(args: Array[String], rootCtx: Context): Reporter = { + @tailrec def loop(args: Array[String], prevCtx: Context): Reporter = { + var (fileNames, ctx) = setup(args, prevCtx) + doCompile(residentCompiler, fileNames)(ctx) + var nextCtx = ctx + var line = getLine() + while (line == reset) { + nextCtx = rootCtx + line = getLine() + } + if (line.startsWith(quit)) ctx.typerState.reporter + else loop(line split "\\s+", nextCtx) + } + loop(args, rootCtx) + } +} diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index 401608a73..553805d95 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -33,7 +33,7 @@ class Run(comp: Compiler)(implicit ctx: Context) { compileSources(sources) } catch { case NonFatal(ex) => - println(i"exception occurred while compiling $units%, %") + ctx.println(i"exception occurred while compiling $units%, %") throw ex } @@ -55,7 +55,7 @@ class Run(comp: Compiler)(implicit ctx: Context) { ctx.usePhases(phases) for (phase <- ctx.allPhases) if (!ctx.reporter.hasErrors) { - if (ctx.settings.verbose.value) println(s"[$phase]") + if (ctx.settings.verbose.value) ctx.println(s"[$phase]") units = phase.runOn(units) def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit = for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) @@ -69,8 +69,8 @@ class Run(comp: Compiler)(implicit ctx: Context) { val prevPhase = ctx.phase.prev // can be a mini-phase val squashedPhase = ctx.squashed(prevPhase) - println(s"result of $unit after ${squashedPhase}:") - println(unit.tpdTree.show(ctx)) + ctx.println(s"result of $unit after ${squashedPhase}:") + ctx.println(unit.tpdTree.show(ctx)) } def compile(sourceCode: String): Unit = { diff --git a/src/dotty/tools/dotc/config/CompilerCommand.scala b/src/dotty/tools/dotc/config/CompilerCommand.scala index 3ba8db3ba..e34ca07f9 100644 --- a/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -60,7 +60,7 @@ object CompilerCommand extends DotClass { * are already applied in context. * @return The list of files to compile. */ - def checkUsage(summary: ArgsSummary)(implicit ctx: Context): List[String] = { + def checkUsage(summary: ArgsSummary, sourcesRequired: Boolean)(implicit ctx: Context): List[String] = { val settings = ctx.settings /** Creates a help message for a subset of options based on cond */ @@ -121,8 +121,7 @@ object CompilerCommand extends DotClass { ctx.println(infoMessage) Nil } else { - if (summary.arguments.isEmpty && !settings.resident.value) - ctx.println(usageMessage) + if (sourcesRequired && summary.arguments.isEmpty) ctx.println(usageMessage) summary.arguments } } diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index 782a2f2d3..97893647c 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -32,6 +32,17 @@ object Config { */ final val checkConstraintsPropagated = false + /** Check that constraints of globally committable typer states are closed. + * NOTE: When enabled, the check can cause CyclicReference errors because + * it traverses all elements of a type. Such failures were observed when + * compiling all of dotty together (source seems to be in GenBCode which + * accesses javac's settings.) + * + * It is recommended to turn this option on only when chasing down + * a PolyParam instantiation error. See comment in Types.TypeVar.instantiate. + */ + final val debugCheckConstraintsClosed = false + /** Check that no type appearing as the info of a SymDenotation contains * skolem types. */ diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index 2ba907084..f8c155cad 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -81,7 +81,6 @@ class ScalaSettings extends Settings.SettingGroup { val Xprintpos = BooleanSetting("-Xprint-pos", "Print tree positions, as offsets.") val printtypes = BooleanSetting("-Xprint-types", "Print tree types (debugging option).") val prompt = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).") - val resident = BooleanSetting("-Xresident", "Compiler stays resident: read source filenames from standard input.") val script = StringSetting("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "") val mainClass = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "") val Xshowcls = StringSetting("-Xshow-class", "class", "Show internal representation of class.", "") diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 5a758f144..19f93ce47 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -146,4 +146,7 @@ abstract class Constraint extends Showable { /** Check that no constrained parameter contains itself as a bound */ def checkNonCyclic()(implicit ctx: Context): Unit + + /** Check that constraint only refers to PolyParams bound by itself */ + def checkClosed()(implicit ctx: Context): Unit } diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 759dff0d4..f39f2bac6 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -388,7 +388,7 @@ object Flags { /** Symbol is a self name */ final val SelfName = termFlag(54, "<selfname>") - /** Symbol is an implementation class */ + /** Symbol is an implementation class of a Scala2 trait */ final val ImplClass = typeFlag(54, "<implclass>") final val SelfNameOrImplClass = SelfName.toCommonFlags diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index dc94f6db1..4d6cca61d 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -62,7 +62,7 @@ object NameOps { def likeTyped(n: Name): N = (if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N] - def isConstructorName = name == CONSTRUCTOR || name == IMPLCLASS_CONSTRUCTOR + def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX def isImplClassName = name endsWith IMPL_CLASS_SUFFIX def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala index 21d003451..7e27ee628 100644 --- a/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -399,7 +399,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def removeParam(ps: List[PolyParam]) = ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx) - def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int) = tp match { + def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match { case bounds @ TypeBounds(lo, hi) => def recombine(andor: AndOrType, op: (Type, Boolean) => Type, isUpper: Boolean): Type = { @@ -424,7 +424,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } bounds.derivedTypeBounds(replaceIn(lo, isUpper = false), replaceIn(hi, isUpper = true)) - case _ => tp + case _ => + tp.substParam(param, replacement) } var current = @@ -438,8 +439,16 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } } - def remove(pt: PolyType)(implicit ctx: Context): This = - newConstraint(boundsMap.remove(pt), lowerMap.remove(pt), upperMap.remove(pt)) + def remove(pt: PolyType)(implicit ctx: Context): This = { + def removeFromOrdering(po: ParamOrdering) = { + def removeFromBoundss(key: PolyType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = { + val bndss1 = bndss.map(_.filterConserve(_.binder ne pt)) + if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1 + } + po.remove(pt).mapValuesNow(removeFromBoundss) + } + newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap)) + } def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean = { val entries = boundsMap(pt) @@ -491,6 +500,19 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } } + override def checkClosed()(implicit ctx: Context): Unit = { + def isFreePolyParam(tp: Type) = tp match { + case PolyParam(binder, _) => !contains(binder) + case _ => false + } + def checkClosedType(tp: Type, where: String) = + if (tp != null) + assert(!tp.existsPart(isFreePolyParam), i"unclosed constraint: $this refers to $tp in $where") + boundsMap.foreachBinding((_, tps) => tps.foreach(checkClosedType(_, "bounds"))) + lowerMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "lower")))) + upperMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "upper")))) + } + private var myUninstVars: mutable.ArrayBuffer[TypeVar] = _ /** The uninstantiated typevars of this constraint */ diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index eaf4ce1e2..eb1a73625 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -232,7 +232,6 @@ object StdNames { val EVT2U: N = "evt2u$" val EQEQ_LOCAL_VAR: N = "eqEqTemp$" val FAKE_LOCAL_THIS: N = "this$" - val IMPLCLASS_CONSTRUCTOR: N = "$init$" val LAZY_LOCAL: N = "$lzy" val LAZY_LOCAL_INIT: N = "$lzyINIT" val LAZY_FIELD_OFFSET: N = "OFFSET$" @@ -261,6 +260,7 @@ object StdNames { val SKOLEM: N = "<skolem>" val SPECIALIZED_INSTANCE: N = "specInstance$" val THIS: N = "_$this" + val TRAIT_CONSTRUCTOR: N = "$init$" val U2EVT: N = "u2evt$" final val Nil: N = "Nil" diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d8dddb082..164b0b8f3 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -530,7 +530,7 @@ object SymDenotations { final def isClassConstructor = name == nme.CONSTRUCTOR /** Is this the constructor of a trait? */ - final def isImplClassConstructor = name == nme.IMPLCLASS_CONSTRUCTOR + final def isImplClassConstructor = name == nme.TRAIT_CONSTRUCTOR /** Is this the constructor of a trait or a class */ final def isConstructor = name.isConstructorName @@ -1630,8 +1630,11 @@ object SymDenotations { override def fullName(implicit ctx: Context): Name = super.fullName override def primaryConstructor(implicit ctx: Context): Symbol = { - val cname = if (this is ImplClass) nme.IMPLCLASS_CONSTRUCTOR else nme.CONSTRUCTOR - info.decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence + def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol + // denotsNamed returns Symbols in reverse order of occurrence + if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) // ignore normal constructor + else + constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR)) } /** The parameter accessors of this class. Term and type accessors, diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 92e32d4b1..9b41eb982 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -110,8 +110,20 @@ object TypeErasure { private def erasureCtx(implicit ctx: Context) = if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase).addMode(Mode.FutureDefsOK) else ctx - def erasure(tp: Type, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type = - erasureFn(isJava = false, semiEraseVCs, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) + /** The standard erasure of a Scala type. Value classes are erased as normal classes. + * + * @param tp The type to erase. + */ + def erasure(tp: Type)(implicit ctx: Context): Type = + erasureFn(isJava = false, semiEraseVCs = false, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) + + /** The value class erasure of a Scala type, where value classes are semi-erased to + * ErasedValueType (they will be fully erased in [[ElimErasedValueType]]). + * + * @param tp The type to erase. + */ + def valueErasure(tp: Type)(implicit ctx: Context): Type = + erasureFn(isJava = false, semiEraseVCs = true, isConstructor = false, wildcardOK = false)(tp)(erasureCtx) def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = { val seqClass = if (isJava) defn.ArrayClass else defn.SeqClass @@ -134,7 +146,7 @@ object TypeErasure { case tp: ThisType => tp case tp => - erasure(tp) + valueErasure(tp) } /** The symbol's erased info. This is the type's erasure, except for the following symbols: @@ -308,12 +320,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val parent = tp.parent if (parent isRef defn.ArrayClass) eraseArray(tp) else this(parent) - case tp: TermRef => + case _: TermRef | _: ThisType => this(tp.widen) - case tp: ThisType => - def thisTypeErasure(tpToErase: Type) = - erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) - thisTypeErasure(tp.cls.typeRef) case SuperType(thistpe, supertpe) => SuperType(this(thistpe), this(supertpe)) case ExprType(rt) => @@ -389,7 +397,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type = { val cls = tref.symbol.asClass val underlying = underlyingOfValueClass(cls) - ErasedValueType(cls, erasure(underlying)) + ErasedValueType(cls, valueErasure(underlying)) } diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 91cda1dd8..5617f568a 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -9,6 +9,7 @@ import util.{SimpleMap, DotClass} import reporting._ import printing.{Showable, Printer} import printing.Texts._ +import config.Config import collection.mutable class TyperState(r: Reporter) extends DotClass with Showable { @@ -19,7 +20,7 @@ class TyperState(r: Reporter) extends DotClass with Showable { /** The current constraint set */ def constraint: Constraint = new OrderingConstraint(SimpleMap.Empty, SimpleMap.Empty, SimpleMap.Empty) - def constraint_=(c: Constraint): Unit = {} + def constraint_=(c: Constraint)(implicit ctx: Context): Unit = {} /** The uninstantiated variables */ def uninstVars = constraint.uninstVars @@ -85,7 +86,10 @@ extends TyperState(r) { private var myConstraint: Constraint = previous.constraint override def constraint = myConstraint - override def constraint_=(c: Constraint) = myConstraint = c + override def constraint_=(c: Constraint)(implicit ctx: Context) = { + if (Config.debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed() + myConstraint = c + } private var myEphemeral: Boolean = previous.ephemeral diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 026e69539..d6bb9c3c5 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2458,6 +2458,11 @@ object Types { if (fromBelow && isOrType(inst) && isFullyDefined(inst) && !isOrType(upperBound)) inst = inst.approximateUnion + if (ctx.typerState.isGlobalCommittable) + assert(!inst.isInstanceOf[PolyParam], i"bad inst $this := $inst, constr = ${ctx.typerState.constraint}") + // If this fails, you might want to turn on Config.debugCheckConstraintsClosed + // to help find the root of the problem. + instantiateWith(inst) } diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 9498cf43c..53e8478fa 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -438,7 +438,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } val name1 = name0.adjustIfModuleClass(flags) - val name = if (name1 == nme.IMPLCLASS_CONSTRUCTOR) nme.CONSTRUCTOR else name1 + val name = if (name1 == nme.TRAIT_CONSTRUCTOR) nme.CONSTRUCTOR else name1 def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass) def isModuleClassRoot = (name == moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index b79077245..2a42a7fa9 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -192,7 +192,7 @@ object Parsers { case _ => if (mustStartStat && in.isAfterLineEnd() && - isLeqIndented(in.offset, lastStatOffset)) + isLeqIndented(in.offset, lastStatOffset max 0)) return } in.nextToken() diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index f07f43a63..26e6324eb 100644 --- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -25,7 +25,7 @@ class ConsoleReporter( printMessage(pos.lineContents.stripLineEnd) def printColumnMarker(pos: SourcePosition) = - if (pos.exists) { printMessage(" " * (pos.column - 1) + "^") } + if (pos.exists) { printMessage(" " * pos.column + "^") } /** Prints the message. */ def printMessage(msg: String): Unit = { writer.print(msg + "\n"); writer.flush() } diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 7c5bab673..7adeeac1c 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -182,7 +182,7 @@ trait Reporting { this: Context => abstract class Reporter { /** Report a diagnostic */ - protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit + def doReport(d: Diagnostic)(implicit ctx: Context): Unit /** Whether very long lines can be truncated. This exists so important * debugging information (like printing the classpath) is not rendered diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala index 2864c01f8..51d3df110 100644 --- a/src/dotty/tools/dotc/reporting/StoreReporter.scala +++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala @@ -14,7 +14,7 @@ class StoreReporter extends Reporter { private var infos: mutable.ListBuffer[Diagnostic] = null - protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit = { + def doReport(d: Diagnostic)(implicit ctx: Context): Unit = { typr.println(s">>>> StoredError: ${d.msg}") // !!! DEBUG if (infos == null) infos = new mutable.ListBuffer infos += d diff --git a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala index eb854d513..026453036 100644 --- a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala +++ b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala @@ -7,11 +7,12 @@ import collection.mutable import Reporter._ /** - * This class implements a Reporter that stores all messages + * This class implements a Reporter that throws all errors and sends warnings and other + * info to the underlying reporter. */ class ThrowingReporter(reportInfo: Reporter) extends Reporter { - protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match { + def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match { case _: Error => throw d - case _ => reportInfo.report(d) + case _ => reportInfo.doReport(d) } } diff --git a/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala index 9f9d2dd67..116fee899 100644 --- a/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala +++ b/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala @@ -60,7 +60,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform val mold = if (meth.isConstructor) meth.copySymDenotation( - name = nme.IMPLCLASS_CONSTRUCTOR, + name = nme.TRAIT_CONSTRUCTOR, info = MethodType(Nil, defn.UnitType)) else meth.ensureNotPrivate meth.copy( diff --git a/src/dotty/tools/dotc/transform/ClassOf.scala b/src/dotty/tools/dotc/transform/ClassOf.scala index 948e0117b..4d6bf2dc9 100644 --- a/src/dotty/tools/dotc/transform/ClassOf.scala +++ b/src/dotty/tools/dotc/transform/ClassOf.scala @@ -9,10 +9,12 @@ import core.Symbols.TermSymbol import core.TypeErasure import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform} -/** Performs rewritings as follows for `classOf` calls: - * classOf[CustomValueClass] ~> CustomValueClass class - * classOf[ValueClass] ~> ValueClass class, where ValueClass is Boolean, Byte, Short, etc. - * classOf[AnyOtherClass] ~> erasure(AnyOtherClass) +/** Rewrite `classOf` calls as follow: + * + * For every primitive class C whose boxed class is called B: + * classOf[C] -> B.TYPE + * For every non-primitive class D: + * classOf[D] -> Literal(Constant(erasure(D))) */ class ClassOf extends MiniPhaseTransform { import tpd._ @@ -32,22 +34,19 @@ class ClassOf extends MiniPhaseTransform { val tp = tree.args.head.tpe val defn = ctx.definitions val claz = tp.classSymbol - if (ValueClasses.isDerivedValueClass(claz)) { - Literal(Constant(ref(claz).tpe)) - } else { - def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe) - claz match { - case defn.BooleanClass => TYPE(defn.BoxedBooleanModule) - case defn.ByteClass => TYPE(defn.BoxedByteModule) - case defn.ShortClass => TYPE(defn.BoxedShortModule) - case defn.CharClass => TYPE(defn.BoxedCharModule) - case defn.IntClass => TYPE(defn.BoxedIntModule) - case defn.LongClass => TYPE(defn.BoxedLongModule) - case defn.FloatClass => TYPE(defn.BoxedFloatModule) - case defn.DoubleClass => TYPE(defn.BoxedDoubleModule) - case defn.UnitClass => TYPE(defn.BoxedVoidModule) - case _ => Literal(Constant(TypeErasure.erasure(tp))) - } + + def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe) + claz match { + case defn.BooleanClass => TYPE(defn.BoxedBooleanModule) + case defn.ByteClass => TYPE(defn.BoxedByteModule) + case defn.ShortClass => TYPE(defn.BoxedShortModule) + case defn.CharClass => TYPE(defn.BoxedCharModule) + case defn.IntClass => TYPE(defn.BoxedIntModule) + case defn.LongClass => TYPE(defn.BoxedLongModule) + case defn.FloatClass => TYPE(defn.BoxedFloatModule) + case defn.DoubleClass => TYPE(defn.BoxedDoubleModule) + case defn.UnitClass => TYPE(defn.BoxedVoidModule) + case _ => Literal(Constant(TypeErasure.erasure(tp))) } } else tree } diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 962297517..8b4c6a87d 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -268,30 +268,24 @@ object Erasure extends TypeTestsCasts{ class Typer extends typer.ReTyper with NoChecking { import Boxing._ - def erasedType(tree: untpd.Tree, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type = - tree.typeOpt match { - case tp: TermRef if tree.isTerm => erasedRef(tp) - case tp => erasure(tp, semiEraseVCs) - } + def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = { + val tp = tree.typeOpt + if (tree.isTerm) erasedRef(tp) else valueErasure(tp) + } - def promote(tree: untpd.Tree, semiEraseVCs: Boolean)(implicit ctx: Context): tree.ThisTree[Type] = { + override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { assert(tree.hasType) - val erased = erasedType(tree, semiEraseVCs) + val erased = erasedType(tree) ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}") tree.withType(erased) } - override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { - promote(tree, true) - } - /** When erasing most TypeTrees we should not semi-erase value types. * This is not the case for [[DefDef#tpt]], [[ValDef#tpt]] and [[Typed#tpt]], they * are handled separately by [[typedDefDef]], [[typedValDef]] and [[typedTyped]]. */ - override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = { - promote(tree, semiEraseVCs = false) - } + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = + tree.withType(erasure(tree.tpe)) /** This override is only needed to semi-erase type ascriptions */ override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { @@ -384,7 +378,7 @@ object Erasure extends TypeTestsCasts{ } override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context) = - untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree, semiEraseVCs = false)) + untpd.Ident(tree.name).withPos(tree.pos).withType(erasedType(tree)) override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = if (tree.symbol == ctx.owner.enclosingClass || tree.symbol.isStaticOwner) promote(tree) @@ -460,7 +454,7 @@ object Erasure extends TypeTestsCasts{ if (pt.isValueType) pt else { if (tree.typeOpt.derivesFrom(ctx.definitions.UnitClass)) tree.typeOpt - else erasure(tree.typeOpt) + else valueErasure(tree.typeOpt) } } diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 36a1b9b30..087e15c71 100644 --- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -14,7 +14,7 @@ import core._ import Phases.Phase import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ -import TypeErasure.{ erasure, ErasedValueType } +import TypeErasure.{ valueErasure, ErasedValueType } import TypeUtils._ import util.Positions._ import Decorators._ @@ -65,7 +65,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful } } - val underlying = erasure(underlyingOfValueClass(valueClass)) + val underlying = valueErasure(underlyingOfValueClass(valueClass)) val evt = ErasedValueType(valueClass, underlying) val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT, Synthetic | Method, MethodType(List(nme.x_0), List(underlying), evt)) diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index 043c92737..cefd283be 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -309,7 +309,8 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform local.copySymDenotation( owner = newOwner, name = newName(local), - initFlags = local.flags &~ InSuperCall | Private | maybeStatic, + initFlags = local.flags &~ (InSuperCall | Module) | Private | maybeStatic, + // drop Module because class is no longer a singleton in the lifted context. info = liftedInfo(local)).installAfter(thisTransform) if (local.isClass) for (member <- local.asClass.info.decls) diff --git a/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala b/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala index 8c247130a..60e8edc26 100644 --- a/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala +++ b/src/dotty/tools/dotc/transform/LinkScala2ImplClasses.scala @@ -50,7 +50,7 @@ class LinkScala2ImplClasses extends MiniPhaseTransform with IdentityDenotTransfo private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = meth.owner.implClass.info - .decl(if (meth.isConstructor) nme.IMPLCLASS_CONSTRUCTOR else meth.name) + .decl(if (meth.isConstructor) nme.TRAIT_CONSTRUCTOR else meth.name) .suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature) .symbol diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index de6cde8f2..bebaf44f4 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -100,8 +100,10 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait)) sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred).ensureNotPrivate - else if (sym.isConstructor && sym.owner.is(Trait) && sym.info.firstParamTypes.nonEmpty) - sym.copySymDenotation(info = MethodType(Nil, sym.info.resultType)) + else if (sym.isConstructor && sym.owner.is(Trait)) + sym.copySymDenotation( + name = nme.TRAIT_CONSTRUCTOR, + info = MethodType(Nil, sym.info.resultType)) else sym @@ -231,8 +233,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => cpy.Template(impl)( constr = - if (cls.is(Trait) && impl.constr.vparamss.flatten.nonEmpty) - cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) + if (cls.is(Trait)) cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) else impl.constr, parents = impl.parents.map(p => TypeTree(p.tpe).withPos(p.pos)), body = diff --git a/src/dotty/tools/dotc/transform/TraitConstructors.scala b/src/dotty/tools/dotc/transform/TraitConstructors.scala deleted file mode 100644 index 9fea468da..000000000 --- a/src/dotty/tools/dotc/transform/TraitConstructors.scala +++ /dev/null @@ -1,36 +0,0 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, DenotTransformer} -import dotty.tools.dotc.core.Denotations.SingleDenotation -import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.core.StdNames._ -import dotty.tools.dotc.core.SymDenotations.SymDenotation -import dotty.tools.dotc.core._ -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} - -/*** - * Renames constructors in traits so that backend will call them with invokeInterface - * Also makes sure that renamed constructor bodies conforms to type of method - */ -class TraitConstructors extends MiniPhaseTransform with SymTransformer { - import dotty.tools.dotc.ast.tpd._ - def phaseName: String = "traitConstructors" - - override def treeTransformPhase: Phase = this.phase - - def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = { - if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) - sym.copySymDenotation(name = nme.IMPLCLASS_CONSTRUCTOR) - else sym - } - - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { - val sym = tree.symbol - if (sym.isPrimaryConstructor && (sym.owner is Flags.Trait)) - cpy.DefDef(tree)(rhs = Block(List(tree.rhs), This(tree.symbol.enclosingClass.asClass))) - else tree - } - -} diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index 19e6aca62..347eb8c01 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -42,8 +42,8 @@ class TreeChecker extends Phase with SymTransformer { private val seenClasses = collection.mutable.HashMap[String, Symbol]() private val seenModuleVals = collection.mutable.HashMap[String, Symbol]() - def printError(str: String) = { - println(Console.RED + "[error] " + Console.WHITE + str) + def printError(str: String)(implicit ctx: Context) = { + ctx.println(Console.RED + "[error] " + Console.WHITE + str) } val NoSuperClass = Trait | Package @@ -109,7 +109,7 @@ class TreeChecker extends Phase with SymTransformer { def check(phasesToRun: Seq[Phase], ctx: Context) = { val prevPhase = ctx.phase.prev // can be a mini-phase val squahsedPhase = ctx.squashed(prevPhase) - println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}") + ctx.println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}") val checkingCtx = ctx.fresh .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.typerState.reporter))) val checker = new Checker(previousPhases(phasesToRun.toList)(ctx)) @@ -117,7 +117,7 @@ class TreeChecker extends Phase with SymTransformer { catch { case NonFatal(ex) => implicit val ctx: Context = checkingCtx - println(i"*** error while checking after phase ${checkingCtx.phase.prev} ***") + ctx.println(i"*** error while checking after phase ${checkingCtx.phase.prev} ***") throw ex } } @@ -151,10 +151,10 @@ class TreeChecker extends Phase with SymTransformer { } nowDefinedSyms += tree.symbol - //println(i"defined: ${tree.symbol}") + //ctx.println(i"defined: ${tree.symbol}") val res = op nowDefinedSyms -= tree.symbol - //println(i"undefined: ${tree.symbol}") + //ctx.println(i"undefined: ${tree.symbol}") res case _ => op } diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 1be0ef39b..4ce64da33 100644 --- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -96,7 +96,7 @@ trait TypeTestsCasts { } else derivedTree(qual, defn.Any_asInstanceOf, argType) } - def erasedArg = erasure(tree.args.head.tpe, semiEraseVCs = false) + def erasedArg = erasure(tree.args.head.tpe) if (sym eq defn.Any_isInstanceOf) transformIsInstanceOf(qual, erasedArg) else if (sym eq defn.Any_asInstanceOf) diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala index 3dda108b0..f417448bd 100644 --- a/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -19,7 +19,7 @@ class FrontEnd extends Phase { try body catch { case NonFatal(ex) => - println(s"exception occurred while $doing ${ctx.compilationUnit}") + ctx.println(s"exception occurred while $doing ${ctx.compilationUnit}") throw ex } diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index d5a6ec8f4..cdce11f22 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -16,6 +16,7 @@ import ErrorReporting._ import tpd.ListOfTreeDecorator import config.Printers._ import Annotations._ +import transform.ValueClasses._ import language.implicitConversions trait NamerContextOps { this: Context => @@ -580,6 +581,7 @@ class Namer { typer: Typer => index(rest)(inClassContext(selfInfo)) denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo) addAnnotations(denot) + if (isDerivedValueClass(cls)) cls.setFlag(Final) cls.setApplicableFlags( (NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat))) } diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index 3633a7279..bb22e2045 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -71,10 +71,17 @@ object RefChecks { } } - /** Check that self type of this class conforms to self types of parents */ - private def checkSelfType(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match { + /** Check that final and sealed restrictions on class parents + * and that self type of this class conforms to self types of parents. + */ + private def checkParents(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match { case cinfo: ClassInfo => for (parent <- cinfo.classParents) { + val pclazz = parent.classSymbol + if (pclazz.is(Final)) + ctx.error(d"cannot extend final $pclazz", clazz.pos) + if (pclazz.is(Sealed) && pclazz.associatedFile != clazz.associatedFile) + ctx.error(d"cannot extend sealed $pclazz in different compilation unit", clazz.pos) val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol) if (pself.exists && !(cinfo.selfType <:< pself)) ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos) @@ -648,13 +655,27 @@ object RefChecks { } /** Verify classes extending AnyVal meet the requirements */ - private def checkAnyValSubclass(clazz: Symbol)(implicit ctx: Context) = + private def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = { + def checkValueClassMember(stat: Tree) = stat match { + case _: ValDef if !stat.symbol.is(ParamAccessor) => + ctx.error(s"value class may not define non-parameter field", stat.pos) + case _: DefDef if stat.symbol.isConstructor => + ctx.error(s"value class may not define secondary constructor", stat.pos) + case _: MemberDef | _: Import | EmptyTree => + // ok + case _ => + ctx.error(s"value class may not contain initialization statements", stat.pos) + } if (isDerivedValueClass(clazz)) { if (clazz.is(Trait)) ctx.error("Only classes (not traits) are allowed to extend AnyVal", clazz.pos) - else if (clazz.is(Abstract)) + if (clazz.is(Abstract)) ctx.error("`abstract' modifier cannot be used with value classes", clazz.pos) + if (!clazz.isStatic) + ctx.error("value class cannot be an inner class", clazz.pos) + stats.foreach(checkValueClassMember) } + } type LevelAndIndex = immutable.Map[Symbol, (LevelInfo, Int)] @@ -701,7 +722,7 @@ import RefChecks._ * - only one overloaded alternative defines default arguments * - applyDynamic methods are not overloaded * - all overrides conform to rules laid down by `checkAllOverrides`. - * - any value classes conform to rules laid down by `checkAnyValSubClass`. + * - any value classes conform to rules laid down by `checkDerivedValueClass`. * - this(...) constructor calls do not forward reference other definitions in their block (not even lazy vals). * - no forward reference in a local block jumps over a non-lazy val definition. * - a class and its companion object do not both define a class or module with the same name. @@ -768,10 +789,10 @@ class RefChecks extends MiniPhase { thisTransformer => override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = { val cls = ctx.owner checkOverloadedRestrictions(cls) - checkSelfType(cls) + checkParents(cls) checkCompanionNameClashes(cls) checkAllOverrides(cls) - checkAnyValSubclass(cls) + checkDerivedValueClass(cls, tree.body) tree } diff --git a/src/dotty/tools/dotc/util/SimpleMap.scala b/src/dotty/tools/dotc/util/SimpleMap.scala index 7bd263f0f..b8668d7e4 100644 --- a/src/dotty/tools/dotc/util/SimpleMap.scala +++ b/src/dotty/tools/dotc/util/SimpleMap.scala @@ -8,7 +8,7 @@ abstract class SimpleMap[K <: AnyRef, +V >: Null <: AnyRef] extends (K => V) { def remove(k: K): SimpleMap[K, V] def updated[V1 >: V <: AnyRef](k: K, v: V1): SimpleMap[K, V1] def contains(k: K): Boolean = apply(k) != null - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1): SimpleMap[K, V1] + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1): SimpleMap[K, V1] def foreachBinding(f: (K, V) => Unit): Unit def map2[T](f: (K, V) => T): List[T] = { val buf = new ListBuffer[T] @@ -32,7 +32,7 @@ object SimpleMap { def apply(k: AnyRef) = null def remove(k: AnyRef) = this def updated[V1 >: Null <: AnyRef](k: AnyRef, v: V1) = new Map1(k, v) - def mapValues[V1 >: Null <: AnyRef](f: (AnyRef, V1) => V1) = this + def mapValuesNow[V1 >: Null <: AnyRef](f: (AnyRef, V1) => V1) = this def foreachBinding(f: (AnyRef, Null) => Unit) = () } @@ -49,7 +49,7 @@ object SimpleMap { def updated[V1 >: V <: AnyRef](k: K, v: V1) = if (k == k1) new Map1(k, v) else new Map2(k1, v1, k, v) - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1) = { + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1) = { val w1 = f(k1, v1) if (v1 eq w1) this else new Map1(k1, w1) } @@ -70,7 +70,7 @@ object SimpleMap { if (k == k1) new Map2(k, v, k2, v2) else if (k == k2) new Map2(k1, v1, k, v) else new Map3(k1, v1, k2, v2, k, v) - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1) = { + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1) = { val w1 = f(k1, v1); val w2 = f(k2, v2) if ((v1 eq w1) && (v2 eq w2)) this else new Map2(k1, w1, k2, w2) @@ -95,7 +95,7 @@ object SimpleMap { else if (k == k2) new Map3(k1, v1, k, v, k3, v3) else if (k == k3) new Map3(k1, v1, k2, v2, k, v) else new Map4(k1, v1, k2, v2, k3, v3, k, v) - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1) = { + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1) = { val w1 = f(k1, v1); val w2 = f(k2, v2); val w3 = f(k3, v3) if ((v1 eq w1) && (v2 eq w2) && (v3 eq w3)) this else new Map3(k1, w1, k2, w2, k3, w3) @@ -123,7 +123,7 @@ object SimpleMap { else if (k == k3) new Map4(k1, v1, k2, v2, k, v, k4, v4) else if (k == k4) new Map4(k1, v1, k2, v2, k3, v3, k, v) else new MapMore(Array[AnyRef](k1, v1, k2, v2, k3, v3, k4, v4, k, v)) - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1) = { + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1) = { val w1 = f(k1, v1); val w2 = f(k2, v2); val w3 = f(k3, v3); val w4 = f(k4, v4) if ((v1 eq w1) && (v2 eq w2) && (v3 eq w3) && (v4 eq w4)) this else new Map4(k1, w1, k2, w2, k3, w3, k4, w4) @@ -197,7 +197,7 @@ object SimpleMap { false } - def mapValues[V1 >: V <: AnyRef](f: (K, V1) => V1) = { + def mapValuesNow[V1 >: V <: AnyRef](f: (K, V1) => V1) = { var bindings1: Array[AnyRef] = bindings var i = 0 while (i < bindings.length) { diff --git a/src/dotty/tools/dotc/util/SourceFile.scala b/src/dotty/tools/dotc/util/SourceFile.scala index 45119a881..5e8f85e28 100644 --- a/src/dotty/tools/dotc/util/SourceFile.scala +++ b/src/dotty/tools/dotc/util/SourceFile.scala @@ -72,7 +72,7 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) { def positionInUltimateSource(position: SourcePosition): SourcePosition = SourcePosition(underlying, position.pos shift start) - def isLineBreak(idx: Int) = + private def isLineBreak(idx: Int) = if (idx >= length) false else { val ch = content(idx) // don't identify the CR in CR LF as a line break, since LF will do. @@ -80,7 +80,7 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) { else isLineBreakChar(ch) } - def calculateLineIndices(cs: Array[Char]) = { + private def calculateLineIndices(cs: Array[Char]) = { val buf = new ArrayBuffer[Int] buf += 0 for (i <- 0 until cs.length) if (isLineBreak(i)) buf += i + 1 @@ -103,22 +103,29 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) { lastLine } - def startOfLine(offset: Int): Int = lineToOffset(offsetToLine(offset)) + /** The index of the first character of the line containing position `offset` */ + def startOfLine(offset: Int): Int = { + require(offset >= 0) + lineToOffset(offsetToLine(offset)) + } + /** The start index of the line following the one containing position `offset` */ def nextLine(offset: Int): Int = lineToOffset(offsetToLine(offset) + 1 min lineIndices.length - 1) + /** The contents of the line containing position `offset` */ def lineContents(offset: Int): String = content.slice(startOfLine(offset), nextLine(offset)).mkString + /** The column corresponding to `offset`, starting at 0 */ def column(offset: Int): Int = { var idx = startOfLine(offset) var col = 0 while (idx != offset) { - col += (if (content(idx) == '\t') tabInc - col % tabInc else 1) + col += (if (content(idx) == '\t') (tabInc - col) % tabInc else 1) idx += 1 } - col + 1 + col } override def toString = file.toString diff --git a/src/dotty/tools/dotc/util/SourcePosition.scala b/src/dotty/tools/dotc/util/SourcePosition.scala index 3d6352a1a..c88cbc78b 100644 --- a/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/src/dotty/tools/dotc/util/SourcePosition.scala @@ -10,7 +10,11 @@ case class SourcePosition(source: SourceFile, pos: Position) { def exists = pos.exists def lineContents: String = source.lineContents(point) + + /** The line of the position, starting at 0 */ def line: Int = source.offsetToLine(point) + + /** The column of the position, starting at 0 */ def column: Int = source.column(point) override def toString = diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index f96e77f00..f222daca4 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -133,6 +133,8 @@ class tests extends CompilerTest { @Test def neg_i0248_inherit_refined = compileFile(negDir, "i0248-inherit-refined", xerrors = 4) @Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3) @Test def neg_i583 = compileFile(negDir, "i0583-skolemize", xerrors = 2) + @Test def neg_finalSealed = compileFile(negDir, "final-sealed", xerrors = 2) + @Test def neg_i705 = compileFile(negDir, "i705-inner-value-class", xerrors = 7) @Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4) @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @@ -140,6 +142,7 @@ class tests extends CompilerTest { @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5) @Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2) + @Test def neg_firstError = compileFile(negDir, "firstError", xerrors = 3) @Test def run_all = runFiles(runDir) diff --git a/test/dotty/partest/DPConfig.scala b/test/dotty/partest/DPConfig.scala index ad9c271ef..640dfd021 100644 --- a/test/dotty/partest/DPConfig.scala +++ b/test/dotty/partest/DPConfig.scala @@ -1,7 +1,8 @@ package dotty.partest -import java.io.File import scala.collection.JavaConversions._ +import scala.reflect.io.Path +import java.io.File /** Dotty Partest runs all tests in the provided testDirs located under @@ -14,7 +15,9 @@ import scala.collection.JavaConversions._ * otherwise pos/__defaultFlags.flags are used if the file exists). */ object DPConfig { - val testRoot = "./tests/partest-generated" + val testRoot = (Path(".") / Path("tests") / Path("partest-generated")).toString + val genLog = Path(testRoot) / Path("gen.log") + lazy val testDirs = { val root = new File(testRoot) val dirs = if (!root.exists) Array.empty[String] else root.listFiles.filter(_.isDirectory).map(_.getName) diff --git a/test/dotty/partest/DPConsoleRunner.scala b/test/dotty/partest/DPConsoleRunner.scala index 13ffed050..fa6256398 100644 --- a/test/dotty/partest/DPConsoleRunner.scala +++ b/test/dotty/partest/DPConsoleRunner.scala @@ -9,7 +9,7 @@ import scala.tools.partest._ import scala.tools.partest.nest._ import scala.util.matching.Regex import tools.nsc.io.{ File => NSCFile } -import java.io.{ File, PrintStream, FileOutputStream } +import java.io.{ File, PrintStream, FileOutputStream, PrintWriter, FileWriter } import java.net.URLClassLoader /** Runs dotty partest from the Console, discovering test sources in @@ -91,23 +91,11 @@ extends SuiteRunner(testSourcePath, fileManager, updateCheck, failed, javaCmdPat val state = try { - // IO redirection is messy, there are no concurrency guarantees. - // Parts of test output might end up in the wrong file or get lost. - Console.out.flush - Console.err.flush - val clog = runner.cLogFile - val stream = new PrintStream(new FileOutputStream(clog.jfile), true) - val result = Console.withOut(stream)({ Console.withErr(stream)({ - val res = runner.run() - Console.err.flush - Console.out.flush - res - })}) - result match { + runner.run match { // Append compiler output to transcript if compilation failed, // printed with --verbose option case TestState.Fail(f, r@"compilation failed", transcript) => - TestState.Fail(f, r, transcript ++ clog.fileLines.dropWhile(_ == "")) + TestState.Fail(f, r, transcript ++ runner.cLogFile.fileLines.dropWhile(_ == "")) case res => res } } catch { @@ -261,11 +249,16 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn override def groupedFiles(sources: List[File]): List[List[File]] = { val grouped = sources groupBy (_.group) val flatGroup = List(grouped.keys.toList.sorted.map({ k => grouped(k) sortBy (_.getName) }).flatten) - try { // try/catch because of bug in partest + try { // try/catch because of bug in partest that throws exception if (flatGroup != super.groupedFiles(sources)) - NestUI.echoWarning("Warning: Overriding compilation groups for tests: " + sources) + throw new java.lang.UnsupportedOperationException() } catch { - case e: java.lang.UnsupportedOperationException => NestUI.echoWarning("Warning: Overriding compilation groups for tests: " + sources) + case e: java.lang.UnsupportedOperationException => + val genlogFWriter = new FileWriter(DPConfig.genLog.jfile, true) + val genlogWriter = new PrintWriter(genlogFWriter, true) + genlogWriter.println("Warning: Overriding compilation groups for tests: " + sources) + genlogWriter.close + genlogFWriter.close } flatGroup } diff --git a/test/dotty/partest/DPDirectCompiler.scala b/test/dotty/partest/DPDirectCompiler.scala index 86e766505..885de8c62 100644 --- a/test/dotty/partest/DPDirectCompiler.scala +++ b/test/dotty/partest/DPDirectCompiler.scala @@ -1,14 +1,17 @@ package dotty.partest +import dotty.tools.dotc.reporting.ConsoleReporter import scala.tools.partest.{ TestState, nest } -import java.io.File +import java.io.{ File, PrintWriter, FileWriter } /* NOTE: Adapted from partest.DirectCompiler and DottyTest */ -class DPDirectCompiler(runner: nest.Runner) extends nest.DirectCompiler(runner) { +class DPDirectCompiler(runner: DPTestRunner) extends nest.DirectCompiler(runner) { override def compile(opts0: List[String], sources: List[File]): TestState = { - println("\ncompiling " + sources.mkString(" ") + "\noptions: " + opts0.mkString(" ")) + val clogFWriter = new FileWriter(runner.cLogFile.jfile, true) + val clogWriter = new PrintWriter(clogFWriter, true) + clogWriter.println("\ncompiling " + sources.mkString(" ") + "\noptions: " + opts0.mkString(" ")) implicit var ctx: dotty.tools.dotc.core.Contexts.Context = { val base = new dotty.tools.dotc.core.Contexts.ContextBase @@ -18,17 +21,23 @@ class DPDirectCompiler(runner: nest.Runner) extends nest.DirectCompiler(runner) base.definitions.init(ctx) ctx } - + try { - val processor = if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main - val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, ctx) + val processor = + if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main + val clogger = new ConsoleReporter(writer = clogWriter)(ctx) + val logCtx = ctx.fresh.setTyperState(ctx.typerState.withReporter(clogger)) + val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, logCtx) if (!reporter.hasErrors) runner.genPass() else { reporter.printSummary(ctx) runner.genFail(s"compilation failed with ${reporter.errorCount} errors") } - } catch { + } catch { case t: Throwable => runner.genCrash(t) + } finally { + clogFWriter.close + clogWriter.close } } } diff --git a/test/test/CompilerTest.scala b/test/test/CompilerTest.scala index 4a8ec6da0..09b608f22 100644 --- a/test/test/CompilerTest.scala +++ b/test/test/CompilerTest.scala @@ -344,7 +344,7 @@ object CompilerTest extends App { lazy val init: SFile = { scala.reflect.io.Directory(DPConfig.testRoot).deleteRecursively new JFile(DPConfig.testRoot).mkdirs - val log = (Path(DPConfig.testRoot) / Path("gen.log")).createFile(true) + val log = DPConfig.genLog.createFile(true) println(s"CompilerTest is generating tests for partest, log: $log") log } diff --git a/tests/neg/final-sealed.scala b/tests/neg/final-sealed.scala new file mode 100644 index 000000000..017afd63b --- /dev/null +++ b/tests/neg/final-sealed.scala @@ -0,0 +1,4 @@ +final class A +class B extends A +class C extends Option[Int] + diff --git a/tests/neg/firstError.scala b/tests/neg/firstError.scala new file mode 100644 index 000000000..317adcced --- /dev/null +++ b/tests/neg/firstError.scala @@ -0,0 +1,4 @@ +. + +\u890u3084eu + diff --git a/tests/neg/i705-inner-value-class.scala b/tests/neg/i705-inner-value-class.scala new file mode 100644 index 000000000..f638b0670 --- /dev/null +++ b/tests/neg/i705-inner-value-class.scala @@ -0,0 +1,22 @@ +class Foo { + class B(val a: Int) extends AnyVal // error +} + +class VCwithBadMembers(val a: Int) extends AnyVal { + def this() = this(1) // error + var x = 0 // error + val y = 2 // error + println("hi") // error +} + +object Test { + class B(val a: Int) extends AnyVal // ok + def f = { + class C(val a: Int) extends AnyVal // error + new C(1) + } + class B1(val b: Int) extends B(b) +// class D extends B( { class E(val a: Int) extends AnyVal; new E(1) } ) // error +} + + diff --git a/tests/pending/run/unittest_collection.check b/tests/pending/run/unittest_collection.check deleted file mode 100644 index df1629dd7..000000000 --- a/tests/pending/run/unittest_collection.check +++ /dev/null @@ -1 +0,0 @@ -warning: there was one deprecation warning; re-run with -deprecation for details diff --git a/tests/pos/extmethods.scala b/tests/pos/extmethods.scala index 3edfa2d75..cac1c4ec1 100644 --- a/tests/pos/extmethods.scala +++ b/tests/pos/extmethods.scala @@ -1,7 +1,6 @@ trait That1[A] class T[A, This <: That1[A]](val x: Int) extends AnyVal { self: This => - var next: This = _ final def loop(x: This, cnt: Int): Int = loop(x, cnt + 1) def const[B](): Boolean = return true } diff --git a/tests/pending/pos/t8230a.scala b/tests/pos/t8230a.scala index 405aa86f5..dfbae51ee 100644 --- a/tests/pending/pos/t8230a.scala +++ b/tests/pos/t8230a.scala @@ -15,9 +15,9 @@ object Test { object Okay { Arr("1") - import I.{ arrToTrav, longArrToTrav } - foo(Arr("2")) - } + import I.{ arrToTrav, longArrToTrav } + val x = foo(Arr("2")) + } object Fail { import I.arrToTrav diff --git a/tests/run/i689.scala b/tests/run/i689.scala new file mode 100644 index 000000000..262d13852 --- /dev/null +++ b/tests/run/i689.scala @@ -0,0 +1,10 @@ +object Test { + def main(args: Array[String]): Unit = { + object A { + def a = new A + def y = 0 + } + class A { A.y } + A.a + } +} diff --git a/tests/run/origins.check b/tests/run/origins.check index 771baf9fd..db9bf29a4 100644 --- a/tests/run/origins.check +++ b/tests/run/origins.check @@ -1,6 +1,6 @@ >> Origins tag 'boop' logged 65 calls from 3 distinguished sources. - 50 Test$.$anonfun$f3$1(origins.scala:21) - 10 Test$.$anonfun$f2$1(origins.scala:20) - 5 Test$.$anonfun$f1$1(origins.scala:19) + 50 Test$.$anonfun$f3$1(origins.scala:22) + 10 Test$.$anonfun$f2$1(origins.scala:21) + 5 Test$.$anonfun$f1$1(origins.scala:20) diff --git a/tests/pending/run/t8002.scala b/tests/run/t8002.scala index c27e83a46..c27e83a46 100644 --- a/tests/pending/run/t8002.scala +++ b/tests/run/t8002.scala diff --git a/tests/pending/run/unittest_collection.scala b/tests/run/unittest_collection.scala index d10845475..d10845475 100644 --- a/tests/pending/run/unittest_collection.scala +++ b/tests/run/unittest_collection.scala diff --git a/tests/run/valueclasses-nested-object.check b/tests/run/valueclasses-nested-object.check new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/run/valueclasses-nested-object.check @@ -0,0 +1 @@ +3 diff --git a/tests/run/valueclasses-nested-object.scala b/tests/run/valueclasses-nested-object.scala new file mode 100644 index 000000000..3042592e4 --- /dev/null +++ b/tests/run/valueclasses-nested-object.scala @@ -0,0 +1,16 @@ +class M(val t: Int) extends AnyVal { + // Disallowed in Scala 2.11 (see SI-6359) + def o = { + object X { + override def toString = t.toString + } + () => X + } +} + +object Test { + def main(args: Array[String]): Unit = { + val x = new M(3) + println(x.o()) + } +} |