aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--README.md34
-rw-r--r--project/Build.scala6
-rwxr-xr-xscripts/jobs/validate/partest2
-rw-r--r--src/dotty/tools/dotc/Driver.scala12
-rw-r--r--src/dotty/tools/dotc/Resident.scala2
-rw-r--r--src/dotty/tools/dotc/Run.scala3
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala16
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala2
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala10
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala10
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala35
-rw-r--r--src/dotty/tools/dotc/core/TyperState.scala4
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala1
-rw-r--r--src/dotty/tools/dotc/parsing/JavaParsers.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala1
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala11
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala7
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala32
-rw-r--r--src/dotty/tools/dotc/reporting/StoreReporter.scala7
-rw-r--r--src/dotty/tools/dotc/reporting/ThrowingReporter.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala32
-rw-r--r--test/dotc/build.scala2
-rw-r--r--test/dotc/tests.scala9
-rw-r--r--tests/neg/i866.scala9
-rw-r--r--tests/neg/typedIdents/PQ.scala6
-rw-r--r--tests/neg/typedIdents/typedIdents.scala (renamed from tests/neg/typedIdents.scala)6
-rw-r--r--tests/pos/i830.scala6
-rw-r--r--tests/pos/i873.scala10
-rw-r--r--tests/pos/i884.scala4
-rw-r--r--tests/pos/i903.scala26
-rw-r--r--tests/pos/java-interop/i879.java11
-rw-r--r--tests/pos/java-interop/volatile/volatile.java3
-rw-r--r--tests/pos/overloadedAccess.scala1
-rw-r--r--tests/pos/range.scala9
-rw-r--r--tests/pos/tparam_inf.scala38
-rw-r--r--tests/pos/typedIdents/PQ.scala6
-rw-r--r--tests/pos/typedIdents/typedIdents.scala (renamed from tests/pos/typedIdents.scala)6
42 files changed, 299 insertions, 97 deletions
diff --git a/.gitignore b/.gitignore
index 95d95ca11..aa7fd2164 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,8 @@ classes/
tests/partest-generated/
tests/locks/
/test-classes/
+
+
+# Ignore output files but keep the directory
+out/
+!out/.keep
diff --git a/README.md b/README.md
index d7d23a625..cfa946253 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,31 @@
dotty
=====
-[![Build Status](https://travis-ci.org/lampepfl/dotty.png?branch=master)](https://travis-ci.org/lampepfl/dotty)
-
-Dotty is a platform to try out new language concepts and compiler technologies for Scala. The focus is mainly on simplification. We remove extraneous syntax (e.g. no XML literals), and try to boil down Scala's types into a smaller set of more fundamental constructors. The theory behind these constructors is researched in [DOT](http://www.cs.uwm.edu/~boyland/fool2012/papers/fool2012_submission_3.pdf), a calculus for dependent object types.
-
-The dotty compiler is largely a new design. It takes a more functional approach than current scalac, paired with aggressive caching to achieve good performance. At present, only the frontend (parser and type-checker) exists; the transformation and code generation phases remain to be written. Some parts, in particular those that have to do with configuration and input/output are derived from the Scala compiler.
-
-We expect that, over time, some of the new technologies explored in this project will find their way into future versions of Scala. At present it is too early to say which ones and when.
-
-If you want to try it out, to get started have a look at https://github.com/lampepfl/dotty/wiki/Getting-Started.
+[![Join the chat at https://gitter.im/lampepfl/dotty](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lampepfl/dotty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+Dotty is a platform to try out new language concepts and compiler
+technologies for Scala. The focus is mainly on simplification. We
+remove extraneous syntax (e.g. no XML literals), and try to boil down
+Scala's types into a smaller set of more fundamental constructors. The
+theory behind these constructors is researched in
+[DOT](http://www.cs.uwm.edu/~boyland/fool2012/papers/fool2012_submission_3.pdf),
+a calculus for dependent object types.
+
+The dotty compiler is largely a new design. It takes a more functional
+approach than current scalac, paired with aggressive caching to
+achieve good performance. Some parts, in particular those that have to
+do with configuration and input/output are ported from the Scala
+compiler. The compiler is fully functional, in particular it can
+compile itself. But there's more work needed (and planned) on
+polishing rough edges, improving diagnostics, improving compilation
+speed, and embedding in other tools.
+
+We expect that, over time, some of the new technologies explored in
+this project will find their way into future versions of Scala. At
+present it is too early to say which ones and when.
+
+If you want to try it out, to get started have a look at
+https://github.com/lampepfl/dotty/wiki/Getting-Started.
Developers mailing list is https://groups.google.com/forum/#!forum/dotty-internals.
diff --git a/project/Build.scala b/project/Build.scala
index be39358ff..442ac3c2f 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -81,7 +81,7 @@ object DottyBuild extends Build {
val args = Def.spaceDelimited("<arg>").parsed
val jars = Seq((packageBin in Compile).value.getAbsolutePath) ++
getJarPaths(partestDeps.value, ivyPaths.value.ivyHome)
- val dottyJars = "-dottyJars " + jars.length + " " + jars.mkString(" ")
+ val dottyJars = "-dottyJars " + (jars.length + 1) + " dotty.jar" + " " + jars.mkString(" ")
// Provide the jars required on the classpath of run tests
runTask(Test, "dotty.partest.DPConsoleRunner", dottyJars + " " + args.mkString(" "))
},
@@ -118,8 +118,8 @@ object DottyBuild extends Build {
("-DpartestParentID=" + pid) :: tuning ::: agentOptions ::: travis_build ::: fullpath
}
- ) ++ addCommandAlias("partest", ";test:package;package;lockPartestFile;test:test;runPartestRunner") ++
- addCommandAlias("partest-only", ";test:package;package;lockPartestFile;test:test-only dotc.tests;runPartestRunner")
+ ) ++ addCommandAlias("partest", ";test:package;package;test:runMain dotc.build;lockPartestFile;test:test;runPartestRunner") ++
+ addCommandAlias("partest-only", ";test:package;package;test:runMain dotc.build;lockPartestFile;test:test-only dotc.tests;runPartestRunner")
lazy val dotty = Project(id = "dotty", base = file("."), settings = defaults)
diff --git a/scripts/jobs/validate/partest b/scripts/jobs/validate/partest
index ee45a3919..55ec9f4c1 100755
--- a/scripts/jobs/validate/partest
+++ b/scripts/jobs/validate/partest
@@ -4,5 +4,5 @@ baseDir=${WORKSPACE-`pwd`}
scriptsDir="$baseDir/scripts"
. $scriptsDir/common
-sbt $sbtArgs update compile "partest-only run --show-diff --verbose"
+sbt $sbtArgs update compile "partest-only --show-diff --verbose"
diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala
index 7e9d4a5e4..3b382da58 100644
--- a/src/dotty/tools/dotc/Driver.scala
+++ b/src/dotty/tools/dotc/Driver.scala
@@ -12,7 +12,7 @@ abstract class Driver extends DotClass {
protected def newCompiler(): Compiler
- protected def emptyReporter: Reporter = new StoreReporter
+ protected def emptyReporter: Reporter = new StoreReporter(null)
protected def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter =
if (fileNames.nonEmpty)
@@ -24,7 +24,7 @@ abstract class Driver extends DotClass {
catch {
case ex: FatalError =>
ctx.error(ex.getMessage) // signals that we should fail compilation.
- ctx.typerState.reporter
+ ctx.reporter
}
else emptyReporter
@@ -44,8 +44,14 @@ abstract class Driver extends DotClass {
doCompile(newCompiler(), fileNames)(ctx)
}
+ // We overload `process` instead of using a default argument so that we
+ // can easily call this method using reflection from `RawCompiler` in sbt.
+ def process(args: Array[String]): Reporter = {
+ process(args, initCtx)
+ }
+
def main(args: Array[String]): Unit =
- sys.exit(if (process(args, initCtx).hasErrors) 1 else 0)
+ sys.exit(if (process(args).hasErrors) 1 else 0)
}
class FatalError(msg: String) extends Exception
diff --git a/src/dotty/tools/dotc/Resident.scala b/src/dotty/tools/dotc/Resident.scala
index 9578e7d2c..3ae369f27 100644
--- a/src/dotty/tools/dotc/Resident.scala
+++ b/src/dotty/tools/dotc/Resident.scala
@@ -47,7 +47,7 @@ class Resident extends Driver {
nextCtx = rootCtx
line = getLine()
}
- if (line.startsWith(quit)) ctx.typerState.reporter
+ if (line.startsWith(quit)) ctx.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 553805d95..ba86e3e70 100644
--- a/src/dotty/tools/dotc/Run.scala
+++ b/src/dotty/tools/dotc/Run.scala
@@ -50,6 +50,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
}
protected def compileUnits() = Stats.monitorHeartBeat {
+ ctx.checkSingleThreaded()
val phases = ctx.squashPhases(ctx.phasePlan,
ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, ctx.settings.YstopAfter.value, ctx.settings.Ycheck.value)
ctx.usePhases(phases)
@@ -84,7 +85,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
/** Print summary; return # of errors encountered */
def printSummary(): Reporter = {
ctx.runInfo.printMaxConstraint()
- val r = ctx.typerState.reporter
+ val r = ctx.reporter
r.printSummary
r
}
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index d1f101283..1ef883bf2 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -556,14 +556,20 @@ object desugar {
DefDef(nme.ANON_FUN, Nil, params :: Nil, tpt, body).withMods(synthetic),
Closure(Nil, Ident(nme.ANON_FUN), EmptyTree))
- /** Expand partial function
+ /** If `nparams` == 1, expand partial function
+ *
* { cases }
* ==>
- * x$0 => x$0 match { cases }
+ * x$1 => x$1 match { cases }
+ *
+ * If `nparams` != 1, expand instead to
+ *
+ * (x$1, ..., x$n) => (x$0, ..., x${n-1}) match { cases }
*/
- def makeCaseLambda(cases: List[CaseDef])(implicit ctx: Context) = {
- val param = makeSyntheticParameter()
- Function(param :: Nil, Match(Ident(param.name), cases))
+ def makeCaseLambda(cases: List[CaseDef], nparams: Int = 1)(implicit ctx: Context) = {
+ val params = (1 to nparams).toList.map(makeSyntheticParameter(_))
+ val selector = makeTuple(params.map(p => Ident(p.name)))
+ Function(params, Match(selector, cases))
}
/** Add annotation with class `cls` to tree:
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index a10dfaa16..54ace3be4 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -146,7 +146,7 @@ object Trees {
* type. (Overridden by empty trees)
*/
def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = {
- if (tpe == ErrorType) assert(ctx.errorsReported)
+ if (tpe == ErrorType) assert(ctx.reporter.errorsReported)
withTypeUnchecked(tpe)
}
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index f9d64b2cc..d5fdba1af 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -611,6 +611,16 @@ object Contexts {
superIdOfClass.clear()
lastSuperId = -1
}
+
+ // Test that access is single threaded
+
+ /** The thread on which `checkSingleThreaded was invoked last */
+ @sharable private var thread: Thread = null
+
+ /** Check that we are on the same thread as before */
+ def checkSingleThreaded() =
+ if (thread == null) thread = Thread.currentThread()
+ else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase")
}
object Context {
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index bd03cc056..65df55a9d 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -193,9 +193,11 @@ object Denotations {
*/
def requiredSymbol(p: Symbol => Boolean, source: AbstractFile = null, generateStubs: Boolean = true)(implicit ctx: Context): Symbol =
disambiguate(p) match {
- case MissingRef(ownerd, name) =>
- if (generateStubs)
+ case m @ MissingRef(ownerd, name) =>
+ if (generateStubs) {
+ m.ex.printStackTrace()
ctx.newStubSymbol(ownerd.symbol, name, source)
+ }
else NoSymbol
case NoDenotation | _: NoQualifyingRef =>
throw new TypeError(s"None of the alternatives of $this satisfies required predicate")
@@ -858,7 +860,9 @@ object Denotations {
/** An error denotation that provides more info about the missing reference.
* Produced by staticRef, consumed by requiredSymbol.
*/
- case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation
+ case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation {
+ val ex: Exception = new Exception
+ }
/** An error denotation that provides more info about alternatives
* that were found but that do not qualify.
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index f2a4c9e1e..684e9cbfd 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -123,7 +123,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
pendingSubTypes = new mutable.HashSet[(Type, Type)]
ctx.log(s"!!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${state.constraint.show}")
ctx.log(s"!!! constraint = ${constraint.show}")
- assert(!ctx.settings.YnoDeepSubtypes.value)
+ if (ctx.settings.YnoDeepSubtypes.value) throw new Error("deep subtype")
if (Config.traceDeepSubTypeRecursions && !this.isInstanceOf[ExplainingTypeComparer])
ctx.log(TypeComparer.explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2)))
}
@@ -197,8 +197,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
val cls1 = tp1.cls
cls1.classInfo.selfType.derivesFrom(cls2) &&
cls2.classInfo.selfType.derivesFrom(cls1)
- case tp1: TermRef if tp2.cls eq tp1.symbol.moduleClass =>
- isSubType(tp1.prefix, cls2.owner.thisType)
+ case tp1: TermRef if cls2.is(Module) && cls2.eq(tp1.widen.typeSymbol) =>
+ cls2.isStaticOwner ||
+ isSubType(tp1.prefix, cls2.owner.thisType) ||
+ secondTry(tp1, tp2)
case _ =>
secondTry(tp1, tp2)
}
@@ -257,9 +259,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
comparePolyParam
case tp1: ThisType =>
+ val cls1 = tp1.cls
tp2 match {
- case tp2: TermRef if tp1.cls eq tp2.symbol.moduleClass =>
- isSubType(tp1.cls.owner.thisType, tp2.prefix)
+ case tp2: TermRef if cls1.is(Module) && cls1.eq(tp2.widen.typeSymbol) =>
+ cls1.isStaticOwner ||
+ isSubType(cls1.owner.thisType, tp2.prefix) ||
+ thirdTry(tp1, tp2)
case _ =>
thirdTry(tp1, tp2)
}
@@ -779,8 +784,24 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
else {
val t2 = mergeIfSub(tp2, tp1)
if (t2.exists) t2
- else andType(tp1, tp2)
- }
+ else tp1 match {
+ case tp1: ConstantType =>
+ tp2 match {
+ case tp2: ConstantType =>
+ // Make use of the fact that the intersection of two constant types
+ // types which are not subtypes of each other is known to be empty.
+ // Note: The same does not apply to singleton types in general.
+ // E.g. we could have a pattern match against `x.type & y.type`
+ // which might succeed if `x` and `y` happen to be the same ref
+ // at run time. It would not work to replace that with `Nothing`.
+ // However, maybe we can still apply the replacement to
+ // types which are not explicitly written.
+ defn.NothingType
+ case _ => andType(tp1, tp2)
+ }
+ case _ => andType(tp1, tp2)
+ }
+ }
}
}
}
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala
index 5617f568a..36f026107 100644
--- a/src/dotty/tools/dotc/core/TyperState.scala
+++ b/src/dotty/tools/dotc/core/TyperState.scala
@@ -98,7 +98,7 @@ extends TyperState(r) {
override def fresh(isCommittable: Boolean): TyperState =
- new MutableTyperState(this, new StoreReporter, isCommittable)
+ new MutableTyperState(this, new StoreReporter(reporter), isCommittable)
override def withReporter(reporter: Reporter) =
new MutableTyperState(this, reporter, isCommittable)
@@ -169,7 +169,7 @@ extends TyperState(r) {
* found a better solution.
*/
override def tryWithFallback[T](op: => T)(fallback: => T)(implicit ctx: Context): T = {
- val storeReporter = new StoreReporter
+ val storeReporter = new StoreReporter(myReporter)
val savedReporter = myReporter
myReporter = storeReporter
val savedConstraint = myConstraint
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index c7df3c400..cdb733efa 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -405,6 +405,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
// println(owner.info.decls.toList.map(_.debugString).mkString("\n ")) // !!! DEBUG
// }
// (5) Create a stub symbol to defer hard failure a little longer.
+ new Exception().printStackTrace()
ctx.newStubSymbol(owner, name, source)
}
}
diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala
index 297f3c0f9..7b9d29ce3 100644
--- a/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -356,7 +356,7 @@ object JavaParsers {
// assumed true unless we see public/private/protected
var isPackageAccess = true
var annots: List[Tree] = Nil
- def addAnnot(sym: ClassSymbol) = annots :+= New(TypeTree(sym.typeRef))
+ def addAnnot(sym: ClassSymbol) = annots :+= New(TypeTree(sym.typeRef)).withPos(Position(in.offset))
while (true) {
in.token match {
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 4b22eac95..caa15c7ff 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -322,6 +322,7 @@ object Parsers {
case Ident(name1) => placeholderParams.nonEmpty && name1 == placeholderParams.head.name
case Typed(t1, _) => isWildcard(t1)
case Annotated(t1, _) => isWildcard(t1)
+ case Parens(t1) => isWildcard(t1)
case _ => false
}
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index a46665ec0..d50b551fa 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -45,8 +45,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
override def nameString(name: Name): String = name.decode.toString
- override protected def simpleNameString(sym: Symbol): String =
- sym.name.decode.toString
+ override protected def simpleNameString(sym: Symbol): String = {
+ val name = sym.originalName
+ nameString(if (sym is ExpandedTypeParam) name.asTypeName.unexpandedName else name)
+ }
override protected def fullNameOwner(sym: Symbol) = {
val owner = super.fullNameOwner(sym)
@@ -86,10 +88,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
else {
val tsym = tp.parent.member(tp.refinedName).symbol
if (!tsym.exists) super.refinementNameString(tp)
- else {
- val name = tsym.originalName
- nameString(if (tsym is ExpandedTypeParam) name.asTypeName.unexpandedName else name)
- }
+ else simpleNameString(tsym)
}
override def toText(tp: Type): Text = controlled {
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
index 26e6324eb..3e2aaa880 100644
--- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -40,8 +40,9 @@ class ConsoleReporter(
}
}
- override def doReport(d: Diagnostic)(implicit ctx: Context): Unit =
- if (!d.isSuppressed || !hasErrors) d match {
+ override def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = {
+ val issue = !(d.isSuppressed && hasErrors)
+ if (issue) d match {
case d: Error =>
printMessageAndPos(s"error: ${d.msg}", d.pos)
if (ctx.settings.prompt.value) displayPrompt()
@@ -51,6 +52,8 @@ class ConsoleReporter(
case _ =>
printMessageAndPos(d.msg, d.pos)
}
+ issue
+ }
def displayPrompt(): Unit = {
writer.print("\na)bort, s)tack, r)esume: ")
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index 086575fb4..0358f71f6 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -173,8 +173,6 @@ trait Reporting { this: Context =>
throw ex
}
}
-
- def errorsReported: Boolean = outersIterator exists (_.reporter.hasErrors)
}
/**
@@ -183,8 +181,10 @@ trait Reporting { this: Context =>
*/
abstract class Reporter {
- /** Report a diagnostic */
- def doReport(d: Diagnostic)(implicit ctx: Context): Unit
+ /** Report a diagnostic, unless it is suppressed because it is nonsensical
+ * @return a diagnostic was reported.
+ */
+ def doReport(d: Diagnostic)(implicit ctx: Context): Boolean
/** Whether very long lines can be truncated. This exists so important
* debugging information (like printing the classpath) is not rendered
@@ -213,20 +213,24 @@ abstract class Reporter {
def hasErrors = errorCount > 0
def hasWarnings = warningCount > 0
+ /** Have errors been reported by this reporter, or in the
+ * case where this is a StoreReporter, by an outer reporter?
+ */
+ def errorsReported = hasErrors
+
val unreportedWarnings = new mutable.HashMap[String, Int] {
override def default(key: String) = 0
}
- def report(d: Diagnostic)(implicit ctx: Context): Unit = if (!isHidden(d)) {
- doReport(d)(ctx.addMode(Mode.Printing))
- d match {
- case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1
- case d: Warning => warningCount += 1
- case d: Error => errorCount += 1
- case d: Info => // nothing to do here
- // match error if d is something else
- }
- }
+ def report(d: Diagnostic)(implicit ctx: Context): Unit =
+ if (!isHidden(d) && doReport(d)(ctx.addMode(Mode.Printing)))
+ d match {
+ case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1
+ case d: Warning => warningCount += 1
+ case d: Error => errorCount += 1
+ case d: Info => // nothing to do here
+ // match error if d is something else
+ }
def incomplete(d: Diagnostic)(implicit ctx: Context): Unit =
incompleteHandler(d)(ctx)
diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala
index 51d3df110..8209839eb 100644
--- a/src/dotty/tools/dotc/reporting/StoreReporter.scala
+++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala
@@ -10,14 +10,15 @@ import config.Printers._
/**
* This class implements a Reporter that stores all messages
*/
-class StoreReporter extends Reporter {
+class StoreReporter(outer: Reporter) extends Reporter {
private var infos: mutable.ListBuffer[Diagnostic] = null
- def doReport(d: Diagnostic)(implicit ctx: Context): Unit = {
+ def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = {
typr.println(s">>>> StoredError: ${d.msg}") // !!! DEBUG
if (infos == null) infos = new mutable.ListBuffer
infos += d
+ true
}
override def hasPending: Boolean = infos != null && {
@@ -33,4 +34,6 @@ class StoreReporter extends Reporter {
infos foreach ctx.reporter.report
infos = null
}
+
+ override def errorsReported = hasErrors || outer.errorsReported
}
diff --git a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
index 026453036..7c63383e9 100644
--- a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
@@ -11,7 +11,7 @@ import Reporter._
* info to the underlying reporter.
*/
class ThrowingReporter(reportInfo: Reporter) extends Reporter {
- def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {
+ def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = d match {
case _: Error => throw d
case _ => reportInfo.doReport(d)
}
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index 2296ae658..1f47b4486 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -118,7 +118,7 @@ class TreeChecker extends Phase with SymTransformer {
val squahsedPhase = ctx.squashed(prevPhase)
ctx.println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")
val checkingCtx = ctx.fresh
- .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.typerState.reporter)))
+ .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.reporter)))
val checker = new Checker(previousPhases(phasesToRun.toList)(ctx))
try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx)
catch {
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 87ad0831c..0fee17bcd 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -153,7 +153,7 @@ trait Applications extends Compatibility { self: Typer =>
def ok = _ok
def ok_=(x: Boolean) = {
- assert(x || ctx.errorsReported || !ctx.typerState.isCommittable) // !!! DEBUG
+ assert(x || ctx.reporter.errorsReported || !ctx.typerState.isCommittable) // !!! DEBUG
_ok = x
}
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 5444dddb0..e3626fe20 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -495,7 +495,7 @@ trait Implicits { self: Typer =>
case _ => false
}
}
- if (ctx.typerState.reporter.hasErrors)
+ if (ctx.reporter.hasErrors)
nonMatchingImplicit(ref)
else if (contextual && !ctx.mode.is(Mode.ImplicitShadowing) &&
!shadowing.tpe.isError && !refMatches(shadowing)) {
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index f414d3bce..ac4ad1b35 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -141,7 +141,7 @@ object Inferencing {
if (toTest.isEmpty) acc
else tree match {
case Apply(fn, _) =>
- fn.tpe match {
+ fn.tpe.widen match {
case mtp: MethodType =>
val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn))
occurring(fn, nocc, occ ::: acc)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 745eee8f8..60ecaac0b 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -200,7 +200,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
def isDefinedInCurrentUnit(denot: Denotation): Boolean = denot match {
case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2)
- case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source
+ case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source.file
}
/** Is `denot` the denotation of a self symbol? */
@@ -502,6 +502,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
}
+ private def decomposeProtoFunction(pt: Type, defaultArity: Int)(implicit ctx: Context): (List[Type], Type) = pt match {
+ case _ if defn.isFunctionType(pt) =>
+ (pt.dealias.argInfos.init, pt.dealias.argInfos.last)
+ case SAMType(meth) =>
+ val mt @ MethodType(_, paramTypes) = meth.info
+ (paramTypes, mt.resultType)
+ case _ =>
+ (List.range(0, defaultArity) map alwaysWildcardType, WildcardType)
+ }
+
def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") {
val untpd.Function(args, body) = tree
if (ctx.mode is Mode.Type)
@@ -509,15 +519,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
untpd.TypeTree(defn.FunctionClass(args.length).typeRef), args :+ body), pt)
else {
val params = args.asInstanceOf[List[untpd.ValDef]]
- val (protoFormals, protoResult): (List[Type], Type) = pt match {
- case _ if defn.isFunctionType(pt) =>
- (pt.dealias.argInfos.init, pt.dealias.argInfos.last)
- case SAMType(meth) =>
- val mt @ MethodType(_, paramTypes) = meth.info
- (paramTypes, mt.resultType)
- case _ =>
- (params map alwaysWildcardType, WildcardType)
- }
+ val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length)
def refersTo(arg: untpd.Tree, param: untpd.ValDef): Boolean = arg match {
case Ident(name) => name == param.name
@@ -563,7 +565,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val pos = params indexWhere (_.name == param.name)
if (pos < mtpe.paramTypes.length) {
val ptype = mtpe.paramTypes(pos)
- if (isFullyDefined(ptype, ForceDegree.none)) return ptype
+ if (isFullyDefined(ptype, ForceDegree.noBottom)) return ptype
}
case _ =>
}
@@ -629,7 +631,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context) = track("typedMatch") {
tree.selector match {
case EmptyTree =>
- typed(desugar.makeCaseLambda(tree.cases) withPos tree.pos, pt)
+ val (protoFormals, _) = decomposeProtoFunction(pt, 1)
+ typed(desugar.makeCaseLambda(tree.cases, protoFormals.length) withPos tree.pos, pt)
case _ =>
val sel1 = typedExpr(tree.selector)
val selType = widenForMatchSelector(
@@ -1000,7 +1003,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(implicit ctx: Context): List[Tree] = {
val firstParent :: otherParents = parents
- if (firstParent.isType && !(cls is Trait))
+ if (firstParent.isType && !(cls is Trait) && !cls.is(JavaDefined))
typed(untpd.New(untpd.TypedSplice(firstParent), Nil)) :: otherParents
else parents
}
@@ -1238,7 +1241,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ {
/*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ {
- interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol)
+ if (tree.isDef) interpolateUndetVars(tree, tree.symbol)
+ else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol)
tree.overwriteType(tree.tpe.simplified)
adaptInterpolated(tree, pt, original)
}
diff --git a/test/dotc/build.scala b/test/dotc/build.scala
index 9f47796c3..2963b8f1e 100644
--- a/test/dotc/build.scala
+++ b/test/dotc/build.scala
@@ -21,6 +21,8 @@ object build extends tests {
def main(args: Array[String]): Unit = {
println("------------ Building dotty ------------")
deleteFilesInFolder(new File(defaultOutputDir)) // clear previous output
+ val keepFile = new File(defaultOutputDir + ".keep")
+ keepFile.createNewFile()
dotty // build output dir
val p = Runtime.getRuntime.exec(Array("jar", "cf", "dotty.jar", "-C", "out", "."))
p.waitFor()
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 700dcd494..deea12272 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -77,7 +77,7 @@ class tests extends CompilerTest {
@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_typedIdents() = compileDir(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)
@@ -103,14 +103,14 @@ class tests extends CompilerTest {
@Test def neg_abstractOverride() = compileFile(negDir, "abstract-override", xerrors = 2)
@Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 1)
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
- @Test def neg_typedidents() = compileFile(negDir, "typedIdents", xerrors = 2)
+ @Test def neg_typedIdents() = compileDir(negDir, "typedIdents", xerrors = 2)
@Test def neg_assignments() = compileFile(negDir, "assignments", xerrors = 3)
@Test def neg_typers() = compileFile(negDir, "typers", xerrors = 14)(allowDoubleBindings)
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
@Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)
- @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", args = "-language:noAutoTupling" :: Nil, xerrors = 4)
- @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4)
+ @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", args = "-language:noAutoTupling" :: Nil, xerrors = 3)
+ @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 3)
@Test def neg_companions = compileFile(negDir, "companions", xerrors = 1)
@Test def neg_over = compileFile(negDir, "over", xerrors = 3)
@Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 11)
@@ -145,6 +145,7 @@ class tests extends CompilerTest {
@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_i866 = compileFile(negDir, "i866", xerrors = 2)
@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)
diff --git a/tests/neg/i866.scala b/tests/neg/i866.scala
new file mode 100644
index 000000000..2cdc99ede
--- /dev/null
+++ b/tests/neg/i866.scala
@@ -0,0 +1,9 @@
+object Test {
+ def x: Int = "" // error
+}
+import nonexistent._ // error; this one will swallow all errors below.
+object Foo {
+ def bar(implicit x: NonExistent) = ???
+ val baz = bar
+}
+
diff --git a/tests/neg/typedIdents/PQ.scala b/tests/neg/typedIdents/PQ.scala
new file mode 100644
index 000000000..8a5afede0
--- /dev/null
+++ b/tests/neg/typedIdents/PQ.scala
@@ -0,0 +1,6 @@
+package P {
+ object X { val x = 1; val y = 2 }
+}
+package Q {
+ object X { val x = true; val y = "" }
+}
diff --git a/tests/neg/typedIdents.scala b/tests/neg/typedIdents/typedIdents.scala
index cb7cca743..4937edfe3 100644
--- a/tests/neg/typedIdents.scala
+++ b/tests/neg/typedIdents/typedIdents.scala
@@ -1,9 +1,3 @@
-package P {
- object X { val x = 1; val y = 2 }
-}
-package Q {
- object X { val x = true; val y = "" }
-}
package P { // `X' bound by package clause
import Console._ // `println' bound by wildcard import
object A {
diff --git a/tests/pos/i830.scala b/tests/pos/i830.scala
new file mode 100644
index 000000000..8fcb29f36
--- /dev/null
+++ b/tests/pos/i830.scala
@@ -0,0 +1,6 @@
+object C {
+ trait X[T]
+ implicit def u[A, B]: X[A | B] = new X[A | B] {}
+ def y[T](implicit x: X[T]): T = ???
+ val x: 1 & 2 | 2 & 3 = y
+}
diff --git a/tests/pos/i873.scala b/tests/pos/i873.scala
new file mode 100644
index 000000000..94f8d2c67
--- /dev/null
+++ b/tests/pos/i873.scala
@@ -0,0 +1,10 @@
+object Test {
+ def call(k: (Int, Int) => Unit): Unit = ???
+ def test = call({ case (x, y) => ()})
+
+ trait X extends Function1[Int, String]
+ implicit def f2x(f: Function1[Int, String]): X = ???
+ ({case _ if "".isEmpty => ""} : X) // allowed, implicit view used to adapt
+
+ // ({case _ if "".isEmpty => 0} : X) // expected String, found Int
+}
diff --git a/tests/pos/i884.scala b/tests/pos/i884.scala
new file mode 100644
index 000000000..29e53b9be
--- /dev/null
+++ b/tests/pos/i884.scala
@@ -0,0 +1,4 @@
+import scala.reflect._
+
+object `package` {
+}
diff --git a/tests/pos/i903.scala b/tests/pos/i903.scala
new file mode 100644
index 000000000..5afb6e530
--- /dev/null
+++ b/tests/pos/i903.scala
@@ -0,0 +1,26 @@
+object Test {
+ def contains(s: String, i: Int) = true
+ def test1 = {
+ val f = contains("", (_: Int))
+ val ff = contains("", ((_: Int)))
+ val g: Int => Boolean = contains("", (_))
+ val gg: Int => Boolean = contains("", ((_)))
+ f.apply(0)
+ // sandbox/eta.scala:4: error: type mismatch:
+ // found : Int => Int
+ // required: Int
+ // val f = contains("", (_: Int))
+ // ^
+ // sandbox/eta.scala:5: error: apply is not a member of Boolean(f)
+ // f.apply(0)
+ // ^
+ }
+
+ def test2 = {
+ val f = "".contains("", (_: Int)) // dotc:
+ f.apply(0)
+ // sandbox/eta.scala:18: error: apply is not a member of Boolean(f)
+ // f.apply(0)
+ // ^
+ }
+}
diff --git a/tests/pos/java-interop/i879.java b/tests/pos/java-interop/i879.java
new file mode 100644
index 000000000..6db5b77ff
--- /dev/null
+++ b/tests/pos/java-interop/i879.java
@@ -0,0 +1,11 @@
+class Foo {
+ Foo(int i) {
+ }
+}
+
+
+class Bar extends Foo {
+ Bar() {
+ super(10);
+ }
+} \ No newline at end of file
diff --git a/tests/pos/java-interop/volatile/volatile.java b/tests/pos/java-interop/volatile/volatile.java
new file mode 100644
index 000000000..c6a607b4d
--- /dev/null
+++ b/tests/pos/java-interop/volatile/volatile.java
@@ -0,0 +1,3 @@
+public class Foo {
+ volatile int x = 1;
+}
diff --git a/tests/pos/overloadedAccess.scala b/tests/pos/overloadedAccess.scala
index a2d72f583..10168b61d 100644
--- a/tests/pos/overloadedAccess.scala
+++ b/tests/pos/overloadedAccess.scala
@@ -14,5 +14,4 @@ object overloadedAccess {
val x = f("abc")
val y: Int = x
}
-
}
diff --git a/tests/pos/range.scala b/tests/pos/range.scala
new file mode 100644
index 000000000..9e7b5d1c9
--- /dev/null
+++ b/tests/pos/range.scala
@@ -0,0 +1,9 @@
+import scala.math._
+import collection.immutable.NumericRange
+object Test {
+ val r1: scala.collection.immutable.Range.Partial = ???
+ val r2: scala.Range.Partial = r1
+ def until(d: BigDecimal, end: BigDecimal): Range.Partial[BigDecimal, NumericRange.Exclusive[BigDecimal]] =
+ new Range.Partial(until(d, end, _))
+ def until(d: BigDecimal, end: BigDecimal, step: BigDecimal) = Range.BigDecimal(d, end, step)
+}
diff --git a/tests/pos/tparam_inf.scala b/tests/pos/tparam_inf.scala
new file mode 100644
index 000000000..16d99b75d
--- /dev/null
+++ b/tests/pos/tparam_inf.scala
@@ -0,0 +1,38 @@
+class HasFoo[T] {
+ val x: Foo[T] = ???
+}
+class Foo[T] {
+ def get(x: T): T = x
+ def get2(x: T): Nothing = ???
+
+ def foo1(x: T)(implicit ev: T): Nothing = ???
+ def foo2(x: T)(implicit ev: T): T = ???
+ def foo3[Dummy](x: T)(implicit ev: T): Nothing = ???
+ def foo4[Dummy](x: T)(implicit ev: T): T = ???
+}
+
+object Test {
+
+ def foo1[T](x: T)(implicit ev: T): Nothing = ???
+ def foo2[T](x: T)(implicit ev: T): T = ???
+
+ def test1: Unit = {
+ implicit val ii: Int = 42
+
+ foo1(10)
+ foo2(10)
+ }
+
+ def hf[T]: HasFoo[T] = ???
+ def test2: Unit = {
+ implicit val ii: Int = 42
+
+ hf.x.get(10)
+ hf.x.get2(10)
+
+ hf.x.foo1(10)
+ hf.x.foo2(10)
+ hf.x.foo3(10)
+ hf.x.foo4(10)
+ }
+}
diff --git a/tests/pos/typedIdents/PQ.scala b/tests/pos/typedIdents/PQ.scala
new file mode 100644
index 000000000..8a5afede0
--- /dev/null
+++ b/tests/pos/typedIdents/PQ.scala
@@ -0,0 +1,6 @@
+package P {
+ object X { val x = 1; val y = 2 }
+}
+package Q {
+ object X { val x = true; val y = "" }
+}
diff --git a/tests/pos/typedIdents.scala b/tests/pos/typedIdents/typedIdents.scala
index e99b5a045..95b9f1b63 100644
--- a/tests/pos/typedIdents.scala
+++ b/tests/pos/typedIdents/typedIdents.scala
@@ -1,9 +1,3 @@
-package P {
- object X { val x = 1; val y = 2 }
-}
-package Q {
- object X { val x = true; val y = "" }
-}
package P { // `X' bound by package clause
import Console._ // `println' bound by wildcard import
object A {