aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bridge/src/main/scala/xsbt/CompilerInterface.scala6
-rw-r--r--bridge/src/main/scala/xsbt/DelegatingReporter.scala58
-rw-r--r--bridge/src/sbt-test/compilerReporter/simple/Source.scala10
-rw-r--r--bridge/src/sbt-test/compilerReporter/simple/build.sbt1
-rw-r--r--bridge/src/sbt-test/compilerReporter/simple/project/DottyInjectedPlugin.scala17
-rw-r--r--bridge/src/sbt-test/compilerReporter/simple/project/Reporter.scala44
-rw-r--r--bridge/src/sbt-test/compilerReporter/simple/test1
-rw-r--r--docs/SyntaxSummary.txt2
-rw-r--r--project/Build.scala20
-rw-r--r--project/plugins.sbt2
-rw-r--r--src/dotty/tools/backend/jvm/CollectSuperCalls.scala12
-rw-r--r--src/dotty/tools/backend/jvm/DottyBackendInterface.scala14
-rw-r--r--src/dotty/tools/dotc/Compiler.scala4
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala96
-rw-r--r--src/dotty/tools/dotc/ast/NavigateAST.scala9
-rw-r--r--src/dotty/tools/dotc/ast/Positioned.scala84
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala47
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala146
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala40
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala106
-rw-r--r--src/dotty/tools/dotc/config/Config.scala3
-rw-r--r--src/dotty/tools/dotc/config/Printers.scala2
-rw-r--r--src/dotty/tools/dotc/core/CheckRealizable.scala1
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala2
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala2
-rw-r--r--src/dotty/tools/dotc/core/ConstraintRunInfo.scala3
-rw-r--r--src/dotty/tools/dotc/core/OrderingConstraint.scala1
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala32
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--src/dotty/tools/dotc/core/Types.scala11
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyFormat.scala5
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala5
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala13
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala9
-rw-r--r--src/dotty/tools/dotc/parsing/JavaParsers.scala174
-rw-r--r--src/dotty/tools/dotc/parsing/JavaScanners.scala1
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala184
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala37
-rw-r--r--src/dotty/tools/dotc/reporting/StoreReporter.scala2
-rw-r--r--src/dotty/tools/dotc/sbt/ExtractDependencies.scala2
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala3
-rw-r--r--src/dotty/tools/dotc/transform/ExpandSAMs.scala2
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala14
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala160
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala13
-rw-r--r--src/dotty/tools/dotc/transform/SelectStatic.scala24
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala7
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala58
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala27
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Dynamic.scala85
-rw-r--r--src/dotty/tools/dotc/typer/FrontEnd.scala5
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala11
-rw-r--r--src/dotty/tools/dotc/typer/ImportInfo.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala7
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala6
-rw-r--r--src/dotty/tools/dotc/typer/ReTyper.scala6
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala55
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala275
-rw-r--r--src/dotty/tools/dotc/typer/VarianceChecker.scala6
-rw-r--r--test/test/parsePackage.scala4
-rw-r--r--tests/disabled/not-representable/hkt/compiler.error (renamed from tests/pending/hkt/compiler.error)0
-rw-r--r--tests/disabled/not-representable/hkt/hkt.scala (renamed from tests/pending/hkt/hkt.scala)3
-rw-r--r--tests/disabled/not-representable/t2337.scala (renamed from tests/pending/run/t2337.scala)2
-rw-r--r--tests/neg/applydynamic_sip.check52
-rw-r--r--tests/neg/applydynamic_sip.flags (renamed from tests/untried/neg/applydynamic_sip.flags)0
-rw-r--r--tests/neg/applydynamic_sip.scala36
-rw-r--r--tests/neg/emptyCatch.scala3
-rw-r--r--tests/neg/i1503.scala14
-rw-r--r--tests/neg/t6355b.check (renamed from tests/untried/neg/t6355b.check)4
-rw-r--r--tests/neg/t6355b.scala (renamed from tests/untried/neg/t6355b.scala)4
-rw-r--r--tests/neg/t6663.check (renamed from tests/untried/neg/t6663.check)0
-rw-r--r--tests/neg/t6663.scala (renamed from tests/untried/neg/t6663.scala)2
-rw-r--r--tests/neg/t6920.check (renamed from tests/untried/neg/t6920.check)2
-rw-r--r--tests/neg/t6920.scala (renamed from tests/untried/neg/t6920.scala)2
-rw-r--r--tests/neg/t8006.check (renamed from tests/untried/neg/t8006.check)2
-rw-r--r--tests/neg/t8006.scala (renamed from tests/untried/neg/t8006.scala)2
-rw-r--r--tests/pending/import-rewrite/compiler.error6
-rw-r--r--tests/pending/run/t2337.check4
-rw-r--r--tests/pending/run/t3150.scala36
-rw-r--r--tests/pending/run/unapply.check3
-rw-r--r--tests/pos-scala2/naming-resolution/callsite.scala10
-rw-r--r--tests/pos-scala2/naming-resolution/package.scala5
-rw-r--r--tests/pos-scala2/t3050.scala (renamed from tests/pending/run/t3050.scala)0
-rw-r--r--tests/pos/import-rewrite/file.scala (renamed from tests/pending/import-rewrite/file.scala)0
-rw-r--r--tests/pos/import-rewrite/rewrite.scala (renamed from tests/pending/import-rewrite/rewrite.scala)0
-rw-r--r--tests/pos/t1500a.scala28
-rw-r--r--tests/pos/t1513a.scala36
-rw-r--r--tests/pos/t1513b.scala25
-rw-r--r--tests/pos/tryWithoutHandler.scala7
-rw-r--r--tests/run/applydynamic_sip.check (renamed from tests/pending/run/applydynamic_sip.check)0
-rw-r--r--tests/run/applydynamic_sip.flags (renamed from tests/pending/run/applydynamic_sip.flags)0
-rw-r--r--tests/run/applydynamic_sip.scala (renamed from tests/pending/run/applydynamic_sip.scala)1
-rw-r--r--tests/run/dynamic-anyval.check (renamed from tests/pending/run/dynamic-anyval.check)0
-rw-r--r--tests/run/dynamic-anyval.scala (renamed from tests/pending/run/dynamic-anyval.scala)0
-rw-r--r--tests/run/dynamicDynamicTests.scala41
-rw-r--r--tests/run/i1503.check5
-rw-r--r--tests/run/i1503.scala38
-rw-r--r--tests/run/t1335.scala11
-rw-r--r--tests/run/t1500b.scala21
-rw-r--r--tests/run/t1500c.scala19
-rw-r--r--tests/run/t298.check (renamed from tests/pending/run/t298.check)0
-rw-r--r--tests/run/t298.scala (renamed from tests/pending/run/t298.scala)0
-rw-r--r--tests/run/t3026.check (renamed from tests/pending/run/t3026.check)0
-rwxr-xr-xtests/run/t3026.scala (renamed from tests/pending/run/t3026.scala)0
-rw-r--r--tests/run/t3353.check (renamed from tests/pending/run/t3353.check)0
-rw-r--r--tests/run/t3353.scala (renamed from tests/pending/run/t3353.scala)0
-rw-r--r--tests/run/t4536.check (renamed from tests/pending/run/t4536.check)0
-rw-r--r--tests/run/t4536.flags (renamed from tests/pending/run/t4536.flags)0
-rw-r--r--tests/run/t4536.scala (renamed from tests/pending/run/t4536.scala)8
-rw-r--r--tests/run/t5040.check (renamed from tests/pending/run/t5040.check)0
-rw-r--r--tests/run/t5040.flags (renamed from tests/pending/run/t5040.flags)0
-rw-r--r--tests/run/t5040.scala (renamed from tests/pending/run/t5040.scala)1
-rw-r--r--tests/run/t5733.check (renamed from tests/pending/run/t5733.check)0
-rw-r--r--tests/run/t5733.scala (renamed from tests/pending/run/t5733.scala)0
-rw-r--r--tests/run/t6353.check (renamed from tests/pending/run/t6353.check)0
-rw-r--r--tests/run/t6353.scala (renamed from tests/pending/run/t6353.scala)0
-rw-r--r--tests/run/t6355.check (renamed from tests/pending/run/t6355.check)0
-rw-r--r--tests/run/t6355.scala (renamed from tests/pending/run/t6355.scala)0
-rw-r--r--tests/run/t6663.check (renamed from tests/pending/run/t6663.check)0
-rw-r--r--tests/run/t6663.flags (renamed from tests/pending/run/t6663.flags)0
-rw-r--r--tests/run/t6663.scala (renamed from tests/pending/run/t6663.scala)0
-rw-r--r--tests/run/unapply.scala (renamed from tests/pending/run/unapply.scala)4
-rw-r--r--tests/untried/neg/applydynamic_sip.check73
-rw-r--r--tests/untried/neg/applydynamic_sip.scala33
130 files changed, 1497 insertions, 1047 deletions
diff --git a/bridge/src/main/scala/xsbt/CompilerInterface.scala b/bridge/src/main/scala/xsbt/CompilerInterface.scala
index ee272b8b1..bf1488dad 100644
--- a/bridge/src/main/scala/xsbt/CompilerInterface.scala
+++ b/bridge/src/main/scala/xsbt/CompilerInterface.scala
@@ -50,12 +50,14 @@ class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean)
(outputArgs ++ args.toList ++ sources.map(_.getAbsolutePath).sortWith(_ < _)).toArray[String]
def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, progress: CompileProgress): Unit = synchronized {
- run(sources.toList, changes, callback, log, progress)
+ run(sources.toList, changes, callback, log, delegate, progress)
}
- private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, compileProgress: CompileProgress): Unit = {
+ private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, compileProgress: CompileProgress): Unit = {
debug(log, args.mkString("Calling Dotty compiler with arguments (CompilerInterface):\n\t", "\n\t", ""))
val ctx = (new ContextBase).initialCtx.fresh
.setSbtCallback(callback)
+ .setReporter(new DelegatingReporter(delegate))
+
val cl = getClass.getClassLoader.asInstanceOf[URLClassLoader]
val reporter = DottyMain.process(commandArguments(sources.toArray), ctx)
diff --git a/bridge/src/main/scala/xsbt/DelegatingReporter.scala b/bridge/src/main/scala/xsbt/DelegatingReporter.scala
new file mode 100644
index 000000000..726570d71
--- /dev/null
+++ b/bridge/src/main/scala/xsbt/DelegatingReporter.scala
@@ -0,0 +1,58 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2008, 2009 Mark Harrah
+ */
+package xsbt
+
+import dotty.tools._
+import dotc._
+import reporting._
+import core.Contexts._
+
+import xsbti.{Maybe, Position}
+
+final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
+ with UniqueMessagePositions
+ with HideNonSensicalMessages {
+
+ override def printSummary(implicit ctx: Context): Unit = delegate.printSummary()
+
+ def doReport(d: Diagnostic)(implicit ctx: Context): Unit = {
+ val severity =
+ d match {
+ case _: Reporter.Error => xsbti.Severity.Error
+ case _: Reporter.Warning => xsbti.Severity.Warn
+ case _ => xsbti.Severity.Info
+ }
+ val pos =
+ if (d.pos.exists) Some(d.pos)
+ else None
+
+ val file =
+ if (d.pos.source.file.exists) Option(d.pos.source.file.file)
+ else None
+
+ val offset0 = pos.map(_.point)
+
+ val position = new Position {
+ def line: Maybe[Integer] = maybe(pos.map(_.line))
+ def lineContent: String = pos.map(_.lineContent).getOrElse("")
+ def offset: Maybe[Integer] = maybeInt(offset0)
+ def pointer: Maybe[Integer] = offset
+ def pointerSpace: Maybe[String] = maybe(offset0.map(" " * _))
+ def sourceFile: Maybe[java.io.File] = maybe(file)
+ def sourcePath: Maybe[String] = maybe(file.map(_.getPath))
+ }
+
+ delegate.log(position, d.message, severity)
+ }
+
+ private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
+ case None => Maybe.nothing[T]
+ case Some(s) => Maybe.just[T](s)
+ }
+ import java.lang.{ Integer => I }
+ private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
+ case None => Maybe.nothing[I]
+ case Some(s) => Maybe.just[I](s)
+ }
+} \ No newline at end of file
diff --git a/bridge/src/sbt-test/compilerReporter/simple/Source.scala b/bridge/src/sbt-test/compilerReporter/simple/Source.scala
new file mode 100644
index 000000000..6f0678599
--- /dev/null
+++ b/bridge/src/sbt-test/compilerReporter/simple/Source.scala
@@ -0,0 +1,10 @@
+trait A
+trait B
+
+trait Wr {
+ val z: A with B
+}
+
+object Er {
+ val a = er1
+} \ No newline at end of file
diff --git a/bridge/src/sbt-test/compilerReporter/simple/build.sbt b/bridge/src/sbt-test/compilerReporter/simple/build.sbt
new file mode 100644
index 000000000..017846f5e
--- /dev/null
+++ b/bridge/src/sbt-test/compilerReporter/simple/build.sbt
@@ -0,0 +1 @@
+Reporter.checkSettings \ No newline at end of file
diff --git a/bridge/src/sbt-test/compilerReporter/simple/project/DottyInjectedPlugin.scala b/bridge/src/sbt-test/compilerReporter/simple/project/DottyInjectedPlugin.scala
new file mode 100644
index 000000000..3433779b6
--- /dev/null
+++ b/bridge/src/sbt-test/compilerReporter/simple/project/DottyInjectedPlugin.scala
@@ -0,0 +1,17 @@
+import sbt._
+import Keys._
+
+object DottyInjectedPlugin extends AutoPlugin {
+ override def requires = plugins.JvmPlugin
+ override def trigger = allRequirements
+
+ override val projectSettings = Seq(
+ scalaVersion := "0.1-SNAPSHOT",
+ scalaOrganization := "ch.epfl.lamp",
+ scalacOptions += "-language:Scala2",
+ scalaBinaryVersion := "2.11",
+ autoScalaLibrary := false,
+ libraryDependencies ++= Seq("org.scala-lang" % "scala-library" % "2.11.5"),
+ scalaCompilerBridgeSource := ("ch.epfl.lamp" % "dotty-bridge" % "0.1.1-SNAPSHOT" % "component").sources()
+ )
+}
diff --git a/bridge/src/sbt-test/compilerReporter/simple/project/Reporter.scala b/bridge/src/sbt-test/compilerReporter/simple/project/Reporter.scala
new file mode 100644
index 000000000..c0a56ec82
--- /dev/null
+++ b/bridge/src/sbt-test/compilerReporter/simple/project/Reporter.scala
@@ -0,0 +1,44 @@
+import sbt._
+import Keys._
+import KeyRanks.DTask
+
+object Reporter {
+ import xsbti.{Reporter, Problem, Position, Severity, Maybe}
+
+ lazy val check = TaskKey[Unit]("check", "make sure compilation info are forwared to sbt")
+
+ // compilerReporter is marked private in sbt
+ lazy val compilerReporter = TaskKey[Option[xsbti.Reporter]]("compilerReporter", "Experimental hook to listen (or send) compilation failure messages.", DTask)
+
+ lazy val reporter =
+ Some(new xsbti.Reporter {
+ private val buffer = collection.mutable.ArrayBuffer.empty[Problem]
+ def reset(): Unit = buffer.clear()
+ def hasErrors: Boolean = buffer.exists(_.severity == Severity.Error)
+ def hasWarnings: Boolean = buffer.exists(_.severity == Severity.Warn)
+ def printSummary(): Unit = println(problems.mkString(System.lineSeparator))
+ def problems: Array[Problem] = buffer.toArray
+ def log(pos: Position, msg: String, sev: Severity): Unit = {
+ object MyProblem extends Problem {
+ def category: String = null
+ def severity: Severity = sev
+ def message: String = msg
+ def position: Position = pos
+ override def toString = s"custom: $position:$severity: $message"
+ }
+ buffer.append(MyProblem)
+ }
+ def comment(pos: xsbti.Position, msg: String): Unit = ()
+ })
+
+ lazy val checkSettings = Seq(
+ compilerReporter in (Compile, compile) := reporter,
+ check <<= (compile in Compile).mapFailure( _ => {
+ val problems = reporter.get.problems
+ println(problems.toList)
+ assert(problems.size == 2)
+ assert(problems.count(_.severity == Severity.Error) == 1) // not found: er1,
+ assert(problems.count(_.severity == Severity.Warn) == 1) // `with' as a type operator has been deprecated; use `&' instead,
+ })
+ )
+} \ No newline at end of file
diff --git a/bridge/src/sbt-test/compilerReporter/simple/test b/bridge/src/sbt-test/compilerReporter/simple/test
new file mode 100644
index 000000000..a5912a391
--- /dev/null
+++ b/bridge/src/sbt-test/compilerReporter/simple/test
@@ -0,0 +1 @@
+> check \ No newline at end of file
diff --git a/docs/SyntaxSummary.txt b/docs/SyntaxSummary.txt
index f07335d1d..6c83c71ab 100644
--- a/docs/SyntaxSummary.txt
+++ b/docs/SyntaxSummary.txt
@@ -105,7 +105,7 @@ grammar.
WithType ::= AnnotType {`with' AnnotType} (deprecated)
AnnotType ::= SimpleType {Annotation} Annotated(t, annot)
SimpleType ::= SimpleType (TypeArgs | NamedTypeArgs) AppliedTypeTree(t, args)
- | SimpleType `#' id SelectFromTypeTree(t, name)
+ | SimpleType `#' id Select(t, name)
| StableId
| Path `.' `type' SingletonTypeTree(p)
| `(' ArgTypes ')' Tuple(ts)
diff --git a/project/Build.scala b/project/Build.scala
index 88ee7dca7..7c57bd862 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -207,11 +207,31 @@ object DottyBuild extends Build {
).
settings(publishing)
+ // until sbt/sbt#2402 is fixed (https://github.com/sbt/sbt/issues/2402)
+ lazy val cleanSbtBridge = TaskKey[Unit]("cleanSbtBridge", "delete dotty-sbt-bridge cache")
+
lazy val `dotty-bridge` = project.in(file("bridge")).
dependsOn(dotty).
settings(
overrideScalaVersionSetting,
+ cleanSbtBridge := {
+ val dottyBridgeVersion = version.value
+ val dottyVersion = (version in dotty).value
+ val classVersion = System.getProperty("java.class.version")
+
+ val sbtV = sbtVersion.value
+ val sbtOrg = "org.scala-sbt"
+ val sbtScalaVersion = "2.10.6"
+
+ val home = System.getProperty("user.home")
+ val org = organization.value
+ val artifact = moduleName.value
+
+ IO.delete(file(home) / ".ivy2" / "cache" / sbtOrg / s"$org-$artifact-$dottyBridgeVersion-bin_${dottyVersion}__$classVersion")
+ IO.delete(file(home) / ".sbt" / "boot" / s"scala-$sbtScalaVersion" / sbtOrg / "sbt" / sbtV / s"$org-$artifact-$dottyBridgeVersion-bin_${dottyVersion}__$classVersion")
+ },
+ publishLocal := (publishLocal.dependsOn(cleanSbtBridge)).value,
description := "sbt compiler bridge for Dotty",
resolvers += Resolver.typesafeIvyRepo("releases"),
libraryDependencies ++= Seq(
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 8ac4d69bf..57bd46581 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -8,5 +8,3 @@ addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.8")
-
-addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.5")
diff --git a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala
index 8f9b067ba..8285bfe4b 100644
--- a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala
+++ b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala
@@ -4,9 +4,13 @@ import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.Trees._
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Symbols._
+import dotty.tools.dotc.core.Flags.Trait
import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo}
-/** Collect all super calls except to the parent class.
+/** Collect all super calls to trait members.
+ *
+ * For each super reference to trait member, register a call from the current class to the
+ * owner of the referenced member.
*
* This information is used to know if it is safe to remove a redundant mixin class.
* A redundant mixin class is one that is implemented by another mixin class. As the
@@ -20,9 +24,9 @@ class CollectSuperCalls extends MiniPhaseTransform {
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = {
tree.qualifier match {
- case Super(qual: This, mix) if mix.nonEmpty =>
- val classSymbol = qual.symbol.asClass.classSymbol
- registerSuperCall(classSymbol, tree.symbol.owner.asClass)
+ case sup: Super =>
+ if (tree.symbol.owner.is(Trait))
+ registerSuperCall(ctx.owner.enclosingClass.asClass, tree.symbol.owner.asClass)
case _ =>
}
tree
diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
index 30934605b..2d60d851c 100644
--- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
+++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
@@ -70,7 +70,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
type Bind = tpd.Bind
type New = tpd.New
type Super = tpd.Super
- type Modifiers = tpd.Modifiers
+ type Modifiers = Null
type Annotation = Annotations.Annotation
type ArrayValue = tpd.JavaSeqLiteral
type ApplyDynamic = Null
@@ -747,9 +747,13 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
*/
def superInterfaces: List[Symbol] = {
val directlyInheritedTraits = decorateSymbol(sym).directlyInheritedTraits
+ val directlyInheritedTraitsSet = directlyInheritedTraits.toSet
val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.symbol.asClass.baseClasses.drop(1)).toSet
val superCalls = superCallsMap.getOrElse(sym, Set.empty)
- directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t))
+ val additional = (superCalls -- directlyInheritedTraitsSet).filter(_.is(Flags.Trait))
+// if (additional.nonEmpty)
+// println(s"$fullName: adding supertraits $additional")
+ directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t)) ++ additional
}
/**
@@ -940,7 +944,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
}
object ValDef extends ValDefDeconstructor {
- def _1: Modifiers = field.mods
+ def _1: Modifiers = null
def _2: Name = field.name
def _3: Tree = field.tpt
def _4: Tree = field.rhs
@@ -1051,7 +1055,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
}
object DefDef extends DefDefDeconstructor {
- def _1: Modifiers = field.mods
+ def _1: Modifiers = null
def _2: Name = field.name
def _3: List[TypeDef] = field.tparams
def _4: List[List[ValDef]] = field.vparamss
@@ -1077,7 +1081,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
}
object ClassDef extends ClassDefDeconstructor {
- def _1: Modifiers = field.mods
+ def _1: Modifiers = null
def _2: Name = field.name
def _4: Template = field.rhs.asInstanceOf[Template]
def _3: List[TypeDef] = Nil
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index d1f126860..2120fa73e 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -25,7 +25,7 @@ class Compiler {
/** Meta-ordering constraint:
*
- * DenotTransformers that change the signature of their denotation's info must go
+ * DenotTransformers that change the signature of their denotation's info must go
* after erasure. The reason is that denotations are permanently referred to by
* TermRefs which contain a signature. If the signature of a symbol would change,
* all refs to it would become outdated - they could not be dereferenced in the
@@ -83,7 +83,7 @@ class Compiler {
new CapturedVars, // Represent vars captured by closures as heap objects
new Constructors, // Collect initialization code in primary constructors
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
- new FunctionalInterfaces,// Rewrites closures to implement @specialized types of Functions.
+ new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
new GetClass), // Rewrites getClass calls on primitive types.
List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 500b28233..edd6da5c9 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -9,13 +9,8 @@ import Decorators._
import language.higherKinds
import collection.mutable.ListBuffer
import util.Attachment
-import config.Printers._
object desugar {
-
- /** Are we using the new unboxed pair scheme? */
- private final val unboxedPairs = false
-
import untpd._
/** Tags a .withFilter call generated by desugaring a for expression.
@@ -27,7 +22,7 @@ object desugar {
private type VarInfo = (NameTree, Tree)
/** Names of methods that are added unconditionally to case classes */
- def isDesugaredCaseClassMethodName(name: Name)(implicit ctx: Context) =
+ def isDesugaredCaseClassMethodName(name: Name)(implicit ctx: Context): Boolean =
name == nme.isDefined ||
name == nme.copy ||
name == nme.productArity ||
@@ -506,7 +501,7 @@ object desugar {
val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body)
val cls = TypeDef(clsName, clsTmpl)
.withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags)
- Thicket(modul, classDef(cls))
+ Thicket(modul, classDef(cls).withPos(mdef.pos))
}
}
@@ -517,7 +512,7 @@ object desugar {
def patDef(pdef: PatDef)(implicit ctx: Context): Tree = {
val PatDef(mods, pats, tpt, rhs) = pdef
val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
- flatTree(pats1 map (makePatDef(mods, _, rhs)))
+ flatTree(pats1 map (makePatDef(pdef, mods, _, rhs)))
}
/** If `pat` is a variable pattern,
@@ -535,9 +530,9 @@ object desugar {
* If the original pattern variable carries a type annotation, so does the corresponding
* ValDef or DefDef.
*/
- def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit ctx: Context): Tree = pat match {
+ def makePatDef(original: Tree, mods: Modifiers, pat: Tree, rhs: Tree)(implicit ctx: Context): Tree = pat match {
case VarPattern(named, tpt) =>
- derivedValDef(named, tpt, rhs, mods)
+ derivedValDef(original, named, tpt, rhs, mods)
case _ =>
val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs)
val vars = getVariables(pat)
@@ -554,7 +549,7 @@ object desugar {
case Nil =>
matchExpr
case (named, tpt) :: Nil =>
- derivedValDef(named, tpt, matchExpr, mods)
+ derivedValDef(original, named, tpt, matchExpr, mods)
case _ =>
val tmpName = ctx.freshName().toTermName
val patMods = mods & (AccessFlags | Lazy) | Synthetic
@@ -565,8 +560,8 @@ object desugar {
val restDefs =
for (((named, tpt), n) <- vars.zipWithIndex)
yield
- if (mods is Lazy) derivedDefDef(named, tpt, selector(n), mods &~ Lazy)
- else derivedValDef(named, tpt, selector(n), mods)
+ if (mods is Lazy) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy)
+ else derivedValDef(original, named, tpt, selector(n), mods)
flatTree(firstDef :: restDefs)
}
}
@@ -633,7 +628,7 @@ object desugar {
val selector = makeTuple(params.map(p => Ident(p.name)))
if (unchecked)
- Function(params, Match(Annotated(New(ref(defn.UncheckedAnnotType)), selector), cases))
+ Function(params, Match(Annotated(selector, New(ref(defn.UncheckedAnnotType))), cases))
else
Function(params, Match(selector, cases))
}
@@ -662,16 +657,20 @@ object desugar {
* tree @cls
*/
def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) =
- Annotated(untpd.New(untpd.TypeTree(cls.typeRef), Nil), tree)
+ Annotated(tree, untpd.New(untpd.TypeTree(cls.typeRef), Nil))
- private def derivedValDef(named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = {
- val vdef = ValDef(named.name.asTermName, tpt, rhs).withMods(mods).withPos(named.pos)
+ private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = {
+ val vdef = ValDef(named.name.asTermName, tpt, rhs)
+ .withMods(mods)
+ .withPos(original.pos.withPoint(named.pos.start))
val mayNeedSetter = valDef(vdef)
mayNeedSetter
}
- private def derivedDefDef(named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers) =
- DefDef(named.name.asTermName, Nil, Nil, tpt, rhs).withMods(mods).withPos(named.pos)
+ private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers) =
+ DefDef(named.name.asTermName, Nil, Nil, tpt, rhs)
+ .withMods(mods)
+ .withPos(original.pos.withPoint(named.pos.start))
/** Main desugaring method */
def apply(tree: Tree)(implicit ctx: Context): Tree = {
@@ -699,7 +698,7 @@ object desugar {
Apply(Select(left, op), args)
} else {
val x = ctx.freshName().toTermName
- Block(
+ new InfixOpBlock(
ValDef(x, TypeTree(), left).withMods(synthetic),
Apply(Select(right, op), Ident(x)))
}
@@ -761,7 +760,7 @@ object desugar {
*/
def makeLambda(pat: Tree, body: Tree): Tree = pat match {
case VarPattern(named, tpt) =>
- Function(derivedValDef(named, tpt, EmptyTree, Modifiers(Param)) :: Nil, body)
+ Function(derivedValDef(pat, named, tpt, EmptyTree, Modifiers(Param)) :: Nil, body)
case _ =>
makeCaseLambda(CaseDef(pat, EmptyTree, body) :: Nil, unchecked = false)
}
@@ -864,7 +863,7 @@ object desugar {
val rhss = valeqs map { case GenAlias(_, rhs) => rhs }
val (defpat0, id0) = makeIdPat(pat)
val (defpats, ids) = (pats map makeIdPat).unzip
- val pdefs = (defpats, rhss).zipped map (makePatDef(Modifiers(), _, _))
+ val pdefs = (valeqs, defpats, rhss).zipped.map(makePatDef(_, Modifiers(), _, _))
val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom(defpat0, rhs) :: Nil, Block(pdefs, makeTuple(id0 :: ids)))
val allpats = pat :: pats
val vfrom1 = new IrrefutableGenFrom(makeTuple(allpats), rhs1)
@@ -886,7 +885,15 @@ object desugar {
Apply(
ref(defn.SymbolClass.companionModule.termRef),
Literal(Constant(str)) :: Nil)
- case InterpolatedString(id, strs, elems) =>
+ case InterpolatedString(id, segments) =>
+ val strs = segments map {
+ case ts: Thicket => ts.trees.head
+ case t => t
+ }
+ val elems = segments flatMap {
+ case ts: Thicket => ts.trees.tail
+ case t => Nil
+ }
Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
case InfixOp(l, op, r) =>
if (ctx.mode is Mode.Type)
@@ -901,8 +908,8 @@ object desugar {
if ((ctx.mode is Mode.Type) && op == nme.raw.STAR) {
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType
Annotated(
- New(ref(defn.RepeatedAnnotType), Nil :: Nil),
- AppliedTypeTree(ref(seqType), t))
+ AppliedTypeTree(ref(seqType), t),
+ New(ref(defn.RepeatedAnnotType), Nil :: Nil))
} else {
assert(ctx.mode.isExpr || ctx.reporter.hasErrors, ctx.mode)
Select(t, op)
@@ -912,25 +919,15 @@ object desugar {
case Parens(t) =>
t
case Tuple(ts) =>
- if (unboxedPairs) {
- def PairTypeTree(l: Tree, r: Tree) =
- AppliedTypeTree(ref(defn.PairType), l :: r :: Nil)
- if (ctx.mode is Mode.Type) ts.reduceRight(PairTypeTree)
- else if (ts.isEmpty) unitLiteral
- else ts.reduceRight(Pair(_, _))
- }
- else {
- val arity = ts.length
- def tupleTypeRef = defn.TupleType(arity)
- if (arity > Definitions.MaxTupleArity) {
- ctx.error(s"tuple too long (max allowed: ${Definitions.MaxTupleArity})", tree.pos)
- unitLiteral
- }
- else if (arity == 1) ts.head
- else if (ctx.mode is Mode.Type) AppliedTypeTree(ref(tupleTypeRef), ts)
- else if (arity == 0) unitLiteral
- else Apply(ref(tupleTypeRef.classSymbol.companionModule.valRef), ts)
- }
+ val arity = ts.length
+ def tupleTypeRef = defn.TupleType(arity)
+ if (arity > Definitions.MaxTupleArity) {
+ ctx.error(s"tuple too long (max allowed: ${Definitions.MaxTupleArity})", tree.pos)
+ unitLiteral
+ } else if (arity == 1) ts.head
+ else if (ctx.mode is Mode.Type) AppliedTypeTree(ref(tupleTypeRef), ts)
+ else if (arity == 0) unitLiteral
+ else Apply(ref(tupleTypeRef.classSymbol.companionModule.valRef), ts)
case WhileDo(cond, body) =>
// { <label> def while$(): Unit = if (cond) { body; while$() } ; while$() }
val call = Apply(Ident(nme.WHILE_PREFIX), Nil)
@@ -947,7 +944,7 @@ object desugar {
makeFor(nme.map, nme.flatMap, enums, body) orElse tree
case PatDef(mods, pats, tpt, rhs) =>
val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
- flatTree(pats1 map (makePatDef(mods, _, rhs)))
+ flatTree(pats1 map (makePatDef(tree, mods, _, rhs)))
case ParsedTry(body, handler, finalizer) =>
handler match {
case Match(EmptyTree, cases) => Try(body, cases, finalizer)
@@ -1037,9 +1034,6 @@ object desugar {
add(id, TypeTree())
case Apply(_, args) =>
args foreach collect
- case Pair(left, right) =>
- collect(left)
- collect(right)
case Typed(expr, _) =>
collect(expr)
case NamedArg(_, arg) =>
@@ -1049,10 +1043,10 @@ object desugar {
case Alternative(trees) =>
for (tree <- trees; (vble, _) <- getVariables(tree))
ctx.error("illegal variable in pattern alternative", vble.pos)
- case Annotated(annot, arg) =>
+ case Annotated(arg, _) =>
collect(arg)
- case InterpolatedString(_, _, elems) =>
- elems foreach collect
+ case InterpolatedString(_, segments) =>
+ segments foreach collect
case InfixOp(left, _, right) =>
collect(left)
collect(right)
diff --git a/src/dotty/tools/dotc/ast/NavigateAST.scala b/src/dotty/tools/dotc/ast/NavigateAST.scala
index 2b11f81f3..33aa87d8e 100644
--- a/src/dotty/tools/dotc/ast/NavigateAST.scala
+++ b/src/dotty/tools/dotc/ast/NavigateAST.scala
@@ -19,10 +19,9 @@ object NavigateAST {
case _ =>
val loosePath = untypedPath(tree, exactMatch = false)
throw new
- Error(i"""no untyped tree for $tree, pos = ${tree.pos}, envelope = ${tree.envelope}
+ Error(i"""no untyped tree for $tree, pos = ${tree.pos}
|best matching path =\n$loosePath%\n====\n%
- |path positions = ${loosePath.map(_.pos)}
- |path envelopes = ${loosePath.map(_.envelope)}""")
+ |path positions = ${loosePath.map(_.pos)}""")
}
/** The reverse path of untyped trees starting with a tree that closest matches
@@ -40,7 +39,7 @@ object NavigateAST {
def untypedPath(tree: tpd.Tree, exactMatch: Boolean = false)(implicit ctx: Context): List[Positioned] =
tree match {
case tree: MemberDef[_] =>
- untypedPath(tree.envelope) match {
+ untypedPath(tree.pos) match {
case path @ (last: DefTree[_]) :: _ => path
case path if !exactMatch => path
case _ => Nil
@@ -76,7 +75,7 @@ object NavigateAST {
path
}
def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] =
- if (p.envelope contains pos) childPath(p.productIterator, p :: path)
+ if (p.pos contains pos) childPath(p.productIterator, p :: path)
else path
singlePath(from, Nil)
}
diff --git a/src/dotty/tools/dotc/ast/Positioned.scala b/src/dotty/tools/dotc/ast/Positioned.scala
index e7f5de591..8d364d439 100644
--- a/src/dotty/tools/dotc/ast/Positioned.scala
+++ b/src/dotty/tools/dotc/ast/Positioned.scala
@@ -3,6 +3,10 @@ package ast
import util.Positions._
import util.DotClass
+import core.Contexts.Context
+import core.Decorators._
+import core.Flags.JavaDefined
+import core.StdNames.nme
/** A base class for things that have positions (currently: modifiers and trees)
*/
@@ -16,7 +20,7 @@ abstract class Positioned extends DotClass with Product {
*/
def pos: Position = curPos
- /** Destructively update `curPos` to given position. Also, set any missing
+ /** Destructively update `curPos` to given position. Also, set any missing
* positions in children.
*/
protected def setPos(pos: Position): Unit = {
@@ -24,11 +28,6 @@ abstract class Positioned extends DotClass with Product {
if (pos.exists) setChildPositions(pos.toSynthetic)
}
- /** The envelope containing the item in its entirety. Envelope is different from
- * `pos` for definitions (instances of MemberDef).
- */
- def envelope: Position = pos.toSynthetic
-
/** A positioned item like this one with the position set to `pos`.
* if the positioned item is source-derived, a clone is returned.
* If the positioned item is synthetic, the position is updated
@@ -106,8 +105,7 @@ abstract class Positioned extends DotClass with Product {
}
}
- /** The initial, synthetic position. This is usually the union of all positioned children's
- * envelopes.
+ /** The initial, synthetic position. This is usually the union of all positioned children's positions.
*/
protected def initialPos: Position = {
var n = productArity
@@ -115,7 +113,7 @@ abstract class Positioned extends DotClass with Product {
while (n > 0) {
n -= 1
productElement(n) match {
- case p: Positioned => pos = pos union p.envelope
+ case p: Positioned => pos = pos union p.pos
case xs: List[_] => pos = unionPos(pos, xs)
case _ =>
}
@@ -124,7 +122,7 @@ abstract class Positioned extends DotClass with Product {
}
private def unionPos(pos: Position, xs: List[_]): Position = xs match {
- case (p: Positioned) :: xs1 => unionPos(pos union p.envelope, xs1)
+ case (p: Positioned) :: xs1 => unionPos(pos union p.pos, xs1)
case _ => pos
}
@@ -138,7 +136,7 @@ abstract class Positioned extends DotClass with Product {
false
}
(this eq that) ||
- (this.envelope contains that.pos) && {
+ (this.pos contains that.pos) && {
var n = productArity
var found = false
while (n > 0 && !found) {
@@ -148,4 +146,68 @@ abstract class Positioned extends DotClass with Product {
found
}
}
+
+ /** Check that all positioned items in this tree satisfy the following conditions:
+ * - Parent positions contain child positions
+ * - If item is a non-empty tree, it has a position
+ */
+ def checkPos(nonOverlapping: Boolean)(implicit ctx: Context): Unit = try {
+ import untpd._
+ var lastPositioned: Positioned = null
+ var lastPos = NoPosition
+ def check(p: Any): Unit = p match {
+ case p: Positioned =>
+ assert(pos contains p.pos,
+ s"""position error, parent position does not contain child positon
+ |parent = $this,
+ |parent position = $pos,
+ |child = $p,
+ |child position = ${p.pos}""".stripMargin)
+ p match {
+ case tree: Tree if !tree.isEmpty =>
+ assert(tree.pos.exists,
+ s"position error: position not set for $tree # ${tree.uniqueId}")
+ case _ =>
+ }
+ if (nonOverlapping) {
+ this match {
+ case _: WildcardFunction
+ if lastPositioned.isInstanceOf[ValDef] && !p.isInstanceOf[ValDef] =>
+ // ignore transition from last wildcard parameter to body
+ case _ =>
+ assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start,
+ s"""position error, child positions overlap or in wrong order
+ |parent = $this
+ |1st child = $lastPositioned
+ |1st child position = $lastPos
+ |2nd child = $p
+ |2nd child position = ${p.pos}""".stripMargin)
+ }
+ lastPositioned = p
+ lastPos = p.pos
+ }
+ p.checkPos(nonOverlapping)
+ case xs: List[_] =>
+ xs.foreach(check)
+ case _ =>
+ }
+ this match {
+ case tree: DefDef if tree.name == nme.CONSTRUCTOR && tree.mods.is(JavaDefined) =>
+ // Special treatment for constructors coming from Java:
+ // Leave out tparams, they are copied with wrong positions from parent class
+ check(tree.mods)
+ check(tree.vparamss)
+ case _ =>
+ val end = productArity
+ var n = 0
+ while (n < end) {
+ check(productElement(n))
+ n += 1
+ }
+ }
+ } catch {
+ case ex: AssertionError =>
+ println(i"error while checking $this")
+ throw ex
+ }
}
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index a48651ebf..725838ef6 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -182,8 +182,8 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
case OrTypeTree(tpt1, tpt2) => mayBeTypePat(tpt1) || mayBeTypePat(tpt2)
case RefinedTypeTree(tpt, refinements) => mayBeTypePat(tpt) || refinements.exists(_.isInstanceOf[Bind])
case AppliedTypeTree(tpt, args) => mayBeTypePat(tpt) || args.exists(_.isInstanceOf[Bind])
- case SelectFromTypeTree(tpt, _) => mayBeTypePat(tpt)
- case Annotated(_, tpt) => mayBeTypePat(tpt)
+ case Select(tpt, _) => mayBeTypePat(tpt)
+ case Annotated(tpt, _) => mayBeTypePat(tpt)
case _ => false
}
@@ -249,17 +249,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
/** Is this case guarded? */
def isGuardedCase(cdef: CaseDef) = cdef.guard ne EmptyTree
- /** True iff definition is a val or def with no right-hand-side, or it
- * is an abstract typoe declaration
- */
- def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match {
- case mdef: ValOrDefDef =>
- mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor)
- case mdef: TypeDef =>
- mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree]
- case _ => false
- }
-
/** The underlying pattern ignoring any bindings */
def unbind(x: Tree): Tree = unsplice(x) match {
case Bind(_, y) => unbind(y)
@@ -279,9 +268,21 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] =>
import TreeInfo._
+ import untpd._
+
+ /** True iff definition is a val or def with no right-hand-side, or it
+ * is an abstract typoe declaration
+ */
+ def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match {
+ case mdef: ValOrDefDef =>
+ mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor)
+ case mdef: TypeDef =>
+ mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree]
+ case _ => false
+ }
def isFunctionWithUnknownParamType(tree: Tree) = tree match {
- case untpd.Function(args, _) =>
+ case Function(args, _) =>
args.exists {
case ValDef(_, tpt, _) => tpt.isEmpty
case _ => false
@@ -307,7 +308,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
| DefDef(_, _, _, _, _) =>
Pure
case vdef @ ValDef(_, _, _) =>
- if (vdef.mods is Mutable) Impure else exprPurity(vdef.rhs)
+ if (vdef.symbol.flags is Mutable) Impure else exprPurity(vdef.rhs)
case _ =>
Impure
}
@@ -480,7 +481,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
require(sym.pos.exists)
object accum extends TreeAccumulator[List[Tree]] {
def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = {
- if (tree.envelope.contains(sym.pos))
+ if (tree.pos.contains(sym.pos))
if (definedSym(tree) == sym) tree :: x
else {
val x1 = foldOver(x, tree)
@@ -630,20 +631,6 @@ object TreeInfo {
}
}
- def isApplyDynamicName(name: Name) = (name == nme.updateDynamic) || (name == nme.selectDynamic) || (name == nme.applyDynamic) || (name == nme.applyDynamicNamed)
-
- class DynamicApplicationExtractor(nameTest: Name => Boolean) {
- def unapply(tree: Tree) = tree match {
- case Apply(TypeApply(Select(qual, oper), _), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
- case Apply(Select(qual, oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
- case Apply(Ident(oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((EmptyTree(), name))
- case _ => None
- }
- }
- object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic)
- object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName)
- object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed)
-
object MacroImplReference {
private def refPart(tree: Tree): Tree = tree match {
case TypeApply(fun, _) => refPart(fun)
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index cf11c27fa..bb6fbd5ba 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -33,51 +33,7 @@ object Trees {
/** Attachment key for trees with documentation strings attached */
val DocComment = new Attachment.Key[Comment]
- /** Modifiers and annotations for definitions
- * @param flags The set flags
- * @param privateWithin If a private or protected has is followed by a
- * qualifier [q], the name q, "" as a typename otherwise.
- * @param annotations The annotations preceding the modifiers
- */
- case class Modifiers[-T >: Untyped] (
- flags: FlagSet = EmptyFlags,
- privateWithin: TypeName = tpnme.EMPTY,
- annotations: List[Tree[T]] = Nil) extends Positioned with Cloneable {
-
- def is(fs: FlagSet): Boolean = flags is fs
- def is(fc: FlagConjunction): Boolean = flags is fc
-
- def | (fs: FlagSet): Modifiers[T] = withFlags(flags | fs)
- def & (fs: FlagSet): Modifiers[T] = withFlags(flags & fs)
- def &~(fs: FlagSet): Modifiers[T] = withFlags(flags &~ fs)
-
- def toTypeFlags: Modifiers[T] = withFlags(flags.toTypeFlags)
- def toTermFlags: Modifiers[T] = withFlags(flags.toTermFlags)
-
- def withFlags(flags: FlagSet) =
- if (this.flags == flags) this
- else copy(flags = flags)
-
- def withAddedAnnotation[U >: Untyped <: T](annot: Tree[U]): Modifiers[U] =
- if (annotations.exists(_ eq annot)) this
- else withAnnotations(annotations :+ annot)
-
- def withAnnotations[U >: Untyped <: T](annots: List[Tree[U]]): Modifiers[U] =
- if (annots eq annotations) this
- else copy(annotations = annots)
-
- def withPrivateWithin(pw: TypeName) =
- if (pw.isEmpty) this
- else copy(privateWithin = pw)
-
- def hasFlags = flags != EmptyFlags
- def hasAnnotations = annotations.nonEmpty
- def hasPrivateWithin = privateWithin != tpnme.EMPTY
-
- def tokenPos: Seq[(Token, Position)] = ???
- }
-
- @sharable private var nextId = 0 // for debugging
+ @sharable private var nextId = 0 // for debugging
type LazyTree = AnyRef /* really: Tree | Lazy[Tree] */
type LazyTreeList = AnyRef /* really: List[Tree] | Lazy[List[Tree]] */
@@ -320,29 +276,41 @@ object Trees {
abstract class MemberDef[-T >: Untyped] extends NameTree[T] with DefTree[T] {
type ThisTree[-T >: Untyped] <: MemberDef[T]
- private[this] var myMods: Modifiers[T] = null
+ private[this] var myMods: untpd.Modifiers = null
- private[ast] def rawMods: Modifiers[T] =
- if (myMods == null) genericEmptyModifiers else myMods
+ private[dotc] def rawMods: untpd.Modifiers =
+ if (myMods == null) untpd.EmptyModifiers else myMods
def rawComment: Option[Comment] = getAttachment(DocComment)
- def withMods(mods: Modifiers[Untyped]): ThisTree[Untyped] = {
+ def withMods(mods: untpd.Modifiers): ThisTree[Untyped] = {
val tree = if (myMods == null || (myMods == mods)) this else clone.asInstanceOf[MemberDef[Untyped]]
tree.setMods(mods)
tree.asInstanceOf[ThisTree[Untyped]]
}
- def withFlags(flags: FlagSet): ThisTree[Untyped] = withMods(Modifiers(flags))
+ def withFlags(flags: FlagSet): ThisTree[Untyped] = withMods(untpd.Modifiers(flags))
def setComment(comment: Option[Comment]): ThisTree[Untyped] = {
comment.map(putAttachment(DocComment, _))
asInstanceOf[ThisTree[Untyped]]
}
- protected def setMods(mods: Modifiers[T @uncheckedVariance]) = myMods = mods
+ protected def setMods(mods: untpd.Modifiers) = myMods = mods
+
+ /** The position of the name defined by this definition.
+ * This is a point position if the definition is synthetic, or a range position
+ * if the definition comes from source.
+ * It might also be that the definition does not have a position (for instance when synthesized by
+ * a calling chain from `viewExists`), in that case the return position is NoPosition.
+ */
+ def namePos =
+ if (pos.exists)
+ if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
+ else Position(pos.point, pos.point + name.length, pos.point)
+ else pos
+
- override def envelope: Position = rawMods.pos.union(pos).union(initialPos)
}
/** A ValDef or DefDef tree */
@@ -366,7 +334,7 @@ object Trees {
override def toString = s"BackquotedIdent($name)"
}
- /** qualifier.name */
+ /** qualifier.name, or qualifier#name, if qualifier is a type */
case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)
extends RefTree[T] {
type ThisTree[-T >: Untyped] = Select[T]
@@ -430,15 +398,6 @@ object Trees {
type ThisTree[-T >: Untyped] = New[T]
}
- /** (left, right) */
- case class Pair[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])
- extends TermTree[T] {
- type ThisTree[-T >: Untyped] = Pair[T]
- override def isTerm = left.isTerm && right.isTerm
- override def isType = left.isType && right.isType
- override def isPattern = !isTerm && (left.isPattern || left.isTerm) && (right.isPattern || right.isTerm)
- }
-
/** expr : tpt */
case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])
extends ProxyTree[T] with TermTree[T] {
@@ -560,15 +519,6 @@ object Trees {
type ThisTree[-T >: Untyped] = SingletonTypeTree[T]
}
- /** qualifier # name
- * In Scala, this always refers to a type, but in a Java
- * compilation unit this might refer to a term.
- */
- case class SelectFromTypeTree[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)
- extends RefTree[T] {
- type ThisTree[-T >: Untyped] = SelectFromTypeTree[T]
- }
-
/** left & right */
case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])
extends TypTree[T] {
@@ -619,7 +569,6 @@ object Trees {
type ThisTree[-T >: Untyped] = Bind[T]
override def isType = name.isTypeName
override def isTerm = name.isTermName
- override def envelope: Position = pos union initialPos
}
/** tree_1 | ... | tree_n */
@@ -697,7 +646,7 @@ object Trees {
/** import expr.selectors
* where a selector is either an untyped `Ident`, `name` or
- * an untyped `Pair` `name => rename`
+ * an untyped thicket consisting of `name` and `rename`.
*/
case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])
extends DenotingTree[T] {
@@ -712,7 +661,7 @@ object Trees {
}
/** arg @annot */
- case class Annotated[-T >: Untyped] private[ast] (annot: Tree[T], arg: Tree[T])
+ case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])
extends ProxyTree[T] {
type ThisTree[-T >: Untyped] = Annotated[T]
def forwardTo = arg
@@ -740,6 +689,7 @@ object Trees {
val newTrees = trees.map(_.withPos(pos))
new Thicket[T](newTrees).asInstanceOf[this.type]
}
+ override def pos = (NoPosition /: trees) ((pos, t) => pos union t.pos)
override def foreachInThicket(op: Tree[T] => Unit): Unit =
trees foreach (_.foreachInThicket(op))
}
@@ -747,16 +697,14 @@ object Trees {
class EmptyValDef[T >: Untyped] extends ValDef[T](
nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T]) with WithoutTypeOrPos[T] {
override def isEmpty: Boolean = true
- setMods(Modifiers[T](PrivateLocal))
+ setMods(untpd.Modifiers(PrivateLocal))
}
@sharable val theEmptyTree: Thicket[Type] = Thicket(Nil)
@sharable val theEmptyValDef = new EmptyValDef[Type]
- @sharable val theEmptyModifiers = new Modifiers()
def genericEmptyValDef[T >: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]]
def genericEmptyTree[T >: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]]
- def genericEmptyModifiers[T >: Untyped]: Modifiers[T] = theEmptyModifiers.asInstanceOf[Modifiers[T]]
def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = {
var buf: ListBuffer[Tree[T]] = null
@@ -815,7 +763,6 @@ object Trees {
abstract class Instance[T >: Untyped <: Type] extends DotClass { inst =>
- type Modifiers = Trees.Modifiers[T]
type Tree = Trees.Tree[T]
type TypTree = Trees.TypTree[T]
type TermTree = Trees.TermTree[T]
@@ -838,7 +785,6 @@ object Trees {
type TypeApply = Trees.TypeApply[T]
type Literal = Trees.Literal[T]
type New = Trees.New[T]
- type Pair = Trees.Pair[T]
type Typed = Trees.Typed[T]
type NamedArg = Trees.NamedArg[T]
type Assign = Trees.Assign[T]
@@ -853,7 +799,6 @@ object Trees {
type JavaSeqLiteral = Trees.JavaSeqLiteral[T]
type TypeTree = Trees.TypeTree[T]
type SingletonTypeTree = Trees.SingletonTypeTree[T]
- type SelectFromTypeTree = Trees.SelectFromTypeTree[T]
type AndTypeTree = Trees.AndTypeTree[T]
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
@@ -875,14 +820,9 @@ object Trees {
@sharable val EmptyTree: Thicket = genericEmptyTree
@sharable val EmptyValDef: ValDef = genericEmptyValDef
- @sharable val EmptyModifiers: Modifiers = genericEmptyModifiers
// ----- Auxiliary creation methods ------------------
- def Modifiers(flags: FlagSet = EmptyFlags,
- privateWithin: TypeName = tpnme.EMPTY,
- annotations: List[Tree] = Nil) = new Modifiers(flags, privateWithin, annotations)
-
def Thicket(trees: List[Tree]): Thicket = new Thicket(trees)
def Thicket(): Thicket = EmptyTree
def Thicket(x1: Tree, x2: Tree): Thicket = Thicket(x1 :: x2 :: Nil)
@@ -892,11 +832,6 @@ object Trees {
case ys => Thicket(ys)
}
- // ----- Accessing modifiers ----------------------------------------------------
-
- abstract class ModsDeco { def mods: Modifiers }
- implicit def modsDeco(mdef: MemberDef)(implicit ctx: Context): ModsDeco
-
// ----- Helper classes for copying, transforming, accumulating -----------------
val cpy: TreeCopier
@@ -957,10 +892,6 @@ object Trees {
case tree: New if tpt eq tree.tpt => tree
case _ => finalize(tree, untpd.New(tpt))
}
- def Pair(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): Pair = tree match {
- case tree: Pair if (left eq tree.left) && (right eq tree.right) => tree
- case _ => finalize(tree, untpd.Pair(left, right))
- }
def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match {
case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree
case _ => finalize(tree, untpd.Typed(expr, tpt))
@@ -1016,10 +947,6 @@ object Trees {
case tree: SingletonTypeTree if ref eq tree.ref => tree
case _ => finalize(tree, untpd.SingletonTypeTree(ref))
}
- def SelectFromTypeTree(tree: Tree)(qualifier: Tree, name: Name): SelectFromTypeTree = tree match {
- case tree: SelectFromTypeTree if (qualifier eq tree.qualifier) && (name == tree.name) => tree
- case _ => finalize(tree, untpd.SelectFromTypeTree(qualifier, name))
- }
def AndTypeTree(tree: Tree)(left: Tree, right: Tree): AndTypeTree = tree match {
case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree
case _ => finalize(tree, untpd.AndTypeTree(left, right))
@@ -1084,9 +1011,9 @@ object Trees {
case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree
case _ => finalize(tree, untpd.PackageDef(pid, stats))
}
- def Annotated(tree: Tree)(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated = tree match {
- case tree: Annotated if (annot eq tree.annot) && (arg eq tree.arg) => tree
- case _ => finalize(tree, untpd.Annotated(annot, arg))
+ def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = tree match {
+ case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree
+ case _ => finalize(tree, untpd.Annotated(arg, annot))
}
def Thicket(tree: Tree)(trees: List[Tree]): Thicket = tree match {
case tree: Thicket if trees eq tree.trees => tree
@@ -1134,8 +1061,6 @@ object Trees {
tree
case New(tpt) =>
cpy.New(tree)(transform(tpt))
- case Pair(left, right) =>
- cpy.Pair(tree)(transform(left), transform(right))
case Typed(expr, tpt) =>
cpy.Typed(tree)(transform(expr), transform(tpt))
case NamedArg(name, arg) =>
@@ -1162,8 +1087,6 @@ object Trees {
tree
case SingletonTypeTree(ref) =>
cpy.SingletonTypeTree(tree)(transform(ref))
- case SelectFromTypeTree(qualifier, name) =>
- cpy.SelectFromTypeTree(tree)(transform(qualifier), name)
case AndTypeTree(left, right) =>
cpy.AndTypeTree(tree)(transform(left), transform(right))
case OrTypeTree(left, right) =>
@@ -1200,8 +1123,8 @@ object Trees {
cpy.Import(tree)(transform(expr), selectors)
case PackageDef(pid, stats) =>
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
- case Annotated(annot, arg) =>
- cpy.Annotated(tree)(transform(annot), transform(arg))
+ case Annotated(arg, annot) =>
+ cpy.Annotated(tree)(transform(arg), transform(annot))
case Thicket(trees) =>
val trees1 = transform(trees)
if (trees1 eq trees) tree else Thicket(trees1)
@@ -1240,8 +1163,6 @@ object Trees {
x
case New(tpt) =>
this(x, tpt)
- case Pair(left, right) =>
- this(this(x, left), right)
case Typed(expr, tpt) =>
this(this(x, expr), tpt)
case NamedArg(name, arg) =>
@@ -1268,8 +1189,6 @@ object Trees {
x
case SingletonTypeTree(ref) =>
this(x, ref)
- case SelectFromTypeTree(qualifier, name) =>
- this(x, qualifier)
case AndTypeTree(left, right) =>
this(this(x, left), right)
case OrTypeTree(left, right) =>
@@ -1306,8 +1225,8 @@ object Trees {
this(x, expr)
case PackageDef(pid, stats) =>
this(this(x, pid), stats)(localCtx)
- case Annotated(annot, arg) =>
- this(this(x, annot), arg)
+ case Annotated(arg, annot) =>
+ this(this(x, arg), annot)
case Thicket(ts) =>
this(x, ts)
}
@@ -1345,7 +1264,6 @@ object Trees {
case tree: DefDef => cpy.DefDef(tree)(name = newName.asTermName)
case tree: untpd.PolyTypeDef => untpd.cpy.PolyTypeDef(tree)(newName.asTypeName, tree.tparams, tree.rhs).withMods(tree.rawMods)
case tree: TypeDef => cpy.TypeDef(tree)(name = newName.asTypeName)
- case tree: SelectFromTypeTree => cpy.SelectFromTypeTree(tree)(tree.qualifier, newName)
}
}.asInstanceOf[tree.ThisTree[T]]
}
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 2b0e63a19..f59bb7a47 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -9,7 +9,6 @@ import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Symbols._
import Denotations._, Decorators._, DenotTransformers._
-import config.Printers._
import collection.mutable
import typer.ErrorReporting._
@@ -20,22 +19,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
private def ta(implicit ctx: Context) = ctx.typeAssigner
- def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Modifiers(
- sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags),
- if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
- sym.annotations map (_.tree))
-
def Ident(tp: NamedType)(implicit ctx: Context): Ident =
ta.assignType(untpd.Ident(tp.name), tp)
def Select(qualifier: Tree, name: Name)(implicit ctx: Context): Select =
ta.assignType(untpd.Select(qualifier, name), qualifier)
- def SelectFromTypeTree(qualifier: Tree, name: Name)(implicit ctx: Context): SelectFromTypeTree =
- ta.assignType(untpd.SelectFromTypeTree(qualifier, name), qualifier)
-
- def SelectFromTypeTree(qualifier: Tree, tp: NamedType)(implicit ctx: Context): SelectFromTypeTree =
- untpd.SelectFromTypeTree(qualifier, tp.name).withType(tp)
+ def Select(qualifier: Tree, tp: NamedType)(implicit ctx: Context): Select =
+ untpd.Select(qualifier, tp.name).withType(tp)
def This(cls: ClassSymbol)(implicit ctx: Context): This =
untpd.This(cls.name).withType(cls.thisType)
@@ -60,9 +51,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def New(tp: Type)(implicit ctx: Context): New = New(TypeTree(tp))
- def Pair(left: Tree, right: Tree)(implicit ctx: Context): Pair =
- ta.assignType(untpd.Pair(left, right), left, right)
-
def Typed(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed =
ta.assignType(untpd.Typed(expr, tpt), tpt)
@@ -293,8 +281,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
ta.assignType(untpd.PackageDef(pid, stats), pid)
- def Annotated(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated =
- ta.assignType(untpd.Annotated(annot, arg), annot, arg)
+ def Annotated(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated =
+ ta.assignType(untpd.Annotated(arg, annot), arg, annot)
def Throw(expr: Tree)(implicit ctx: Context): Tree =
ref(defn.throwMethod).appliedTo(expr)
@@ -337,7 +325,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Ident(tp)
else tp.prefix match {
case pre: SingletonType => followOuterLinks(singleton(pre)).select(tp)
- case pre => SelectFromTypeTree(TypeTree(pre), tp)
+ case pre => Select(TypeTree(pre), tp)
} // no checks necessary
def ref(sym: Symbol)(implicit ctx: Context): Tree =
@@ -453,10 +441,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
} else foldOver(sym, tree)
}
- implicit class modsDeco(mdef: MemberDef)(implicit ctx: Context) extends ModsDeco {
- def mods = if (mdef.hasType) Modifiers(mdef.symbol) else mdef.rawMods
- }
-
override val cpy = new TypedTreeCopier
class TypedTreeCopier extends TreeCopier {
@@ -494,14 +478,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
override def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New =
ta.assignType(untpd.cpy.New(tree)(tpt), tpt)
- override def Pair(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): Pair = {
- val tree1 = untpd.cpy.Pair(tree)(left, right)
- tree match {
- case tree: Pair if (left.tpe eq tree.left.tpe) && (right.tpe eq tree.right.tpe) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, left, right)
- }
- }
-
override def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed =
ta.assignType(untpd.cpy.Typed(tree)(expr, tpt), tpt)
@@ -569,11 +545,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}
- override def Annotated(tree: Tree)(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated = {
- val tree1 = untpd.cpy.Annotated(tree)(annot, arg)
+ override def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = {
+ val tree1 = untpd.cpy.Annotated(tree)(arg, annot)
tree match {
case tree: Annotated if (arg.tpe eq tree.arg.tpe) && (annot eq tree.annot) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, annot, arg)
+ case _ => ta.assignType(tree1, arg, annot)
}
}
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index cef78c6e6..61c3a79a4 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -35,11 +35,24 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree
case class SymbolLit(str: String) extends TermTree
- case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends TermTree
+
+ /** An interpolated string
+ * @param segments a list of two element tickets consisting of string literal and argument tree,
+ * possibly with a simple string literal as last element of the list
+ */
+ case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree
+
case class Function(args: List[Tree], body: Tree) extends Tree {
override def isTerm = body.isTerm
override def isType = body.isType
}
+ /** A function created from a wildcard expression
+ * @param placeHolderParams a list of definitions of synthetic parameters
+ * @param body the function body where wildcards are replaced by
+ * references to synthetic parameters.
+ */
+ class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body)
+
case class InfixOp(left: Tree, op: Name, right: Tree) extends OpTree
case class PostfixOp(od: Tree, op: Name) extends OpTree
case class PrefixOp(op: Name, od: Tree) extends OpTree
@@ -63,6 +76,62 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
class PolyTypeDef(name: TypeName, override val tparams: List[TypeDef], rhs: Tree)
extends TypeDef(name, rhs)
+ /** A block arising from a right-associative infix operation, where, e.g.
+ *
+ * a +: b
+ *
+ * is expanded to
+ *
+ * { val x = a; b.+:(x) }
+ */
+ class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp)
+
+ // ----- Modifiers -----------------------------------------------------
+
+ /** Modifiers and annotations for definitions
+ * @param flags The set flags
+ * @param privateWithin If a private or protected has is followed by a
+ * qualifier [q], the name q, "" as a typename otherwise.
+ * @param annotations The annotations preceding the modifiers
+ */
+ case class Modifiers (
+ flags: FlagSet = EmptyFlags,
+ privateWithin: TypeName = tpnme.EMPTY,
+ annotations: List[Tree] = Nil) extends Positioned with Cloneable {
+
+ def is(fs: FlagSet): Boolean = flags is fs
+ def is(fc: FlagConjunction): Boolean = flags is fc
+
+ def | (fs: FlagSet): Modifiers = withFlags(flags | fs)
+ def & (fs: FlagSet): Modifiers = withFlags(flags & fs)
+ def &~(fs: FlagSet): Modifiers = withFlags(flags &~ fs)
+
+ def toTypeFlags: Modifiers = withFlags(flags.toTypeFlags)
+ def toTermFlags: Modifiers = withFlags(flags.toTermFlags)
+
+ def withFlags(flags: FlagSet) =
+ if (this.flags == flags) this
+ else copy(flags = flags)
+
+ def withAddedAnnotation(annot: Tree): Modifiers =
+ if (annotations.exists(_ eq annot)) this
+ else withAnnotations(annotations :+ annot)
+
+ def withAnnotations(annots: List[Tree]): Modifiers =
+ if (annots eq annotations) this
+ else copy(annotations = annots)
+
+ def withPrivateWithin(pw: TypeName) =
+ if (pw.isEmpty) this
+ else copy(privateWithin = pw)
+
+ def hasFlags = flags != EmptyFlags
+ def hasAnnotations = annotations.nonEmpty
+ def hasPrivateWithin = privateWithin != tpnme.EMPTY
+ }
+
+ @sharable val EmptyModifiers: Modifiers = new Modifiers()
+
// ----- TypeTrees that refer to other tree's symbols -------------------
/** A type tree that gets its type from some other tree's symbol. Enters the
@@ -116,7 +185,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def TypeApply(fun: Tree, args: List[Tree]): TypeApply = new TypeApply(fun, args)
def Literal(const: Constant): Literal = new Literal(const)
def New(tpt: Tree): New = new New(tpt)
- def Pair(left: Tree, right: Tree): Pair = new Pair(left, right)
def Typed(expr: Tree, tpt: Tree): Typed = new Typed(expr, tpt)
def NamedArg(name: Name, arg: Tree): NamedArg = new NamedArg(name, arg)
def Assign(lhs: Tree, rhs: Tree): Assign = new Assign(lhs, rhs)
@@ -132,7 +200,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def TypeTree(original: Tree): TypeTree = new TypeTree(original)
def TypeTree() = new TypeTree(EmptyTree)
def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref)
- def SelectFromTypeTree(qualifier: Tree, name: Name): SelectFromTypeTree = new SelectFromTypeTree(qualifier, name)
def AndTypeTree(left: Tree, right: Tree): AndTypeTree = new AndTypeTree(left, right)
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
@@ -149,7 +216,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList): Template = new Template(constr, parents, self, body)
def Import(expr: Tree, selectors: List[untpd.Tree]): Import = new Import(expr, selectors)
def PackageDef(pid: RefTree, stats: List[Tree]): PackageDef = new PackageDef(pid, stats)
- def Annotated(annot: Tree, arg: Tree): Annotated = new Annotated(annot, arg)
+ def Annotated(arg: Tree, annot: Tree): Annotated = new Annotated(arg, annot)
// ------ Additional creation methods for untyped only -----------------
@@ -243,22 +310,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
/** A repeated argument such as `arg: _*` */
def repeated(arg: Tree)(implicit ctx: Context) = Typed(arg, Ident(tpnme.WILDCARD_STAR))
-// ------- Decorators -------------------------------------------------
+// ----- Accessing modifiers ----------------------------------------------------
- implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal {
- def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = {
- def encloses(elem: Any) = elem match {
- case t: Tree => t.envelope contains pos
- case _ => false
- }
- base.productIterator find encloses match {
- case Some(tree: Tree) => locateEnclosing(tree :: base, pos)
- case none => base
- }
- }
- }
+ abstract class ModsDecorator { def mods: Modifiers }
- implicit class modsDeco(val mdef: MemberDef)(implicit ctx: Context) extends ModsDeco {
+ implicit class modsDeco(val mdef: MemberDef)(implicit ctx: Context) {
def mods = mdef.rawMods
}
@@ -295,9 +351,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case tree: SymbolLit if str == tree.str => tree
case _ => untpd.SymbolLit(str).withPos(tree.pos)
}
- def InterpolatedString(tree: Tree)(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match {
- case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree
- case _ => untpd.InterpolatedString(id, strings, elems).withPos(tree.pos)
+ def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree]) = tree match {
+ case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree
+ case _ => untpd.InterpolatedString(id, segments).withPos(tree.pos)
}
def Function(tree: Tree)(args: List[Tree], body: Tree) = tree match {
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
@@ -369,8 +425,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
cpy.ParsedTry(tree)(transform(expr), transform(handler), transform(finalizer))
case SymbolLit(str) =>
cpy.SymbolLit(tree)(str)
- case InterpolatedString(id, strings, elems) =>
- cpy.InterpolatedString(tree)(id, transformSub(strings), transform(elems))
+ case InterpolatedString(id, segments) =>
+ cpy.InterpolatedString(tree)(id, transform(segments))
case Function(args, body) =>
cpy.Function(tree)(transform(args), transform(body))
case InfixOp(left, op, right) =>
@@ -416,8 +472,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
this(this(this(x, expr), handler), finalizer)
case SymbolLit(str) =>
x
- case InterpolatedString(id, strings, elems) =>
- this(this(x, strings), elems)
+ case InterpolatedString(id, segments) =>
+ this(x, segments)
case Function(args, body) =>
this(this(x, args), body)
case InfixOp(left, op, right) =>
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index 0949d7fee..c188bfab4 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -63,6 +63,9 @@ object Config {
*/
final val checkNoDoubleBindings = true
+ /** Check positions for consistency after parsing */
+ final val checkPositions = true
+
/** Show subtype traces for all deep subtype recursions */
final val traceDeepSubTypeRecursions = false
diff --git a/src/dotty/tools/dotc/config/Printers.scala b/src/dotty/tools/dotc/config/Printers.scala
index fa36ad12c..322bc82d9 100644
--- a/src/dotty/tools/dotc/config/Printers.scala
+++ b/src/dotty/tools/dotc/config/Printers.scala
@@ -4,12 +4,10 @@ object Printers {
class Printer {
def println(msg: => String): Unit = System.out.println(msg)
- def echo[T](msg: => String, value: T): T = { println(msg + value); value }
}
object noPrinter extends Printer {
override def println(msg: => String): Unit = ()
- override def echo[T](msg: => String, value: T): T = value
}
val default: Printer = new Printer
diff --git a/src/dotty/tools/dotc/core/CheckRealizable.scala b/src/dotty/tools/dotc/core/CheckRealizable.scala
index 11fd6786a..78ec685fc 100644
--- a/src/dotty/tools/dotc/core/CheckRealizable.scala
+++ b/src/dotty/tools/dotc/core/CheckRealizable.scala
@@ -4,7 +4,6 @@ package core
import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._
import SymDenotations._, Denotations.SingleDenotation
-import config.Printers._
import util.Positions._
import Decorators._
import StdNames._
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
index 99b4af0a9..91e70b7b5 100644
--- a/src/dotty/tools/dotc/core/Constraint.scala
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -8,7 +8,7 @@ import collection.mutable
import printing.{Printer, Showable}
import printing.Texts._
import config.Config
-import config.Printers._
+import config.Printers.constr
/** Constraint over undetermined type parameters. Constraints are built
* over values of the following types:
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 18e47a7f2..5911af72c 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -5,7 +5,7 @@ package core
import Types._, Contexts._, Symbols._
import Decorators._
import config.Config
-import config.Printers._
+import config.Printers.{constr, typr}
import TypeApplications.EtaExpansion
import collection.mutable
diff --git a/src/dotty/tools/dotc/core/ConstraintRunInfo.scala b/src/dotty/tools/dotc/core/ConstraintRunInfo.scala
index 4b7e22653..e0f659cc6 100644
--- a/src/dotty/tools/dotc/core/ConstraintRunInfo.scala
+++ b/src/dotty/tools/dotc/core/ConstraintRunInfo.scala
@@ -1,7 +1,8 @@
package dotty.tools.dotc
package core
-import Contexts._, config.Printers._
+import Contexts._
+import config.Printers.typr
trait ConstraintRunInfo { self: RunInfo =>
private var maxSize = 0
diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala
index e7e388be9..458f8b82f 100644
--- a/src/dotty/tools/dotc/core/OrderingConstraint.scala
+++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala
@@ -8,7 +8,6 @@ import collection.mutable
import printing.{Printer, Showable}
import printing.Texts._
import config.Config
-import config.Printers._
import collection.immutable.BitSet
import reflect.ClassTag
import annotation.tailrec
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index 4b2861452..222e2235d 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -9,7 +9,7 @@ import util.DotClass
import DenotTransformers._
import Denotations._
import Decorators._
-import config.Printers._
+import config.Printers.config
import scala.collection.mutable.{ListBuffer, ArrayBuffer}
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransformer, MiniPhase, TreeTransform}
import dotty.tools.dotc.transform._
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 47ec541ab..ab45550a4 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -16,7 +16,7 @@ import CheckRealizable._
import util.SimpleMap
import util.Stats
import config.Config
-import config.Printers._
+import config.Printers.{completions, incremental, noPrinter}
trait SymDenotations { this: Context =>
import SymDenotations._
@@ -46,7 +46,7 @@ trait SymDenotations { this: Context =>
val initial = denot.initial
val firstPhaseId = initial.validFor.firstPhaseId.max(ctx.typerPhase.id)
if ((initial ne denot) || ctx.phaseId != firstPhaseId)
- ctx.withPhase(firstPhaseId).stillValidInOwner(initial.asSymDenotation)
+ ctx.withPhase(firstPhaseId).stillValidInOwner(initial)
else
stillValidInOwner(denot)
}
@@ -56,6 +56,7 @@ trait SymDenotations { this: Context =>
stillValid(owner) && (
!owner.isClass
|| owner.isRefinementClass
+ || owner.is(Scala2x)
|| (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
|| denot.isSelfSym)
} catch {
@@ -77,7 +78,7 @@ trait SymDenotations { this: Context =>
implicit val ctx: Context = this
val initial = denot.initial
if ((initial ne denot) || ctx.phaseId != initial.validFor.firstPhaseId) {
- ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial.asSymDenotation)
+ ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial)
} else try {
val owner = denot.owner.denot
if (!traceInvalid(owner)) explainSym("owner is invalid")
@@ -346,14 +347,14 @@ object SymDenotations {
else {
def legalize(name: Name): Name = // JVM method names may not contain `<' or `>' characters
if (is(Method)) name.replace('<', '(').replace('>', ')') else name
- legalize(name.expandedName(initial.asSymDenotation.owner))
+ legalize(name.expandedName(initial.owner))
}
// need to use initial owner to disambiguate, as multiple private symbols with the same name
// might have been moved from different origins into the same class
/** The name with which the denoting symbol was created */
final def originalName(implicit ctx: Context) = {
- val d = initial.asSymDenotation
+ val d = initial
if (d is ExpandedName) d.name.unexpandedName else d.name // !!!DEBUG, was: effectiveName
}
@@ -435,13 +436,13 @@ object SymDenotations {
/** Is this symbol an anonymous class? */
final def isAnonymousClass(implicit ctx: Context): Boolean =
- isClass && (initial.asSymDenotation.name startsWith tpnme.ANON_CLASS)
+ isClass && (initial.name startsWith tpnme.ANON_CLASS)
final def isAnonymousFunction(implicit ctx: Context) =
- this.symbol.is(Method) && (initial.asSymDenotation.name startsWith nme.ANON_FUN)
+ this.symbol.is(Method) && (initial.name startsWith nme.ANON_FUN)
final def isAnonymousModuleVal(implicit ctx: Context) =
- this.symbol.is(ModuleVal) && (initial.asSymDenotation.name startsWith nme.ANON_CLASS)
+ this.symbol.is(ModuleVal) && (initial.name startsWith nme.ANON_CLASS)
/** Is this a companion class method or companion object method?
* These methods are generated by Symbols#synthesizeCompanionMethod
@@ -606,7 +607,7 @@ object SymDenotations {
/** Is this symbol a class that extends `AnyVal`? */
final def isValueClass(implicit ctx: Context): Boolean = {
- val di = this.initial.asSymDenotation
+ val di = initial
di.isClass &&
di.derivesFrom(defn.AnyValClass)(ctx.withPhase(di.validFor.firstPhaseId))
// We call derivesFrom at the initial phase both because AnyVal does not exist
@@ -1164,6 +1165,8 @@ object SymDenotations {
d
}
+ override def initial: SymDenotation = super.initial.asSymDenotation
+
/** Install this denotation as the result of the given denotation transformer. */
override def installAfter(phase: DenotTransformer)(implicit ctx: Context): Unit =
super.installAfter(phase)
@@ -1226,10 +1229,13 @@ object SymDenotations {
if (myTypeParams == null)
myTypeParams =
if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
- else if (this ne initial) initial.asSymDenotation.typeParams
- else infoOrCompleter match {
- case info: TypeParamsCompleter => info.completerTypeParams(symbol)
- case _ => typeParamsFromDecls
+ else {
+ val di = initial
+ if (this ne di) di.typeParams
+ else infoOrCompleter match {
+ case info: TypeParamsCompleter => info.completerTypeParams(symbol)
+ case _ => typeParamsFromDecls
+ }
}
myTypeParams
}
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index af362f4da..f32a591a6 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -13,7 +13,7 @@ import NameOps._
import Flags._
import StdNames.tpnme
import util.Positions.Position
-import config.Printers._
+import config.Printers.core
import collection.mutable
import dotty.tools.dotc.config.Config
import java.util.NoSuchElementException
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 538a74198..991dd2664 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -8,7 +8,7 @@ import StdNames.{nme, tpnme}
import collection.mutable
import util.{Stats, DotClass, SimpleMap}
import config.Config
-import config.Printers._
+import config.Printers.{typr, constr, subtyping}
import TypeErasure.{erasedLub, erasedGlb}
import TypeApplications._
import scala.util.control.NonFatal
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index b69ce2536..5ba9a3351 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -4,7 +4,7 @@ package core
import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._
import SymDenotations._, Denotations.SingleDenotation
-import config.Printers._
+import config.Printers.typr
import util.Positions._
import NameOps._
import Decorators._
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 87d94dcbe..30d1c0136 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -28,11 +28,11 @@ import Hashable._
import Uniques._
import collection.{mutable, Seq, breakOut}
import config.Config
-import config.Printers._
import annotation.tailrec
import Flags.FlagSet
import language.implicitConversions
import scala.util.hashing.{ MurmurHash3 => hashing }
+import config.Printers.{core, typr, cyclicErrors}
object Types {
@@ -927,7 +927,7 @@ object Types {
def narrow(implicit ctx: Context): TermRef =
TermRef(NoPrefix, ctx.newSkolem(this))
- /** Useful for diagnsotics: The underlying type if this type is a type proxy,
+ /** Useful for diagnostics: The underlying type if this type is a type proxy,
* otherwise NoType
*/
def underlyingIfProxy(implicit ctx: Context) = this match {
@@ -935,6 +935,9 @@ object Types {
case _ => NoType
}
+ /** If this is a FunProto or PolyProto, WildcardType, otherwise this. */
+ def notApplied: Type = this
+
// ----- Normalizing typerefs over refined types ----------------------------
/** If this normalizes* to a refinement type that has a refinement for `name` (which might be followed
@@ -2532,8 +2535,8 @@ object Types {
/** A type for polymorphic methods */
class PolyType(val paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)
extends CachedGroundType with GenericType with MethodOrPoly {
- val paramBounds = paramBoundsExp(this)
- val resType = resultTypeExp(this)
+ val paramBounds: List[TypeBounds] = paramBoundsExp(this)
+ val resType: Type = resultTypeExp(this)
def variances = Nil
protected def computeSignature(implicit ctx: Context) = resultSignature
diff --git a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index 394d8f11a..e9de68e7f 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -74,7 +74,6 @@ Standard-Section: "ASTs" TopLevelStat*
SELECT possiblySigned_NameRef qual_Term
NEW cls_Type
SUPER Length this_Term mixinTrait_Type?
- PAIR Length left_Term right_Term
TYPED Length expr_Term ascription_Type
NAMEDARG Length paramName_NameRef arg_Term
ASSIGN Length lhs_Term rhs_Term
@@ -300,7 +299,8 @@ object TastyFormat {
final val RENAMED = 138
final val APPLY = 139
final val TYPEAPPLY = 140
- final val PAIR = 142
+
+
final val TYPED = 143
final val NAMEDARG = 144
final val ASSIGN = 145
@@ -452,7 +452,6 @@ object TastyFormat {
case APPLY => "APPLY"
case TYPEAPPLY => "TYPEAPPLY"
case NEW => "NEW"
- case PAIR => "PAIR"
case TYPED => "TYPED"
case NAMEDARG => "NAMEDARG"
case ASSIGN => "ASSIGN"
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index be3999533..e5cacfc00 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -392,9 +392,6 @@ class TreePickler(pickler: TastyPickler) {
case New(tpt) =>
writeByte(NEW)
pickleTpt(tpt)
- case Pair(left, right) =>
- writeByte(PAIR)
- withLength { pickleTree(left); pickleTree(right) }
case Typed(expr, tpt) =>
writeByte(TYPED)
withLength { pickleTree(expr); pickleTpt(tpt) }
@@ -496,7 +493,7 @@ class TreePickler(pickler: TastyPickler) {
withLength {
pickleTree(expr)
selectors foreach {
- case Pair(Ident(from), Ident(to)) =>
+ case Thicket(Ident(from) :: Ident(to) :: Nil) =>
writeByte(RENAMED)
withLength { pickleName(from); pickleName(to) }
case Ident(name) =>
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 31247c005..56bb8498a 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -729,9 +729,12 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
}
}
val mods =
- if (sym.annotations.isEmpty) EmptyModifiers
- else Modifiers(annotations = sym.annotations.map(_.tree))
- tree.withMods(mods) // record annotations in tree so that tree positions can be filled in.
+ if (sym.annotations.isEmpty) untpd.EmptyModifiers
+ else untpd.Modifiers(annotations = sym.annotations.map(_.tree))
+ tree.withMods(mods)
+ // record annotations in tree so that tree positions can be filled in.
+ // Note: Once the inline PR with its changes to positions is in, this should be
+ // no longer necessary.
goto(end)
setPos(start, tree)
}
@@ -831,7 +834,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case RENAMED =>
readByte()
readEnd()
- untpd.Pair(untpd.Ident(readName()), untpd.Ident(readName())) :: readSelectors()
+ untpd.Thicket(untpd.Ident(readName()), untpd.Ident(readName())) :: readSelectors()
case IMPORTED =>
readByte()
untpd.Ident(readName()) :: readSelectors()
@@ -915,8 +918,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
tpd.Apply(fn, until(end)(readArg()))
case TYPEAPPLY =>
tpd.TypeApply(readTerm(), until(end)(readTpt()))
- case PAIR =>
- Pair(readTerm(), readTerm())
case TYPED =>
val expr = readTerm()
val tpt = readTpt()
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 0d91e8cd6..70148b3e2 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -12,6 +12,7 @@ import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._
import dotty.tools.dotc.typer.ProtoTypes.{FunProtoTyped, FunProto}
import util.Positions._
import dotty.tools.dotc.ast.{tpd, Trees, untpd}, ast.tpd._
+import ast.untpd.Modifiers
import printing.Texts._
import printing.Printer
import io.AbstractFile
@@ -1044,7 +1045,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
val toName = readNameRef()
val from = untpd.Ident(fromName)
val to = untpd.Ident(toName)
- if (toName.isEmpty) from else untpd.Pair(from, untpd.Ident(toName))
+ if (toName.isEmpty) from else untpd.Thicket(from, untpd.Ident(toName))
})
Import(expr, selectors)
@@ -1186,7 +1187,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case ANNOTATEDtree =>
val annot = readTreeRef()
val arg = readTreeRef()
- Annotated(annot, arg)
+ Annotated(arg, annot)
case SINGLETONTYPEtree =>
SingletonTypeTree(readTreeRef())
@@ -1194,7 +1195,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case SELECTFROMTYPEtree =>
val qualifier = readTreeRef()
val selector = readTypeNameRef()
- SelectFromTypeTree(qualifier, symbol.namedType)
+ Select(qualifier, symbol.namedType)
case COMPOUNDTYPEtree =>
readTemplateRef()
@@ -1236,7 +1237,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
val pflags = (pflagsHi.toLong << 32) + pflagsLo
val flags = unpickleScalaFlags(pflags, isType)
val privateWithin = readNameRef().asTypeName
- Trees.Modifiers[Type](flags, privateWithin, Nil)
+ Modifiers(flags, privateWithin, Nil)
}
protected def readTemplateRef()(implicit ctx: Context): Template =
diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala
index fbb362354..ed7cf9e3f 100644
--- a/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -10,6 +10,7 @@ import scala.language.implicitConversions
import JavaTokens._
import JavaScanners._
+import Scanners.Offset
import Parsers._
import core._
import Contexts._
@@ -107,9 +108,6 @@ object JavaParsers {
def unimplementedExpr = Ident("???".toTermName)
- def makePackaging(pkg: RefTree, stats: List[Tree]): PackageDef =
- atPos(pkg.pos) { PackageDef(pkg, stats) }
-
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean) = {
def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match {
case (meth: DefDef) :: rest if meth.name == CONSTRUCTOR => (meth, rest)
@@ -229,7 +227,7 @@ object JavaParsers {
def convertToTypeId(tree: Tree): Tree = convertToTypeName(tree) match {
case Some(t) => t withPos tree.pos
case _ => tree match {
- case AppliedTypeTree(_, _) | SelectFromTypeTree(_, _) =>
+ case AppliedTypeTree(_, _) | Select(_, _) =>
tree
case _ =>
syntaxError("identifier expected", tree.pos)
@@ -250,14 +248,14 @@ object JavaParsers {
var t: RefTree = atPos(in.offset) { Ident(ident()) }
while (in.token == DOT) {
in.nextToken()
- t = atPos(in.offset) { Select(t, ident()) }
+ t = atPos(t.pos.start, in.offset) { Select(t, ident()) }
}
t
}
def optArrayBrackets(tpt: Tree): Tree =
if (in.token == LBRACKET) {
- val tpt1 = atPos(in.offset) { arrayOf(tpt) }
+ val tpt1 = atPos(tpt.pos.start, in.offset) { arrayOf(tpt) }
in.nextToken()
accept(RBRACKET)
optArrayBrackets(tpt1)
@@ -283,18 +281,15 @@ object JavaParsers {
if (in.token == FINAL) in.nextToken()
if (in.token == IDENTIFIER) {
var t = typeArgs(atPos(in.offset)(Ident(ident())))
- // typeSelect generates Select nodes is the lhs is an Ident or Select,
- // SelectFromTypeTree otherwise. See #3567.
- // Select nodes can be later
- // converted in the typechecker to SelectFromTypeTree if the class
- // turns out to be an instance ionner class instead of a static inner class.
+ // typeSelect generates Select nodes if the lhs is an Ident or Select,
+ // For other nodes it always assumes that the selected item is a type.
def typeSelect(t: Tree, name: Name) = t match {
case Ident(_) | Select(_, _) => Select(t, name)
- case _ => SelectFromTypeTree(t, name.toTypeName)
+ case _ => Select(t, name.toTypeName)
}
while (in.token == DOT) {
in.nextToken()
- t = typeArgs(atPos(in.offset)(typeSelect(t, ident())))
+ t = typeArgs(atPos(t.pos.start, in.offset)(typeSelect(t, ident())))
}
convertToTypeId(t)
} else {
@@ -328,7 +323,7 @@ object JavaParsers {
val t1 = convertToTypeId(t)
val args = repsep(typeArg, COMMA)
acceptClosingAngle()
- atPos(t1.pos) {
+ atPos(t1.pos.start) {
AppliedTypeTree(t1, args)
}
} else t
@@ -356,7 +351,11 @@ 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)).withPos(Position(in.offset))
+ def addAnnot(sym: ClassSymbol) =
+ annots :+= atPos(in.offset) {
+ in.nextToken()
+ New(TypeTree(sym.typeRef))
+ }
while (true) {
in.token match {
@@ -387,13 +386,10 @@ object JavaParsers {
in.nextToken()
case NATIVE =>
addAnnot(NativeAnnot)
- in.nextToken()
case TRANSIENT =>
addAnnot(TransientAnnot)
- in.nextToken()
case VOLATILE =>
addAnnot(VolatileAnnot)
- in.nextToken()
case SYNCHRONIZED | STRICTFP =>
in.nextToken()
case _ =>
@@ -443,16 +439,19 @@ object JavaParsers {
}
def formalParam(): ValDef = {
+ val start = in.offset
if (in.token == FINAL) in.nextToken()
annotations()
var t = typ()
if (in.token == DOTDOTDOT) {
in.nextToken()
- t = atPos(t.pos) {
+ t = atPos(t.pos.start) {
PostfixOp(t, nme.raw.STAR)
}
}
- varDecl(Position(in.offset), Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName)
+ atPos(start, in.offset) {
+ varDecl(Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName)
+ }
}
def optThrows(): Unit = {
@@ -462,7 +461,7 @@ object JavaParsers {
}
}
- def methodBody(): Tree = {
+ def methodBody(): Tree = atPos(in.offset) {
skipAhead()
accept(RBRACE) // skip block
unimplementedExpr
@@ -470,16 +469,18 @@ object JavaParsers {
def definesInterface(token: Int) = token == INTERFACE || token == AT
- def termDecl(mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = {
+ def termDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = {
val inInterface = definesInterface(parentToken)
val tparams = if (in.token == LT) typeParams(Flags.JavaDefined | Flags.Param) else List()
val isVoid = in.token == VOID
var rtpt =
- if (isVoid) {
- in.nextToken()
- TypeTree(UnitType) withPos Position(in.offset)
- } else typ()
- var offset = in.offset
+ if (isVoid)
+ atPos(in.offset) {
+ in.nextToken()
+ TypeTree(UnitType)
+ }
+ else typ()
+ var nameOffset = in.offset
val rtptName = rtpt match {
case Ident(name) => name
case _ => nme.EMPTY
@@ -489,14 +490,15 @@ object JavaParsers {
val vparams = formalParams()
optThrows()
List {
- atPos(offset) {
- DefDef(nme.CONSTRUCTOR, parentTParams, List(vparams), TypeTree(), methodBody()).withMods(mods)
+ atPos(start) {
+ DefDef(nme.CONSTRUCTOR, parentTParams,
+ List(vparams), TypeTree(), methodBody()).withMods(mods)
}
}
} else {
var mods1 = mods
if (mods is Flags.Abstract) mods1 = mods &~ Flags.Abstract
- offset = in.offset
+ nameOffset = in.offset
val name = ident()
if (in.token == LPAREN) {
// method declaration
@@ -510,13 +512,14 @@ object JavaParsers {
} else {
if (parentToken == AT && in.token == DEFAULT) {
val annot =
- atPos(offset) {
+ atPos(nameOffset) {
New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), Nil)
}
mods1 = mods1 withAddedAnnotation annot
+ val unimplemented = unimplementedExpr
skipTo(SEMI)
accept(SEMI)
- unimplementedExpr
+ unimplemented
} else {
accept(SEMI)
EmptyTree
@@ -524,13 +527,13 @@ object JavaParsers {
}
//if (inInterface) mods1 |= Flags.Deferred
List {
- atPos(offset) {
+ atPos(start, nameOffset) {
DefDef(name.toTermName, tparams, List(vparams), rtpt, body).withMods(mods1 | Flags.Method)
}
}
} else {
if (inInterface) mods1 |= Flags.Final | Flags.JavaStatic
- val result = fieldDecls(Position(offset), mods1, rtpt, name)
+ val result = fieldDecls(start, nameOffset, mods1, rtpt, name)
accept(SEMI)
result
}
@@ -546,19 +549,21 @@ object JavaParsers {
* Once we have reached the end of the statement, we know whether
* these potential definitions are real or not.
*/
- def fieldDecls(pos: Position, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = {
- val buf = ListBuffer[Tree](varDecl(pos, mods, tpt, name.toTermName))
+ def fieldDecls(start: Offset, firstNameOffset: Offset, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = {
+ val buf = ListBuffer[Tree](
+ atPos(start, firstNameOffset) { varDecl(mods, tpt, name.toTermName) })
val maybe = new ListBuffer[Tree] // potential variable definitions.
while (in.token == COMMA) {
in.nextToken()
if (in.token == IDENTIFIER) { // if there's an ident after the comma ...
+ val nextNameOffset = in.offset
val name = ident()
if (in.token == EQUALS || in.token == SEMI) { // ... followed by a `=` or `;`, we know it's a real variable definition
buf ++= maybe
- buf += varDecl(Position(in.offset), mods, tpt, name.toTermName)
+ buf += atPos(start, nextNameOffset) { varDecl(mods, tpt, name.toTermName) }
maybe.clear()
} else if (in.token == COMMA) { // ... if there's a comma after the ident, it could be a real vardef or not.
- maybe += varDecl(Position(in.offset), mods, tpt, name.toTermName)
+ maybe += atPos(start, nextNameOffset) { varDecl(mods, tpt, name.toTermName) }
} else { // ... if there's something else we were still in the initializer of the
// previous var def; skip to next comma or semicolon.
skipTo(COMMA, SEMI)
@@ -576,35 +581,29 @@ object JavaParsers {
buf.toList
}
- def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
+ def varDecl(mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
val tpt1 = optArrayBrackets(tpt)
if (in.token == EQUALS && !(mods is Flags.Param)) skipTo(COMMA, SEMI)
val mods1 = if (mods is Flags.Final) mods else mods | Flags.Mutable
- atPos(pos) {
- ValDef(name, tpt1, if (mods is Flags.Param) EmptyTree else unimplementedExpr).withMods(mods1)
- }
+ ValDef(name, tpt1, if (mods is Flags.Param) EmptyTree else unimplementedExpr).withMods(mods1)
}
- def memberDecl(mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match {
+ def memberDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match {
case CLASS | ENUM | INTERFACE | AT =>
- typeDecl(if (definesInterface(parentToken)) mods | Flags.JavaStatic else mods)
+ typeDecl(start, if (definesInterface(parentToken)) mods | Flags.JavaStatic else mods)
case _ =>
- termDecl(mods, parentToken, parentTParams)
+ termDecl(start, mods, parentToken, parentTParams)
}
def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree =
atPos(cdef.pos) {
+ assert(cdef.pos.exists)
ModuleDef(cdef.name.toTermName,
makeTemplate(List(), statics, List(), false)).withMods((cdef.mods & (Flags.AccessFlags | Flags.JavaDefined)).toTermFlags)
}
- private val wild = Ident(nme.WILDCARD) withPos Position(-1)
- private val wildList = List(wild) // OPT This list is shared for performance.
-
def importCompanionObject(cdef: TypeDef): Tree =
- atPos(cdef.pos) {
- Import(Ident(cdef.name.toTermName), wildList)
- }
+ Import(Ident(cdef.name.toTermName).withPos(NoPosition), Ident(nme.WILDCARD) :: Nil)
// Importing the companion object members cannot be done uncritically: see
// ticket #2377 wherein a class contains two static inner classes, each of which
@@ -633,8 +632,8 @@ object JavaParsers {
}
def importDecl(): List[Tree] = {
+ val start = in.offset
accept(IMPORT)
- val offset = in.offset
val buf = new ListBuffer[Name]
def collectIdents() : Int = {
if (in.token == ASTERISK) {
@@ -657,7 +656,7 @@ object JavaParsers {
accept(SEMI)
val names = buf.toList
if (names.length < 2) {
- syntaxError(offset, "illegal import", skipIt = false)
+ syntaxError(start, "illegal import", skipIt = false)
List()
} else {
val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _))
@@ -667,7 +666,8 @@ object JavaParsers {
// case nme.WILDCARD => Pair(ident, Ident(null) withPos Position(-1))
// case _ => Pair(ident, ident)
// }
- List(atPos(offset)(Import(qual, List(ident))))
+ val imp = atPos(start) { Import(qual, List(ident)) }
+ imp :: Nil
}
}
@@ -679,9 +679,9 @@ object JavaParsers {
List()
}
- def classDecl(mods: Modifiers): List[Tree] = {
+ def classDecl(start: Offset, mods: Modifiers): List[Tree] = {
accept(CLASS)
- val offset = in.offset
+ val nameOffset = in.offset
val name = identForType()
val tparams = typeParams()
val superclass =
@@ -693,14 +693,15 @@ object JavaParsers {
}
val interfaces = interfacesOpt()
val (statics, body) = typeBody(CLASS, name, tparams)
- addCompanionObject(statics, atPos(offset) {
+ val cls = atPos(start, nameOffset) {
TypeDef(name, makeTemplate(superclass :: interfaces, body, tparams, true)).withMods(mods)
- })
+ }
+ addCompanionObject(statics, cls)
}
- def interfaceDecl(mods: Modifiers): List[Tree] = {
+ def interfaceDecl(start: Offset, mods: Modifiers): List[Tree] = {
accept(INTERFACE)
- val offset = in.offset
+ val nameOffset = in.offset
val name = identForType()
val tparams = typeParams()
val parents =
@@ -711,11 +712,12 @@ object JavaParsers {
List(javaLangObject())
}
val (statics, body) = typeBody(INTERFACE, name, tparams)
- addCompanionObject(statics, atPos(offset) {
+ val iface = atPos(start, nameOffset) {
TypeDef(
name, tparams,
makeTemplate(parents, body, tparams, false)).withMods(mods | Flags.Trait | Flags.JavaInterface | Flags.Abstract)
- })
+ }
+ addCompanionObject(statics, iface)
}
def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
@@ -730,7 +732,8 @@ object JavaParsers {
val statics = new ListBuffer[Tree]
val members = new ListBuffer[Tree]
while (in.token != RBRACE && in.token != EOF) {
- var mods = modifiers(inInterface)
+ val start = in.offset
+ var mods = atPos(start) { modifiers(inInterface) }
if (in.token == LBRACE) {
skipAhead() // skip init block, we just assume we have seen only static
accept(RBRACE)
@@ -738,7 +741,7 @@ object JavaParsers {
in.nextToken()
} else {
if (in.token == ENUM || definesInterface(in.token)) mods |= Flags.JavaStatic
- val decls = memberDecl(mods, parentToken, parentTParams)
+ val decls = memberDecl(start, mods, parentToken, parentTParams)
(if ((mods is Flags.JavaStatic) || inInterface && !(decls exists (_.isInstanceOf[DefDef])))
statics
else
@@ -761,10 +764,10 @@ object JavaParsers {
Select(javaLangDot(nme.annotation), tpnme.Annotation),
scalaAnnotationDot(tpnme.ClassfileAnnotation)
)
- def annotationDecl(mods: Modifiers): List[Tree] = {
+ def annotationDecl(start: Offset, mods: Modifiers): List[Tree] = {
accept(AT)
accept(INTERFACE)
- val offset = in.offset
+ val nameOffset = in.offset
val name = identForType()
val (statics, body) = typeBody(AT, name, List())
val constructorParams = body.collect {
@@ -774,14 +777,15 @@ object JavaParsers {
List(), List(constructorParams), TypeTree(), EmptyTree).withMods(Modifiers(Flags.JavaDefined))
val body1 = body.filterNot(_.isInstanceOf[DefDef])
val templ = makeTemplate(annotationParents, constr :: body1, List(), false)
- addCompanionObject(statics, atPos(offset) {
+ val annot = atPos(start, nameOffset) {
TypeDef(name, templ).withMods(mods | Flags.Abstract)
- })
+ }
+ addCompanionObject(statics, annot)
}
- def enumDecl(mods: Modifiers): List[Tree] = {
+ def enumDecl(start: Offset, mods: Modifiers): List[Tree] = {
accept(ENUM)
- val offset = in.offset
+ val nameOffset = in.offset
val name = identForType()
def enumType = Ident(name)
val interfaces = interfacesOpt()
@@ -824,10 +828,11 @@ object JavaParsers {
val superclazz = Apply(TypeApply(
Select(New(javaLangDot(tpnme.Enum)), nme.CONSTRUCTOR), List(enumType)),
List(Literal(Constant(null)),Literal(Constant(0))))
- addCompanionObject(consts ::: statics ::: predefs, atPos(offset) {
+ val enum = atPos(start, nameOffset) {
TypeDef(name, List(),
makeTemplate(superclazz :: interfaces, body, List(), true)).withMods(mods | Flags.Enum)
- })
+ }
+ addCompanionObject(consts ::: statics ::: predefs, enum)
}
def enumConst(enumType: Tree) = {
@@ -848,22 +853,21 @@ object JavaParsers {
}
}
- def typeDecl(mods: Modifiers): List[Tree] = in.token match {
- case ENUM => enumDecl(mods)
- case INTERFACE => interfaceDecl(mods)
- case AT => annotationDecl(mods)
- case CLASS => classDecl(mods)
+ def typeDecl(start: Offset, mods: Modifiers): List[Tree] = in.token match {
+ case ENUM => enumDecl(start, mods)
+ case INTERFACE => interfaceDecl(start, mods)
+ case AT => annotationDecl(start, mods)
+ case CLASS => classDecl(start, mods)
case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree)
}
/** CompilationUnit ::= [package QualId semi] TopStatSeq
*/
def compilationUnit(): Tree = {
- var offset = in.offset
+ val start = in.offset
val pkg: RefTree =
if (in.token == AT || in.token == PACKAGE) {
annotations()
- offset = in.offset
accept(PACKAGE)
val pkg = qualId()
accept(SEMI)
@@ -880,13 +884,15 @@ object JavaParsers {
buf ++= importDecl()
while (in.token != EOF && in.token != RBRACE) {
while (in.token == SEMI) in.nextToken()
- if (in.token != EOF)
- buf ++= typeDecl(modifiers(inInterface = false))
+ if (in.token != EOF) {
+ val start = in.offset
+ val mods = atPos(start) { modifiers(inInterface = false) }
+ buf ++= typeDecl(start, mods)
+ }
}
+ val unit = atPos(start) { PackageDef(pkg, buf.toList) }
accept(EOF)
- atPos(offset) {
- makePackaging(pkg, buf.toList)
- }
+ unit
}
}
}
diff --git a/src/dotty/tools/dotc/parsing/JavaScanners.scala b/src/dotty/tools/dotc/parsing/JavaScanners.scala
index faac8e163..83e16627c 100644
--- a/src/dotty/tools/dotc/parsing/JavaScanners.scala
+++ b/src/dotty/tools/dotc/parsing/JavaScanners.scala
@@ -27,6 +27,7 @@ object JavaScanners {
def nextToken(): Unit = {
if (next.token == EMPTY) {
+ lastOffset = lastCharOffset
fetchToken()
}
else {
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 378aa6ed7..86330f3ab 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -59,19 +59,30 @@ object Parsers {
/* ------------- POSITIONS ------------------------------------------- */
+ /** Positions tree.
+ * If `t` does not have a position yet, set its position to the given one.
+ */
+ def atPos[T <: Positioned](pos: Position)(t: T): T =
+ if (t.pos.isSourceDerived) t else t.withPos(pos)
+
def atPos[T <: Positioned](start: Offset, point: Offset, end: Offset)(t: T): T =
atPos(Position(start, end, point))(t)
+ /** If the last read offset is strictly greater than `start`, position tree
+ * to position spanning from `start` to last read offset, with given point.
+ * If the last offset is less than or equal to start, the tree `t` did not
+ * consume any source for its construction. In this case, don't position it yet,
+ * but wait for its position to be determined by `setChildPositions` when the
+ * parent node is positioned.
+ */
def atPos[T <: Positioned](start: Offset, point: Offset)(t: T): T =
- atPos(start, point, in.lastOffset max start)(t)
+ if (in.lastOffset > start) atPos(start, point, in.lastOffset)(t) else t
def atPos[T <: Positioned](start: Offset)(t: T): T =
atPos(start, start)(t)
- def atPos[T <: Positioned](pos: Position)(t: T): T =
- if (t.pos.isSourceDerived) t else t.withPos(pos)
-
- def tokenRange = Position(in.offset, in.lastCharOffset, in.offset)
+ def nameStart: Offset =
+ if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset
def sourcePos(off: Int = in.offset): SourcePosition =
source atPos Position(off)
@@ -313,8 +324,6 @@ object Parsers {
tree
}
- def emptyConstructor() = atPos(in.offset) { ast.untpd.emptyConstructor }
-
/* --------------- PLACEHOLDERS ------------------------------------------- */
/** The implicit parameters introduced by `_` in the current expression.
@@ -601,30 +610,30 @@ object Parsers {
}
private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) {
- val partsBuf = new ListBuffer[Literal]
- val exprBuf = new ListBuffer[Tree]
+ val segmentBuf = new ListBuffer[Tree]
val interpolator = in.name
in.nextToken()
while (in.token == STRINGPART) {
- partsBuf += literal().asInstanceOf[Literal]
- exprBuf += atPos(in.offset) {
- if (in.token == IDENTIFIER)
- termIdent()
- else if (in.token == THIS) {
- in.nextToken()
- This(tpnme.EMPTY)
- }
- else if (in.token == LBRACE)
- if (inPattern) Block(Nil, inBraces(pattern()))
- else expr()
- else {
- syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected")
- EmptyTree
- }
- }
+ segmentBuf += Thicket(
+ literal(),
+ atPos(in.offset) {
+ if (in.token == IDENTIFIER)
+ termIdent()
+ else if (in.token == THIS) {
+ in.nextToken()
+ This(tpnme.EMPTY)
+ }
+ else if (in.token == LBRACE)
+ if (inPattern) Block(Nil, inBraces(pattern()))
+ else expr()
+ else {
+ syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected")
+ EmptyTree
+ }
+ })
}
- if (in.token == STRINGLIT) partsBuf += literal().asInstanceOf[Literal]
- InterpolatedString(interpolator, partsBuf.toList, exprBuf.toList)
+ if (in.token == STRINGLIT) segmentBuf += literal()
+ InterpolatedString(interpolator, segmentBuf.toList)
}
/* ------------- NEW LINES ------------------------------------------------- */
@@ -694,9 +703,10 @@ object Parsers {
}
}
else if (in.token == LBRACKET) {
+ val start = in.offset
val tparams = typeParamClause(ParamOwner.TypeParam)
if (isIdent && in.name.toString == "->")
- atPos(in.skipToken())(TypeLambdaTree(tparams, typ()))
+ atPos(start, in.skipToken())(TypeLambdaTree(tparams, typ()))
else { syntaxErrorOrIncomplete(expectedMessage("`->'")); typ() }
}
else infixType()
@@ -742,7 +752,7 @@ object Parsers {
def annotType(): Tree = annotTypeRest(simpleType())
def annotTypeRest(t: Tree): Tree =
- if (in.token == AT) annotTypeRest(atPos(t.pos.start) { Annotated(annot(), t) })
+ if (in.token == AT) annotTypeRest(atPos(t.pos.start) { Annotated(t, annot()) })
else t
/** SimpleType ::= SimpleType TypeArgs
@@ -762,7 +772,7 @@ object Parsers {
else if (isSimpleLiteral) { SingletonTypeTree(literal()) }
else if (in.token == USCORE) {
val start = in.skipToken()
- typeBounds().withPos(Position(start, in.offset, start))
+ typeBounds().withPos(Position(start, in.lastOffset, start))
}
else path(thisOK = false, handleSingletonType) match {
case r @ SingletonTypeTree(_) => r
@@ -785,7 +795,7 @@ object Parsers {
private def typeProjection(t: Tree): Tree = {
accept(HASH)
val id = typeIdent()
- atPos(t.pos.start, id.pos.start) { SelectFromTypeTree(t, id.name) }
+ atPos(t.pos.start, id.pos.start) { Select(t, id.name) }
}
/** NamedTypeArg ::= id `=' Type
@@ -866,7 +876,8 @@ object Parsers {
def typeParamBounds(pname: TypeName): Tree = {
val t = typeBounds()
val cbs = contextBounds(pname)
- if (cbs.isEmpty) t else atPos(t.pos.start) { ContextBounds(t, cbs) }
+ if (cbs.isEmpty) t
+ else atPos((t.pos union cbs.head.pos).start) { ContextBounds(t, cbs) }
}
def contextBounds(pname: TypeName): List[Tree] = in.token match {
@@ -899,7 +910,7 @@ object Parsers {
private final def findWildcardType(t: Tree): Option[Position] = t match {
case TypeBoundsTree(_, _) => Some(t.pos)
case Parens(t1) => findWildcardType(t1)
- case Annotated(_, t1) => findWildcardType(t1)
+ case Annotated(t1, _) => findWildcardType(t1)
case _ => None
}
@@ -972,7 +983,7 @@ object Parsers {
else
try
if (placeholderParams.isEmpty) t
- else Function(placeholderParams.reverse, t)
+ else new WildcardFunction(placeholderParams.reverse, t)
finally placeholderParams = saved
}
@@ -1009,9 +1020,23 @@ object Parsers {
in.nextToken()
expr()
} else EmptyTree
+
+ handler match {
+ case Block(Nil, EmptyTree) => syntaxError(
+ "`catch` block does not contain a valid expression, try adding a case like - `case e: Exception =>` to the block",
+ handler.pos
+ )
+ case _ =>
+ }
+
val finalizer =
- if (handler.isEmpty || in.token == FINALLY) { accept(FINALLY); expr() }
- else EmptyTree
+ if (in.token == FINALLY) { accept(FINALLY); expr() }
+ else {
+ if (handler.isEmpty)
+ warning("A try without `catch` or `finally` is equivalent to putting its body in a block; no exceptions are handled.")
+
+ EmptyTree
+ }
ParsedTry(body, handler, finalizer)
}
case THROW =>
@@ -1056,12 +1081,13 @@ object Parsers {
syntaxErrorOrIncomplete("`*' expected"); t
}
case AT if location != Location.InPattern =>
- (t /: annotations()) ((t, annot) => Annotated(annot, t))
+ (t /: annotations())(Annotated)
case _ =>
val tpt = typeDependingOn(location)
if (isWildcard(t) && location != Location.InPattern) {
val vd :: rest = placeholderParams
- placeholderParams = cpy.ValDef(vd)(tpt = tpt) :: rest
+ placeholderParams =
+ cpy.ValDef(vd)(tpt = tpt).withPos(vd.pos union tpt.pos) :: rest
}
Typed(t, tpt)
}
@@ -1140,12 +1166,12 @@ object Parsers {
case NEW =>
canApply = false
val start = in.skipToken()
- val (impl, missingBody) = template(emptyConstructor())
+ val (impl, missingBody) = template(emptyConstructor)
impl.parents match {
case parent :: Nil if missingBody =>
if (parent.isType) ensureApplied(wrapNew(parent)) else parent
case _ =>
- New(impl)
+ New(impl.withPos(Position(start, in.lastOffset)))
}
case _ =>
if (isLiteral) literal()
@@ -1348,15 +1374,15 @@ object Parsers {
*/
val pattern2 = () => infixPattern() match {
case p @ Ident(name) if isVarPattern(p) && in.token == AT =>
- val pos = in.skipToken()
+ val offset = in.skipToken()
// compatibility for Scala2 `x @ _*` syntax
infixPattern() match {
case pt @ Ident(tpnme.WILDCARD_STAR) =>
migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start)
- atPos(p.pos.start, pos) { Typed(p, pt) }
+ atPos(p.pos.start, offset) { Typed(p, pt) }
case p =>
- atPos(p.pos.start, pos) { Bind(name, p) }
+ atPos(p.pos.start, offset) { Bind(name, p) }
}
case p @ Ident(tpnme.WILDCARD_STAR) =>
// compatibility for Scala2 `_*` syntax
@@ -1576,12 +1602,12 @@ object Parsers {
def typeParamClause(ownerKind: ParamOwner.Value): List[TypeDef] = inBrackets {
def typeParam(): TypeDef = {
val isConcreteOwner = ownerKind == ParamOwner.Class || ownerKind == ParamOwner.Def
- val modStart = in.offset
+ val start = in.offset
var mods = annotsAsMods()
if (ownerKind == ParamOwner.Class) {
mods = modifiers(start = mods)
mods =
- atPos(modStart, in.offset) {
+ atPos(start, in.offset) {
if (in.token == TYPE) {
in.nextToken()
mods | Param | ParamAccessor
@@ -1591,13 +1617,13 @@ object Parsers {
}
}
}
- else mods = atPos(modStart) (mods | Param)
+ else mods = atPos(start) (mods | Param)
if (ownerKind != ParamOwner.Def) {
if (isIdent(nme.raw.PLUS)) mods |= Covariant
else if (isIdent(nme.raw.MINUS)) mods |= Contravariant
if (mods is VarianceFlags) in.nextToken()
}
- atPos(tokenRange) {
+ atPos(start, nameStart) {
val name =
if (isConcreteOwner || in.token != USCORE) ident().toTypeName
else {
@@ -1631,12 +1657,12 @@ object Parsers {
var firstClauseOfCaseClass = ofCaseClass
var implicitOffset = -1 // use once
def param(): ValDef = {
- val modStart = in.offset
+ val start = in.offset
var mods = annotsAsMods()
if (owner.isTypeName) {
mods = modifiers(start = mods) | ParamAccessor
mods =
- atPos(modStart, in.offset) {
+ atPos(start, in.offset) {
if (in.token == VAL) {
in.nextToken()
mods
@@ -1649,8 +1675,8 @@ object Parsers {
}
}
}
- else mods = atPos(modStart) { mods | Param }
- atPos(tokenRange) {
+ else mods = atPos(start) { mods | Param }
+ atPos(start, nameStart) {
val name = ident()
val tpt =
if (ctx.settings.YmethodInfer.value && owner.isTermName && in.token != COLON) {
@@ -1669,7 +1695,7 @@ object Parsers {
if (in.token == EQUALS) { in.nextToken(); expr() }
else EmptyTree
if (implicitOffset >= 0) {
- mods = mods.withPos(mods.pos.withStart(implicitOffset))
+ mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset)))
implicitOffset = -1
}
ValDef(name, tpt, default).withMods(addFlag(mods, implicitFlag))
@@ -1760,12 +1786,16 @@ object Parsers {
val from = termIdentOrWildcard()
if (from.name != nme.WILDCARD && in.token == ARROW)
atPos(from.pos.start, in.skipToken()) {
- Pair(from, termIdentOrWildcard())
+ Thicket(from, termIdentOrWildcard())
}
else from
}
- def posMods(start: Int, mods: Modifiers) = atPos(start, in.skipToken())(mods)
+ def posMods(start: Int, mods: Modifiers) = {
+ val mods1 = atPos(start)(mods)
+ in.nextToken()
+ mods1
+ }
/** Def ::= val PatDef
* | var VarDef
@@ -1779,13 +1809,13 @@ object Parsers {
*/
def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match {
case VAL =>
- patDefOrDcl(posMods(start, mods), in.getDocComment(start))
+ patDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
case VAR =>
- patDefOrDcl(posMods(start, addFlag(mods, Mutable)), in.getDocComment(start))
+ patDefOrDcl(start, posMods(start, addFlag(mods, Mutable)), in.getDocComment(start))
case DEF =>
- defDefOrDcl(posMods(start, mods), in.getDocComment(start))
+ defDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
case TYPE =>
- typeDefOrDcl(posMods(start, mods), in.getDocComment(start))
+ typeDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
case _ =>
tmplDef(start, mods)
}
@@ -1795,7 +1825,7 @@ object Parsers {
* ValDcl ::= Id {`,' Id} `:' Type
* VarDcl ::= Id {`,' Id} `:' Type
*/
- def patDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = {
+ def patDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) {
val lhs = commaSeparated(pattern2)
val tpt = typedOpt()
val rhs =
@@ -1810,7 +1840,7 @@ object Parsers {
} else EmptyTree
lhs match {
case (id @ Ident(name: TermName)) :: Nil => {
- cpy.ValDef(id)(name, tpt, rhs).withMods(mods).setComment(docstring)
+ ValDef(name, tpt, rhs).withMods(mods).setComment(docstring)
} case _ =>
PatDef(mods, lhs, tpt, rhs)
}
@@ -1821,7 +1851,7 @@ object Parsers {
* DefDcl ::= DefSig `:' Type
* DefSig ::= id [DefTypeParamClause] ParamClauses
*/
- def defDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(tokenRange) {
+ def defDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) {
def scala2ProcedureSyntax(resultTypeStr: String) = {
val toInsert =
if (in.token == LBRACE) s"$resultTypeStr ="
@@ -1896,9 +1926,9 @@ object Parsers {
/** TypeDef ::= type Id [TypeParamClause] `=' Type
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
*/
- def typeDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = {
+ def typeDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = {
newLinesOpt()
- atPos(tokenRange) {
+ atPos(start, nameStart) {
val name = ident().toTypeName
val tparams = typeParamClauseOpt(ParamOwner.Type)
in.token match {
@@ -1921,15 +1951,15 @@ object Parsers {
val docstring = in.getDocComment(start)
in.token match {
case TRAIT =>
- classDef(posMods(start, addFlag(mods, Trait)), docstring)
+ classDef(start, posMods(start, addFlag(mods, Trait)), docstring)
case CLASS =>
- classDef(posMods(start, mods), docstring)
+ classDef(start, posMods(start, mods), docstring)
case CASECLASS =>
- classDef(posMods(start, mods | Case), docstring)
+ classDef(start, posMods(start, mods | Case), docstring)
case OBJECT =>
- objectDef(posMods(start, mods | Module), docstring)
+ objectDef(start, posMods(start, mods | Module), docstring)
case CASEOBJECT =>
- objectDef(posMods(start, mods | Case | Module), docstring)
+ objectDef(start, posMods(start, mods | Case | Module), docstring)
case _ =>
syntaxErrorOrIncomplete("expected start of definition")
EmptyTree
@@ -1939,9 +1969,9 @@ object Parsers {
/** ClassDef ::= Id [ClsTypeParamClause]
* [ConstrMods] ClsParamClauses TemplateOpt
*/
- def classDef(mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(tokenRange) {
+ def classDef(start: Offset, mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(start, nameStart) {
val name = ident().toTypeName
- val constr = atPos(in.offset) {
+ val constr = atPos(in.lastOffset) {
val tparams = typeParamClauseOpt(ParamOwner.Class)
val cmods = constrModsOpt()
val vparamss = paramClauses(name, mods is Case)
@@ -1966,9 +1996,9 @@ object Parsers {
/** ObjectDef ::= Id TemplateOpt
*/
- def objectDef(mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = {
+ def objectDef(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = atPos(start, nameStart) {
val name = ident()
- val template = templateOpt(emptyConstructor())
+ val template = templateOpt(emptyConstructor)
ModuleDef(name, template).withMods(mods).setComment(docstring)
}
@@ -2007,12 +2037,12 @@ object Parsers {
else {
newLineOptWhenFollowedBy(LBRACE)
if (in.token == LBRACE) template(constr)._1
- else Template(constr, Nil, EmptyValDef, Nil).withPos(constr.pos.toSynthetic)
+ else Template(constr, Nil, EmptyValDef, Nil)
}
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
*/
- def templateBodyOpt(constr: DefDef, parents: List[Tree]) = atPos(constr.pos.start) {
+ def templateBodyOpt(constr: DefDef, parents: List[Tree]) = {
val (self, stats) =
if (in.token == LBRACE) templateBody() else (EmptyValDef, Nil)
Template(constr, parents, self, stats)
@@ -2023,7 +2053,7 @@ object Parsers {
if (in.token == WITH) {
syntaxError("early definitions are not supported; use trait parameters instead")
in.nextToken()
- template(emptyConstructor())
+ template(emptyConstructor)
}
r
}
@@ -2058,7 +2088,7 @@ object Parsers {
if (in.token == PACKAGE) {
val start = in.skipToken()
if (in.token == OBJECT)
- stats += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) })
+ stats += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) })
else stats += packaging(start)
}
else if (in.token == IMPORT)
@@ -2192,7 +2222,7 @@ object Parsers {
in.nextToken()
if (in.token == OBJECT) {
val docstring = in.getDocComment(start)
- ts += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) }, docstring)
+ ts += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }, docstring)
if (in.token != EOF) {
acceptStatSep()
ts ++= topStatSeq()
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 7e2a2893e..205d2b6b9 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -161,8 +161,15 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
import untpd.{modsDeco => _, _}
/** Print modifiers from symbols if tree has type, overriding the untpd behavior. */
- implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDeco =
- tpd.modsDeco(mdef.asInstanceOf[tpd.MemberDef]).asInstanceOf[untpd.ModsDeco]
+ implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDecorator =
+ new untpd.ModsDecorator {
+ def mods = if (mdef.hasType) Modifiers(mdef.symbol) else mdef.rawMods
+ }
+
+ def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = untpd.Modifiers(
+ sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags),
+ if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
+ sym.annotations map (_.tree))
def isLocalThis(tree: Tree) = tree.typeOpt match {
case tp: ThisType => tp.cls == ctx.owner.enclosingClass
@@ -253,6 +260,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt
else {
var modsText = modText(constr.mods, "")
+ if (!modsText.isEmpty) modsText = " " ~ modsText
if (constr.mods.hasAnnotations && !constr.mods.hasFlags) modsText = modsText ~~ " this"
withEnclosingDef(constr) { addVparamssText(tparamsTxt ~~ modsText, vparamss) }
}
@@ -280,7 +288,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case _ => toText(name)
}
case tree @ Select(qual, name) =>
- toTextLocal(qual) ~ ("." ~ nameIdText(tree) provided name != nme.CONSTRUCTOR)
+ if (qual.isType) toTextLocal(qual) ~ "#" ~ toText(name)
+ else toTextLocal(qual) ~ ("." ~ nameIdText(tree) provided name != nme.CONSTRUCTOR)
case tree: This =>
optDotPrefix(tree) ~ "this" ~ idText(tree)
case Super(qual: This, mix) =>
@@ -310,8 +319,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
toTextLocal(tpt)
}
}
- case Pair(l, r) =>
- "(" ~ toTextGlobal(l) ~ ", " ~ toTextGlobal(r) ~ ")"
case Typed(expr, tpt) =>
changePrec(InfixPrec) { toText(expr) ~ ": " ~ toText(tpt) }
case NamedArg(name, arg) =>
@@ -350,8 +357,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (tree.hasType) toText(tree.typeOpt) else toText(orig)
case SingletonTypeTree(ref) =>
toTextLocal(ref) ~ ".type"
- case SelectFromTypeTree(qual, name) =>
- toTextLocal(qual) ~ "#" ~ toText(name)
case AndTypeTree(l, r) =>
changePrec(AndPrec) { toText(l) ~ " & " ~ toText(r) }
case OrTypeTree(l, r) =>
@@ -415,7 +420,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
case Import(expr, selectors) =>
def selectorText(sel: Tree): Text = sel match {
- case Pair(l, r) => toTextGlobal(l) ~ " => " ~ toTextGlobal(r)
+ case Thicket(l :: r :: Nil) => toTextGlobal(l) ~ " => " ~ toTextGlobal(r)
case _ => toTextGlobal(sel)
}
val selectorsText: Text = selectors match {
@@ -433,7 +438,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
"package " ~ toTextPackageId(pid) ~ bodyText
case tree: Template =>
toTextTemplate(tree)
- case Annotated(annot, arg) =>
+ case Annotated(arg, annot) =>
toTextLocal(arg) ~~ annotText(annot)
case EmptyTree =>
"<empty>"
@@ -445,15 +450,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
case SymbolLit(str) =>
"'" + str
- case InterpolatedString(id, strings, elems) =>
- def interleave(strs: List[Text], elems: List[Text]): Text = ((strs, elems): @unchecked) match {
- case (Nil, Nil) => ""
- case (str :: Nil, Nil) => str
- case (str :: strs1, elem :: elems1) => str ~ elem ~ interleave(strs1, elems1)
+ case InterpolatedString(id, segments) =>
+ def strText(str: Literal) = Str(escapedString(str.const.stringValue))
+ def segmentText(segment: Tree) = segment match {
+ case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}"
+ case str: Literal => strText(str)
}
- val strTexts = strings map (str => Str(escapedString(str.const.stringValue)))
- val elemsTexts = elems map (elem => "{" ~ toTextGlobal(elem) ~ "}")
- toText(id) ~ "\"" ~ interleave(strTexts, elemsTexts) ~ "\""
+ toText(id) ~ "\"" ~ Text(segments map segmentText, "") ~ "\""
case Function(args, body) =>
var implicitSeen: Boolean = false
def argToText(arg: Tree) = arg match {
diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala
index 954bff88e..b7b7c1af0 100644
--- a/src/dotty/tools/dotc/reporting/StoreReporter.scala
+++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala
@@ -5,7 +5,7 @@ package reporting
import core.Contexts.Context
import collection.mutable
import Reporter.{Error, Warning}
-import config.Printers._
+import config.Printers.typr
/**
* This class implements a Reporter that stores all messages
diff --git a/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
index 026a518ce..a36b47aa8 100644
--- a/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
+++ b/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
@@ -184,7 +184,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp
selectors foreach {
case Ident(name) =>
addImported(name)
- case Pair(Ident(name), Ident(rename)) =>
+ case Thicket(Ident(name) :: Ident(rename) :: Nil) =>
addImported(name)
if (rename ne nme.WILDCARD)
addUsedName(rename)
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 24dea5118..a503d55e5 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -388,9 +388,6 @@ object Erasure extends TypeTestsCasts{
recur(typed(tree.qualifier, AnySelectionProto))
}
- override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context) =
- 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)
else {
diff --git a/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/src/dotty/tools/dotc/transform/ExpandSAMs.scala
index 04c6864b1..91399f91a 100644
--- a/src/dotty/tools/dotc/transform/ExpandSAMs.scala
+++ b/src/dotty/tools/dotc/transform/ExpandSAMs.scala
@@ -74,7 +74,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer =>
Bind(defaultSym, Underscore(selector.tpe.widen)),
EmptyTree,
Literal(Constant(false)))
- val annotated = Annotated(New(ref(defn.UncheckedAnnotType)), paramRef)
+ val annotated = Annotated(paramRef, New(ref(defn.UncheckedAnnotType)))
cpy.Match(applyRhs)(annotated, cases.map(translateCase) :+ defaultCase)
case _ =>
tru
diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala
index 504f9250b..e63a7c3a7 100644
--- a/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -210,7 +210,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
def transformMemberDefNonVolatile(x: ValOrDefDef)(implicit ctx: Context) = {
val claz = x.symbol.owner.asClass
val tpe = x.tpe.widen.resultType.widen
- assert(!(x.mods is Flags.Mutable))
+ assert(!(x.symbol is Flags.Mutable))
val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName
val containerSymbol = ctx.newSymbol(claz, containerName,
x.symbol.flags &~ containerFlagsMask | containerFlags | Flags.Private,
@@ -220,14 +220,14 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val containerTree = ValDef(containerSymbol, defaultValue(tpe))
if (x.tpe.isNotNull && tpe <:< defn.ObjectType) { // can use 'null' value instead of flag
val slowPath = DefDef(x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, x.rhs))
- Thicket(List(containerTree, slowPath))
+ Thicket(containerTree, slowPath)
}
else {
val flagName = ctx.freshName(x.name ++ StdNames.nme.BITMAP_PREFIX).toTermName
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags | Flags.Private, defn.BooleanType).enteredAfter(this)
val flag = ValDef(flagSymbol, Literal(Constants.Constant(false)))
val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs))
- Thicket(List(containerTree, flag, slowPath))
+ Thicket(containerTree, flag, slowPath)
}
}
@@ -331,7 +331,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
}
def transformMemberDefVolatile(x: ValOrDefDef)(implicit ctx: Context) = {
- assert(!(x.mods is Flags.Mutable))
+ assert(!(x.symbol is Flags.Mutable))
val tpe = x.tpe.widen.resultType.widen
val claz = x.symbol.owner.asClass
@@ -377,7 +377,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
}
val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName
- val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this)
+ val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags, tpe, coord = x.symbol.coord).enteredAfter(this)
val containerTree = ValDef(containerSymbol, defaultValue(tpe))
@@ -390,8 +390,8 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val accessor = mkThreadSafeDef(x.symbol.asTerm, claz, ord, containerSymbol, x.rhs, tpe, offset, getFlag, state, cas, setFlag, wait)
if (flag eq EmptyTree)
- Thicket(List(containerTree, accessor))
- else Thicket(List(containerTree, flag, accessor))
+ Thicket(containerTree, accessor)
+ else Thicket(containerTree, flag, accessor)
}
}
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 21b56959b..490feb7d0 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -37,7 +37,7 @@ import scala.reflect.internal.util.Collections
* elimRepeated is required
* TODO: outer tests are not generated yet.
*/
-class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTransformer =>
+class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
import dotty.tools.dotc.ast.tpd._
override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref
@@ -80,7 +80,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
ctx.newSymbol(owner, ctx.freshName(prefix + ctr).toTermName, Flags.Synthetic | Flags.Case, tp, coord = pos)
}
- def newSynthCaseLabel(name: String, tpe:Type, owner: Symbol = ctx.owner) =
+ def newSynthCaseLabel(name: String, tpe: Type, owner: Symbol = ctx.owner) =
ctx.newSymbol(owner, ctx.freshName(name).toTermName, Flags.Label | Flags.Synthetic | Flags.Method, tpe).asTerm
//NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS
@@ -148,30 +148,28 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
}
}
+ object Rebindings {
+ def apply(from: Symbol, to: Symbol) = new Rebindings(List(from), List(ref(to)))
+ // requires sameLength(from, to)
+ def apply(from: List[Symbol], to: List[Tree]) =
+ if (from nonEmpty) new Rebindings(from, to) else NoRebindings
+ }
- object Rebindings {
- def apply(from: Symbol, to: Symbol) = new Rebindings(List(from), List(ref(to)))
- // requires sameLength(from, to)
- def apply(from: List[Symbol], to: List[Tree]) =
- if (from nonEmpty) new Rebindings(from, to) else NoRebindings
- }
-
- class Rebindings(val lhs: List[Symbol], val rhs: List[Tree]) {
- def >>(other: Rebindings) = {
- if (other eq NoRebindings) this
- else if (this eq NoRebindings) other
- else {
- assert((lhs.toSet ++ other.lhs.toSet).size == lhs.length + other.lhs.length, "no double assignments")
- new Rebindings(this.lhs ++ other.lhs, this.rhs ++ other.rhs)
- }
- }
-
- def emitValDefs: List[ValDef] = {
- Collections.map2(lhs, rhs)((symbol, tree) => ValDef(symbol.asTerm, tree.ensureConforms(symbol.info)))
+ class Rebindings(val lhs: List[Symbol], val rhs: List[Tree]) {
+ def >>(other: Rebindings) = {
+ if (other eq NoRebindings) this
+ else if (this eq NoRebindings) other
+ else {
+ assert((lhs.toSet ++ other.lhs.toSet).size == lhs.length + other.lhs.length, "no double assignments")
+ new Rebindings(this.lhs ++ other.lhs, this.rhs ++ other.rhs)
}
}
- object NoRebindings extends Rebindings(Nil, Nil)
+ def emitValDefs: List[ValDef] = {
+ Collections.map2(lhs, rhs)((symbol, tree) => ValDef(symbol.asTerm, tree.ensureConforms(symbol.info)))
+ }
+ }
+ object NoRebindings extends Rebindings(Nil, Nil)
trait OptimizedCodegen extends CodegenCore {
override def codegen: AbsCodegen = optimizedCodegen
@@ -192,12 +190,13 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
//val matchRes = ctx.newSymbol(NoSymbol, ctx.freshName("matchRes").toTermName, Flags.Synthetic | Flags.Param | Flags.Label | Flags.Method, restpe /*withoutAnnotations*/)
//NoSymbol.newValueParameter(newTermName("x"), NoPosition, newFlags = SYNTHETIC) setInfo restpe.withoutAnnotations
- val caseSyms = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) => newSynthCaseLabel(ctx.freshName("case"), MethodType(Nil, restpe), curOwner)).tail
+
+ val caseSyms: List[TermSymbol] = cases.scanLeft(ctx.owner.asTerm)((curOwner, nextTree) => newSynthCaseLabel(ctx.freshName("case"), MethodType(Nil, restpe), curOwner)).tail
// must compute catchAll after caseLabels (side-effects nextCase)
// catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
// if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd
- val catchAllDef = matchFailGen.map { _(scrutSym)}
+ val catchAllDef = matchFailGen.map { _(scrutSym) }
.getOrElse(Throw(New(defn.MatchErrorType, List(ref(scrutSym)))))
val matchFail = newSynthCaseLabel(ctx.freshName("matchFail"), MethodType(Nil, restpe))
@@ -207,14 +206,13 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val caseDefs = (cases zip caseSyms zip nextCases).foldRight[Tree](catchAllDefBody) {
// dotty deviation
//case (((mkCase, sym), nextCase), acc) =>
- (x:(((Casegen => Tree), TermSymbol), Tree), acc: Tree) => x match {
-
- case ((mkCase, sym), nextCase) =>
- val body = mkCase(new OptimizedCasegen(nextCase)).ensureConforms(restpe)
-
- DefDef(sym, _ => Block(List(acc), body))
- }}
+ (x: (((Casegen => Tree), TermSymbol), Tree), acc: Tree) => x match {
+ case ((mkCase, sym), nextCase) =>
+ val body = mkCase(new OptimizedCasegen(nextCase)).ensureConforms(restpe)
+ DefDef(sym, _ => Block(List(acc), body))
+ }
+ }
// scrutSym == NoSymbol when generating an alternatives matcher
// val scrutDef = scrutSym.fold(List[Tree]())(ValDef(_, scrut) :: Nil) // for alternatives
@@ -255,9 +253,13 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
)
} else {
assert(defn.isProductSubType(prev.tpe))
- Block(
- List(ValDef(b.asTerm, prev)),
- next //Substitution(b, ref(prevSym))(next)
+ val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
+ ifThenElseZero(
+ nullCheck,
+ Block(
+ List(ValDef(b.asTerm, prev)),
+ next //Substitution(b, ref(prevSym))(next)
+ )
)
}
}
@@ -285,7 +287,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
next
))
}
-
}
}
final case class Suppression(exhaustive: Boolean, unreachable: Boolean)
@@ -642,7 +643,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val checkedLength: Option[Int],
val prevBinder: Symbol,
val ignoredSubPatBinders: Set[Symbol]
- ) extends FunTreeMaker with PreserveSubPatBinders {
+ ) extends FunTreeMaker with PreserveSubPatBinders {
def extraStoredBinders: Set[Symbol] = Set()
@@ -664,9 +665,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
bindSubPats(next)
}
- if (extractorReturnsBoolean) casegen.flatMapCond(extractor, unitLiteral, nextBinder, condAndNext)
- else casegen.flatMap(extractor, nextBinder, condAndNext) // getType?
-
+ if (extractorReturnsBoolean) casegen.flatMapCond(extractor, unitLiteral, nextBinder, condAndNext)
+ else casegen.flatMap(extractor, nextBinder, condAndNext) // getType?
}
override def toString = "X" + ((extractor, nextBinder.name))
@@ -700,7 +700,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val mutableBinders: List[Symbol],
binderKnownNonNull: Boolean,
val ignoredSubPatBinders: Set[Symbol]
- ) extends FunTreeMaker with PreserveSubPatBinders {
+ ) extends FunTreeMaker with PreserveSubPatBinders {
val nextBinder = prevBinder // just passing through
@@ -709,6 +709,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
val nullCheck: Tree = ref(prevBinder).select(defn.Object_ne).appliedTo(Literal(Constant(null)))
+
val cond: Option[Tree] =
if (binderKnownNonNull) extraCond
else extraCond.map(nullCheck.select(defn.Boolean_&&).appliedTo).orElse(Some(nullCheck))
@@ -782,9 +783,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val expectedClass = expectedTp.dealias.classSymbol.asClass
val test = codegen._asInstanceOf(testedBinder, expectedTp)
val outerAccessorTested = ctx.atPhase(ctx.explicitOuterPhase.next) { implicit ctx =>
- ExplicitOuter.ensureOuterAccessors(expectedClass)
- test.select(ExplicitOuter.outerAccessor(expectedClass)).select(defn.Object_eq).appliedTo(expectedOuter)
- }
+ ExplicitOuter.ensureOuterAccessors(expectedClass)
+ test.select(ExplicitOuter.outerAccessor(expectedClass)).select(defn.Object_eq).appliedTo(expectedOuter)
+ }
outerAccessorTested
}
}
@@ -848,7 +849,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val nextBinder = afterTest.asTerm
- def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
+ def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol): Boolean = {
// See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
// generates an outer test based on `patType.prefix` with automatically dealises.
patType.dealias match {
@@ -866,7 +867,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val np = expectedTp.normalizedPrefix
val ts = np.termSymbol
(ts ne NoSymbol) && needsOuterTest(expectedTp, testedBinder.info, ctx.owner)
-
}
// the logic to generate the run-time test that follows from the fact that
@@ -906,7 +906,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
if (isExpectedReferenceType) mkNullTest
else mkTypeTest
)
- )
+ )
// true when called to type-test the argument to an extractor
// don't do any fancy equality checking, just test the type
@@ -920,7 +920,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
and(mkEqualsTest(ref(tref.symbol.companionModule)), mkTypeTest) // must use == to support e.g. List() == Nil
case ConstantType(Constant(null)) if isAnyRef => mkEqTest(expTp(Literal(Constant(null))))
case ConstantType(const) => mkEqualsTest(expTp(Literal(const)))
- case t:SingletonType => mkEqTest(singleton(expectedTp)) // SI-4577, SI-4897
+ case t: SingletonType => mkEqTest(singleton(expectedTp)) // SI-4577, SI-4897
//case ThisType(sym) => mkEqTest(expTp(This(sym)))
case _ => mkDefault
}
@@ -1050,7 +1050,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val (cases, toHoist) = optimizeCases(scrutSym, casesRebindingPropagated, pt)
-
val matchRes = codegen.matcher(scrut, scrutSym, pt)(cases.map(x => combineExtractors(x) _), synthCatchAll)
if (toHoist isEmpty) matchRes else Block(toHoist, matchRes)
@@ -1092,7 +1091,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
def unapply(pat: Tree): Boolean = pat match {
case Typed(_, arg) if arg.tpe.isRepeatedParam => true
case Bind(nme.WILDCARD, WildcardPattern()) => true // don't skip when binding an interesting symbol!
- case t if (tpd.isWildcardArg(t)) => true
+ case t if (tpd.isWildcardArg(t)) => true
case x: Ident => isVarPattern(x)
case Alternative(ps) => ps forall unapply
case EmptyTree => true
@@ -1113,7 +1112,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
object SymbolBound {
def unapply(tree: Tree): Option[(Symbol, Tree)] = tree match {
case Bind(_, expr) if tree.symbol.exists => Some(tree.symbol -> expr)
- case _ => None
+ case _ => None
}
}
@@ -1126,13 +1125,13 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
final case class BoundTree(binder: Symbol, tree: Tree) {
private lazy val extractor = ExtractorCall(tree, binder)
- def pos = tree.pos
- def tpe = binder.info.widenDealias
- def pt = unbound match {
- // case Star(tpt) => this glbWith seqType(tpt.tpe) dd todo:
- case TypeBound(tpe) => tpe
- case tree => tree.tpe
- }
+ def pos = tree.pos
+ def tpe = binder.info.widenDealias
+ def pt = unbound match {
+ // case Star(tpt) => this glbWith seqType(tpt.tpe) dd todo:
+ case TypeBound(tpe) => tpe
+ case tree => tree.tpe
+ }
def glbWith(other: Type) = ctx.typeComparer.glb(tpe :: other :: Nil)// .normalize
@@ -1200,7 +1199,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
// Statically conforms to paramType
if (tpe <:< paramType) treeMaker(binder, false, pos, tpe) :: Nil
else typeTest :: extraction :: Nil
- )
+ )
step(makers: _*)(extractor.subBoundTrees: _*)
}
@@ -1219,7 +1218,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
// [7] symbol-less bind patterns - this happens in certain ill-formed programs, there'll be an error later
// don't fail here though (or should we?)
def nextStep(): TranslationStep = tree match {
- case _: UnApply | _: Apply| Typed(_: UnApply | _: Apply, _) => extractorStep()
+ case _: UnApply | _: Apply | Typed(_: UnApply | _: Apply, _) => extractorStep()
case SymbolAndTypeBound(sym, tpe) => typeTestStep(sym, tpe)
case TypeBound(tpe) => typeTestStep(binder, tpe)
case SymbolBound(sym, expr) => bindingStep(sym, expr)
@@ -1230,7 +1229,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
}
def translate(): List[TreeMaker] = nextStep() merge (_.translate())
-
private def concreteType = tpe.bounds.hi
private def unbound = unbind(tree)
private def tpe_s = if (pt <:< concreteType) "" + pt else s"$pt (binder: $tpe)"
@@ -1260,7 +1258,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
*
* NOTE: the resulting tree is not type checked, nor are nested pattern matches transformed
* thus, you must typecheck the result (and that will in turn translate nested matches)
- * this could probably optimized... (but note that the matchStrategy must be solved for each nested patternmatch)
+ * this could probably be optimized... (but note that the matchStrategy must be solved for each nested patternmatch)
*/
def translateMatch(match_ : Match): Tree = {
val Match(sel, cases) = match_
@@ -1271,7 +1269,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val (nonSyntheticCases, defaultOverride) = cases match {
case init :+ last if isSyntheticDefaultCase(last) => (init, Some(((scrut: Symbol) => last.body)))
- case _ => (cases, None)
+ case _ => (cases, None)
}
@@ -1331,7 +1329,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
* a function that will take care of binding and substitution of the next ast (to the right).
*
*/
- def translateCase(scrutSym: Symbol, pt: Type)(caseDef: CaseDef) = {
+ def translateCase(scrutSym: Symbol, pt: Type)(caseDef: CaseDef): List[TreeMaker] = {
val CaseDef(pattern, guard, body) = caseDef
translatePattern(BoundTree(scrutSym, pattern)) ++ translateGuard(guard) :+ translateBody(body, pt)
}
@@ -1400,7 +1398,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
object ExtractorCall {
// TODO: check unargs == args
- def apply(tree: Tree, binder: Symbol): ExtractorCall = {
+ def apply(tree: Tree, binder: Symbol): ExtractorCall = {
tree match {
case UnApply(unfun, implicits, args) =>
val castedBinder = ref(binder).ensureConforms(tree.tpe)
@@ -1479,8 +1477,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
productSelectors(binder.info)
else binder.caseAccessors
val res =
- if (accessors.isDefinedAt(i - 1)) ref(binder).select(accessors(i - 1).name)
- else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN
+ if (accessors.isDefinedAt(i - 1)) ref(binder).select(accessors(i - 1).name)
+ else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN
val rsym = res.symbol // just for debugging
res
}
@@ -1492,7 +1490,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
if (!aligner.isStar) Nil
else if (expectedLength == 0) seqTree(binder) :: Nil
else genDrop(binder, expectedLength)
- )
+ )
// this error-condition has already been checked by checkStarPatOK:
// if (isSeq) assert(firstIndexingBinder + nbIndexingIndices + (if (lastIsStar) 1 else 0) == totalArity, "(resultInMonad, ts, subPatTypes, subPats)= " +(resultInMonad, ts, subPatTypes, subPats))
@@ -1503,7 +1501,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
( productElemsToN(binder, firstIndexingBinder)
++ genTake(binder, expectedLength)
++ lastTrees
- ).toList
+ ).toList
}
// the trees that select the subpatterns on the extractor's result, referenced by `binder`
@@ -1511,7 +1509,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
protected def subPatRefs(binder: Symbol): List[Tree] = {
val refs = if (totalArity > 0 && isSeq) subPatRefsSeq(binder)
else if (binder.info.member(nme._1).exists && !isSeq) productElemsToN(binder, totalArity)
- else ref(binder):: Nil
+ else ref(binder) :: Nil
refs
}
@@ -1601,7 +1599,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
// can't simplify this when subPatBinders.isEmpty, since UnitTpe is definitely
// wrong when isSeq, and resultInMonad should always be correct since it comes
// directly from the extractor's result type
- val binder = freshSym(pos, resultInMonad)
+ val binder = freshSym(pos, resultInMonad)
val spb = subPatBinders
ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)(
spb,
@@ -1819,6 +1817,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
def expectedTypes = typedPatterns map (_.tpe)
def unexpandedFormals = extractor.varargsTypes
}
+
trait ScalacPatternExpander extends PatternExpander[Tree, Type] {
def NoPattern = EmptyTree
def NoType = core.Types.NoType
@@ -1836,7 +1835,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
( typeOfMemberNamedHead(seq)
orElse typeOfMemberNamedApply(seq)
orElse seq.elemType
- )
+ )
}
def newExtractor(whole: Type, fixed: List[Type], repeated: Repeated): Extractor = {
ctx.log(s"newExtractor($whole, $fixed, $repeated")
@@ -1863,7 +1862,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
method.paramTypess.head match {
case init :+ last if last.isRepeatedParam => newExtractor(whole, init, repeatedFromVarargs(last))
- case tps => newExtractor(whole, tps, NoRepeated)
+ case tps => newExtractor(whole, tps, NoRepeated)
}
}
@@ -1874,15 +1873,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
* Unfortunately the MethodType does not carry the information of whether
* it was unapplySeq, so we have to funnel that information in separately.
*/
- def unapplyMethodTypes(tree:Tree, fun: Tree, args:List[Tree], resultType:Type, isSeq: Boolean): Extractor = {
+ def unapplyMethodTypes(tree: Tree, fun: Tree, args: List[Tree], resultType: Type, isSeq: Boolean): Extractor = {
_id = _id + 1
- val whole = tree.tpe// see scaladoc for Trees.Unapply
+ val whole = tree.tpe // see scaladoc for Trees.Unapply
// fun.tpe.widen.paramTypess.headOption.flatMap(_.headOption).getOrElse(NoType)//firstParamType(method)
val resultOfGet = extractorMemberType(resultType, nme.get)
- //println(s"${_id}unapplyArgs(${result.widen}")
- val expanded:List[Type] = /*(
+ val expanded: List[Type] = /*(
if (result =:= defn.BooleanType) Nil
else if (defn.isProductSubType(result)) productSelectorTypes(result)
else if (result.classSymbol is Flags.CaseClass) result.decls.filter(x => x.is(Flags.CaseAccessor) && x.is(Flags.Method)).map(_.info).toList
@@ -1917,7 +1915,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
def offering = extractor.offeringString
def symString = tree.symbol.showLocated
def offerString = if (extractor.isErroneous) "" else s" offering $offering"
- def arityExpected = ( if (extractor.hasSeq) "at least " else "" ) + prodArity
+ def arityExpected = (if (extractor.hasSeq) "at least " else "") + prodArity
def err(msg: String) = ctx.error(msg, tree.pos)
def warn(msg: String) = ctx.warning(msg, tree.pos)
@@ -1944,10 +1942,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
}
}
- def apply(tree:Tree, sel: Tree, args: List[Tree], resultType: Type): Aligned = {
+ def apply(tree: Tree, sel: Tree, args: List[Tree], resultType: Type): Aligned = {
val fn = sel match {
case Applied(fn) => fn
- case _ => sel
+ case _ => sel
}
val patterns = newPatterns(args)
val isSeq = sel.symbol.name == nme.unapplySeq
@@ -1977,8 +1975,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
}
def apply(tree: Tree, resultType: Type): Aligned = tree match {
- case Typed(tree, _) => apply(tree, resultType)
- case Apply(fn, args) => apply(tree, fn, args, resultType)
+ case Typed(tree, _) => apply(tree, resultType)
+ case Apply(fn, args) => apply(tree, fn, args, resultType)
case UnApply(fn, implicits, args) => apply(tree, fn, args, resultType)
}
}
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index fd22a0ad9..6af225035 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -13,7 +13,7 @@ import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTrans
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import util.Positions._
import Decorators._
-import config.Printers._
+import config.Printers.typr
import Symbols._, TypeUtils._
/** A macro transform that runs immediately after typer and that performs the following functions:
@@ -93,7 +93,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
*
* should behave differently.
*
- * O1.x should have the same effect as { println("43"; 42 }
+ * O1.x should have the same effect as { println("43"); 42 }
*
* whereas
*
@@ -103,10 +103,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
* purity of the prefix unless the selection goes to an inline val.
*/
private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
- case tree: TypeTree => tree
- case TypeApply(fn, args) =>
- Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])
- tree
+ case _: TypeTree | _: TypeApply => tree
case _ =>
if (tree.isType) {
Checking.typeChecker.traverse(tree)
@@ -265,8 +262,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
case tree: New if !inJavaAnnot && !parentNews.contains(tree) =>
Checking.checkInstantiable(tree.tpe, tree.pos)
super.transform(tree)
- case tree @ Annotated(annot, annotated) =>
- cpy.Annotated(tree)(transformAnnot(annot), transform(annotated))
+ case tree @ Annotated(annotated, annot) =>
+ cpy.Annotated(tree)(transform(annotated), transformAnnot(annot))
case tree: TypeTree =>
tree.withType(
tree.tpe match {
diff --git a/src/dotty/tools/dotc/transform/SelectStatic.scala b/src/dotty/tools/dotc/transform/SelectStatic.scala
index 504a66c2f..5d60bb984 100644
--- a/src/dotty/tools/dotc/transform/SelectStatic.scala
+++ b/src/dotty/tools/dotc/transform/SelectStatic.scala
@@ -19,25 +19,21 @@ class SelectStatic extends MiniPhaseTransform with IdentityDenotTransformer { th
import ast.tpd._
override def phaseName: String = "selectStatic"
- private val isPackage = FlagConjunction(PackageCreationFlags.bits)
override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
val sym = tree.symbol
- val r1 =
- if (!sym.is(isPackage) && !sym.maybeOwner.is(isPackage) &&
- (
- ((sym is Flags.Module) && sym.maybeOwner.isStaticOwner) ||
- (sym is Flags.JavaStatic) ||
- (sym.maybeOwner is Flags.ImplClass) ||
- sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot)
- )
- )
- if (!tree.qualifier.symbol.is(JavaModule) && !tree.qualifier.isType)
- Block(List(tree.qualifier), ref(sym))
- else tree
+ def isStaticMember =
+ (sym is Flags.Module) && sym.initial.maybeOwner.initial.isStaticOwner ||
+ (sym is Flags.JavaStatic) ||
+ (sym.maybeOwner is Flags.ImplClass) ||
+ sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot)
+ val isStaticRef = !sym.is(Package) && !sym.maybeOwner.is(Package) && isStaticMember
+ val tree1 =
+ if (isStaticRef && !tree.qualifier.symbol.is(JavaModule) && !tree.qualifier.isType)
+ Block(List(tree.qualifier), ref(sym))
else tree
- normalize(r1)
+ normalize(tree1)
}
private def normalize(t: Tree)(implicit ctx: Context) = t match {
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index 18e3a6c8a..e7342aec9 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -164,7 +164,6 @@ class TreeChecker extends Phase with SymTransformer {
tree match {
case t: MemberDef =>
if (t.name ne sym.name) ctx.warning(s"symbol ${sym.fullName} name doesn't correspond to AST: ${t}")
- if (sym.flags != t.mods.flags) ctx.warning(s"symbol ${sym.fullName} flags ${sym.flags} doesn't match AST definition flags ${t.mods.flags}")
// todo: compare trees inside annotations
case _ =>
}
@@ -200,7 +199,6 @@ class TreeChecker extends Phase with SymTransformer {
def checkIdentNotJavaClass(tree: Tree)(implicit ctx: Context): Unit = tree match {
// case tree: untpd.Ident =>
// case tree: untpd.Select =>
- // case tree: untpd.SelectFromTypeTree =>
// case tree: untpd.Bind =>
case vd : ValDef =>
assertIdentNotJavaClass(vd.forceIfLazy)
@@ -213,9 +211,6 @@ class TreeChecker extends Phase with SymTransformer {
// case tree: untpd.This =>
// case tree: untpd.Literal =>
// case tree: untpd.New =>
- case Pair(left, right) =>
- assertIdentNotJavaClass(left)
- assertIdentNotJavaClass(right)
case Typed(expr, _) =>
assertIdentNotJavaClass(expr)
case NamedArg(_, arg) =>
@@ -252,7 +247,7 @@ class TreeChecker extends Phase with SymTransformer {
// case tree: TypeBoundsTree =>
// case tree: Alternative =>
// case tree: PackageDef =>
- case Annotated(_, arg) =>
+ case Annotated(arg, _) =>
assertIdentNotJavaClass(arg)
case _ =>
}
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index 89ae927b7..05961508a 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -70,7 +70,6 @@ object TreeTransforms {
def prepareForApply(tree: Apply)(implicit ctx: Context) = this
def prepareForTypeApply(tree: TypeApply)(implicit ctx: Context) = this
def prepareForLiteral(tree: Literal)(implicit ctx: Context) = this
- def prepareForPair(tree: Pair)(implicit ctx: Context) = this
def prepareForNew(tree: New)(implicit ctx: Context) = this
def prepareForTyped(tree: Typed)(implicit ctx: Context) = this
def prepareForAssign(tree: Assign)(implicit ctx: Context) = this
@@ -83,7 +82,6 @@ object TreeTransforms {
def prepareForTry(tree: Try)(implicit ctx: Context) = this
def prepareForSeqLiteral(tree: SeqLiteral)(implicit ctx: Context) = this
def prepareForTypeTree(tree: TypeTree)(implicit ctx: Context) = this
- def prepareForSelectFromTypeTree(tree: SelectFromTypeTree)(implicit ctx: Context) = this
def prepareForBind(tree: Bind)(implicit ctx: Context) = this
def prepareForAlternative(tree: Alternative)(implicit ctx: Context) = this
def prepareForTypeDef(tree: TypeDef)(implicit ctx: Context) = this
@@ -104,7 +102,6 @@ object TreeTransforms {
def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo): Tree = tree
- def transformPair(tree: Pair)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = tree
@@ -116,7 +113,6 @@ object TreeTransforms {
def transformTry(tree: Try)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = tree
- def transformSelectFromTypeTree(tree: SelectFromTypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformBind(tree: Bind)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformAlternative(tree: Alternative)(implicit ctx: Context, info: TransformerInfo): Tree = tree
def transformUnApply(tree: UnApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree
@@ -267,7 +263,6 @@ object TreeTransforms {
nxPrepTypeApply = index(transformations, "prepareForTypeApply")
nxPrepLiteral = index(transformations, "prepareForLiteral")
nxPrepNew = index(transformations, "prepareForNew")
- nxPrepPair = index(transformations, "prepareForPair")
nxPrepTyped = index(transformations, "prepareForTyped")
nxPrepAssign = index(transformations, "prepareForAssign")
nxPrepBlock = index(transformations, "prepareForBlock")
@@ -279,7 +274,6 @@ object TreeTransforms {
nxPrepTry = index(transformations, "prepareForTry")
nxPrepSeqLiteral = index(transformations, "prepareForSeqLiteral")
nxPrepTypeTree = index(transformations, "prepareForTypeTree")
- nxPrepSelectFromTypeTree = index(transformations, "prepareForSelectFromTypeTree")
nxPrepBind = index(transformations, "prepareForBind")
nxPrepAlternative = index(transformations, "prepareForAlternative")
nxPrepUnApply = index(transformations, "prepareForUnApply")
@@ -299,7 +293,6 @@ object TreeTransforms {
nxTransTypeApply = index(transformations, "transformTypeApply")
nxTransLiteral = index(transformations, "transformLiteral")
nxTransNew = index(transformations, "transformNew")
- nxTransPair = index(transformations, "transformPair")
nxTransTyped = index(transformations, "transformTyped")
nxTransAssign = index(transformations, "transformAssign")
nxTransBlock = index(transformations, "transformBlock")
@@ -311,7 +304,6 @@ object TreeTransforms {
nxTransTry = index(transformations, "transformTry")
nxTransSeqLiteral = index(transformations, "transformSeqLiteral")
nxTransTypeTree = index(transformations, "transformTypeTree")
- nxTransSelectFromTypeTree = index(transformations, "transformSelectFromTypeTree")
nxTransBind = index(transformations, "transformBind")
nxTransAlternative = index(transformations, "transformAlternative")
nxTransUnApply = index(transformations, "transformUnApply")
@@ -341,7 +333,6 @@ object TreeTransforms {
nxPrepTypeApply = indexUpdate(prev.nxPrepTypeApply, changedTransformationClass, transformationIndex, "prepareForTypeApply", copy)
nxPrepLiteral = indexUpdate(prev.nxPrepLiteral, changedTransformationClass, transformationIndex, "prepareForLiteral", copy)
nxPrepNew = indexUpdate(prev.nxPrepNew, changedTransformationClass, transformationIndex, "prepareForNew", copy)
- nxPrepPair = indexUpdate(prev.nxPrepPair, changedTransformationClass, transformationIndex, "prepareForPair", copy)
nxPrepTyped = indexUpdate(prev.nxPrepTyped, changedTransformationClass, transformationIndex, "prepareForTyped", copy)
nxPrepAssign = indexUpdate(prev.nxPrepAssign, changedTransformationClass, transformationIndex, "prepareForAssign", copy)
nxPrepBlock = indexUpdate(prev.nxPrepBlock, changedTransformationClass, transformationIndex, "prepareForBlock", copy)
@@ -353,7 +344,6 @@ object TreeTransforms {
nxPrepTry = indexUpdate(prev.nxPrepTry, changedTransformationClass, transformationIndex, "prepareForTry", copy)
nxPrepSeqLiteral = indexUpdate(prev.nxPrepSeqLiteral, changedTransformationClass, transformationIndex, "prepareForSeqLiteral", copy)
nxPrepTypeTree = indexUpdate(prev.nxPrepTypeTree, changedTransformationClass, transformationIndex, "prepareForTypeTree", copy)
- nxPrepSelectFromTypeTree = indexUpdate(prev.nxPrepSelectFromTypeTree, changedTransformationClass, transformationIndex, "prepareForSelectFromTypeTree", copy)
nxPrepBind = indexUpdate(prev.nxPrepBind, changedTransformationClass, transformationIndex, "prepareForBind", copy)
nxPrepAlternative = indexUpdate(prev.nxPrepAlternative, changedTransformationClass, transformationIndex, "prepareForAlternative", copy)
nxPrepUnApply = indexUpdate(prev.nxPrepUnApply, changedTransformationClass, transformationIndex, "prepareForUnApply", copy)
@@ -372,7 +362,6 @@ object TreeTransforms {
nxTransTypeApply = indexUpdate(prev.nxTransTypeApply, changedTransformationClass, transformationIndex, "transformTypeApply", copy)
nxTransLiteral = indexUpdate(prev.nxTransLiteral, changedTransformationClass, transformationIndex, "transformLiteral", copy)
nxTransNew = indexUpdate(prev.nxTransNew, changedTransformationClass, transformationIndex, "transformNew", copy)
- nxTransPair = indexUpdate(prev.nxTransPair, changedTransformationClass, transformationIndex, "transformPair", copy)
nxTransTyped = indexUpdate(prev.nxTransTyped, changedTransformationClass, transformationIndex, "transformTyped", copy)
nxTransAssign = indexUpdate(prev.nxTransAssign, changedTransformationClass, transformationIndex, "transformAssign", copy)
nxTransBlock = indexUpdate(prev.nxTransBlock, changedTransformationClass, transformationIndex, "transformBlock", copy)
@@ -384,7 +373,6 @@ object TreeTransforms {
nxTransTry = indexUpdate(prev.nxTransTry, changedTransformationClass, transformationIndex, "transformTry", copy)
nxTransSeqLiteral = indexUpdate(prev.nxTransSeqLiteral, changedTransformationClass, transformationIndex, "transformSeqLiteral", copy)
nxTransTypeTree = indexUpdate(prev.nxTransTypeTree, changedTransformationClass, transformationIndex, "transformTypeTree", copy)
- nxTransSelectFromTypeTree = indexUpdate(prev.nxTransSelectFromTypeTree, changedTransformationClass, transformationIndex, "transformSelectFromTypeTree", copy)
nxTransBind = indexUpdate(prev.nxTransBind, changedTransformationClass, transformationIndex, "transformBind", copy)
nxTransAlternative = indexUpdate(prev.nxTransAlternative, changedTransformationClass, transformationIndex, "transformAlternative", copy)
nxTransUnApply = indexUpdate(prev.nxTransUnApply, changedTransformationClass, transformationIndex, "transformUnApply", copy)
@@ -409,7 +397,6 @@ object TreeTransforms {
var nxPrepTypeApply: Array[Int] = _
var nxPrepLiteral: Array[Int] = _
var nxPrepNew: Array[Int] = _
- var nxPrepPair: Array[Int] = _
var nxPrepTyped: Array[Int] = _
var nxPrepAssign: Array[Int] = _
var nxPrepBlock: Array[Int] = _
@@ -421,7 +408,6 @@ object TreeTransforms {
var nxPrepTry: Array[Int] = _
var nxPrepSeqLiteral: Array[Int] = _
var nxPrepTypeTree: Array[Int] = _
- var nxPrepSelectFromTypeTree: Array[Int] = _
var nxPrepBind: Array[Int] = _
var nxPrepAlternative: Array[Int] = _
var nxPrepUnApply: Array[Int] = _
@@ -441,7 +427,6 @@ object TreeTransforms {
var nxTransTypeApply: Array[Int] = _
var nxTransLiteral: Array[Int] = _
var nxTransNew: Array[Int] = _
- var nxTransPair: Array[Int] = _
var nxTransTyped: Array[Int] = _
var nxTransAssign: Array[Int] = _
var nxTransBlock: Array[Int] = _
@@ -453,7 +438,6 @@ object TreeTransforms {
var nxTransTry: Array[Int] = _
var nxTransSeqLiteral: Array[Int] = _
var nxTransTypeTree: Array[Int] = _
- var nxTransSelectFromTypeTree: Array[Int] = _
var nxTransBind: Array[Int] = _
var nxTransAlternative: Array[Int] = _
var nxTransUnApply: Array[Int] = _
@@ -520,7 +504,6 @@ object TreeTransforms {
val prepForApply: Mutator[Apply] = (trans, tree, ctx) => trans.prepareForApply(tree)(ctx)
val prepForTypeApply: Mutator[TypeApply] = (trans, tree, ctx) => trans.prepareForTypeApply(tree)(ctx)
val prepForNew: Mutator[New] = (trans, tree, ctx) => trans.prepareForNew(tree)(ctx)
- val prepForPair: Mutator[Pair] = (trans, tree, ctx) => trans.prepareForPair(tree)(ctx)
val prepForTyped: Mutator[Typed] = (trans, tree, ctx) => trans.prepareForTyped(tree)(ctx)
val prepForAssign: Mutator[Assign] = (trans, tree, ctx) => trans.prepareForAssign(tree)(ctx)
val prepForLiteral: Mutator[Literal] = (trans, tree, ctx) => trans.prepareForLiteral(tree)(ctx)
@@ -533,7 +516,6 @@ object TreeTransforms {
val prepForTry: Mutator[Try] = (trans, tree, ctx) => trans.prepareForTry(tree)(ctx)
val prepForSeqLiteral: Mutator[SeqLiteral] = (trans, tree, ctx) => trans.prepareForSeqLiteral(tree)(ctx)
val prepForTypeTree: Mutator[TypeTree] = (trans, tree, ctx) => trans.prepareForTypeTree(tree)(ctx)
- val prepForSelectFromTypeTree: Mutator[SelectFromTypeTree] = (trans, tree, ctx) => trans.prepareForSelectFromTypeTree(tree)(ctx)
val prepForBind: Mutator[Bind] = (trans, tree, ctx) => trans.prepareForBind(tree)(ctx)
val prepForAlternative: Mutator[Alternative] = (trans, tree, ctx) => trans.prepareForAlternative(tree)(ctx)
val prepForUnApply: Mutator[UnApply] = (trans, tree, ctx) => trans.prepareForUnApply(tree)(ctx)
@@ -638,17 +620,6 @@ object TreeTransforms {
}
@tailrec
- final private[TreeTransforms] def goPair(tree: Pair, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = {
- if (cur < info.transformers.length) {
- val trans = info.transformers(cur)
- trans.transformPair(tree)(ctx.withPhase(trans.treeTransformPhase), info) match {
- case t: Pair => goPair(t, info.nx.nxTransPair(cur + 1))
- case t => transformSingle(t, cur + 1)
- }
- } else tree
- }
-
- @tailrec
final private[TreeTransforms] def goTyped(tree: Typed, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = {
if (cur < info.transformers.length) {
val trans = info.transformers(cur)
@@ -781,17 +752,6 @@ object TreeTransforms {
}
@tailrec
- final private[TreeTransforms] def goSelectFromTypeTree(tree: SelectFromTypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = {
- if (cur < info.transformers.length) {
- val trans = info.transformers(cur)
- trans.transformSelectFromTypeTree(tree)(ctx.withPhase(trans.treeTransformPhase), info) match {
- case t: SelectFromTypeTree => goSelectFromTypeTree(t, info.nx.nxTransSelectFromTypeTree(cur + 1))
- case t => transformSingle(t, cur + 1)
- }
- } else tree
- }
-
- @tailrec
final private[TreeTransforms] def goBind(tree: Bind, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = {
if (cur < info.transformers.length) {
val trans = info.transformers(cur)
@@ -900,8 +860,6 @@ object TreeTransforms {
tree match {
case tree: Ident => goIdent(tree, info.nx.nxTransIdent(cur))
case tree: Select => goSelect(tree, info.nx.nxTransSelect(cur))
- case tree: SelectFromTypeTree =>
- goSelectFromTypeTree(tree, info.nx.nxTransSelectFromTypeTree(cur))
case tree: Bind => goBind(tree, cur)
case tree: ValDef if !tree.isEmpty => goValDef(tree, info.nx.nxTransValDef(cur))
case tree: DefDef => goDefDef(tree, info.nx.nxTransDefDef(cur))
@@ -917,7 +875,6 @@ object TreeTransforms {
case tree: TypeApply => goTypeApply(tree, info.nx.nxTransTypeApply(cur))
case tree: Literal => goLiteral(tree, info.nx.nxTransLiteral(cur))
case tree: New => goNew(tree, info.nx.nxTransNew(cur))
- case tree: Pair => goPair(tree, info.nx.nxTransPair(cur))
case tree: Typed => goTyped(tree, info.nx.nxTransTyped(cur))
case tree: Assign => goAssign(tree, info.nx.nxTransAssign(cur))
case tree: Block => goBlock(tree, info.nx.nxTransBlock(cur))
@@ -967,13 +924,6 @@ object TreeTransforms {
val qual = transform(tree.qualifier, mutatedInfo, cur)
goSelect(cpy.Select(tree)(qual, tree.name), mutatedInfo.nx.nxTransSelect(cur))
}
- case tree: SelectFromTypeTree =>
- implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForSelectFromTypeTree, info.nx.nxPrepSelectFromTypeTree, tree, cur)
- if (mutatedInfo eq null) tree
- else {
- val qual = transform(tree.qualifier, mutatedInfo, cur)
- goSelectFromTypeTree(cpy.SelectFromTypeTree(tree)(qual, tree.name), mutatedInfo.nx.nxTransSelectFromTypeTree(cur))
- }
case tree: Bind =>
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForBind, info.nx.nxPrepBind, tree, cur)
if (mutatedInfo eq null) tree
@@ -1052,14 +1002,6 @@ object TreeTransforms {
val tpt = transform(tree.tpt, mutatedInfo, cur)
goNew(cpy.New(tree)(tpt), mutatedInfo.nx.nxTransNew(cur))
}
- case tree: Pair =>
- implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForPair, info.nx.nxPrepPair, tree, cur)
- if (mutatedInfo eq null) tree
- else {
- val left = transform(tree.left, mutatedInfo, cur)
- val right = transform(tree.right, mutatedInfo, cur)
- goPair(cpy.Pair(tree)(left, right), mutatedInfo.nx.nxTransPair(cur))
- }
case tree: Typed =>
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTyped, info.nx.nxPrepTyped, tree, cur)
if (mutatedInfo eq null) tree
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 099105de3..55d9fc990 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -24,14 +24,14 @@ import ProtoTypes._
import EtaExpansion._
import Inferencing._
import collection.mutable
-import config.Printers._
+import config.Printers.{typr, unapp, overload}
import TypeApplications._
import language.implicitConversions
object Applications {
import tpd._
- def extractorMemberType(tp: Type, name: Name, errorPos: Position = NoPosition)(implicit ctx:Context) = {
+ def extractorMemberType(tp: Type, name: Name, errorPos: Position = NoPosition)(implicit ctx: Context) = {
val ref = tp.member(name).suchThat(_.info.isParameterless)
if (ref.isOverloaded)
errorType(i"Overloaded reference to $ref is not allowed in extractor", errorPos)
@@ -41,12 +41,12 @@ object Applications {
ref.info.widenExpr.dealias
}
- def productSelectorTypes(tp: Type, errorPos: Position = NoPosition)(implicit ctx:Context): List[Type] = {
+ def productSelectorTypes(tp: Type, errorPos: Position = NoPosition)(implicit ctx: Context): List[Type] = {
val sels = for (n <- Iterator.from(0)) yield extractorMemberType(tp, nme.selectorName(n), errorPos)
sels.takeWhile(_.exists).toList
}
- def productSelectors(tp: Type)(implicit ctx:Context): List[Symbol] = {
+ def productSelectors(tp: Type)(implicit ctx: Context): List[Symbol] = {
val sels = for (n <- Iterator.from(0)) yield tp.member(nme.selectorName(n)).symbol
sels.takeWhile(_.exists).toList
}
@@ -58,7 +58,7 @@ object Applications {
else tp :: Nil
} else tp :: Nil
- def unapplyArgs(unapplyResult: Type, unapplyFn:Tree, args:List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = {
+ def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = {
def seqSelector = defn.RepeatedParamType.appliedTo(unapplyResult.elemType :: Nil)
def getTp = extractorMemberType(unapplyResult, nme.get, pos)
@@ -591,13 +591,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
fun1.tpe match {
case ErrorType => tree.withType(ErrorType)
- case TryDynamicCallType =>
- tree match {
- case tree @ Apply(Select(qual, name), args) if !isDynamicMethod(name) =>
- typedDynamicApply(qual, name, args, pt)(tree)
- case _ =>
- handleUnexpectedFunType(tree, fun1)
- }
+ case TryDynamicCallType => typedDynamicApply(tree, pt)
case _ =>
tryEither {
implicit ctx => simpleApply(fun1, proto)
@@ -658,7 +652,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
/** Overridden in ReTyper to handle primitive operations that can be generated after erasure */
protected def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree =
- throw new Error(s"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}")
+ throw new Error(i"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}")
def typedNamedArgs(args: List[untpd.Tree])(implicit ctx: Context) =
for (arg @ NamedArg(id, argtpt) <- args) yield {
@@ -679,7 +673,12 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
}
case _ =>
}
- assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
+ def tryDynamicTypeApply(): Tree = typedFn match {
+ case typedFn: Select if !pt.isInstanceOf[FunProto] => typedDynamicSelect(typedFn, typedArgs, pt)
+ case _ => tree.withType(TryDynamicCallType)
+ }
+ if (typedFn.tpe eq TryDynamicCallType) tryDynamicTypeApply()
+ else assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
}
/** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray.
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index d77520c77..415cd5d6a 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -26,7 +26,7 @@ import transform.SymUtils._
import Decorators._
import Uniques._
import ErrorReporting.{err, errorType}
-import config.Printers._
+import config.Printers.typr
import collection.mutable
import SymDenotations.NoCompleter
@@ -37,7 +37,7 @@ object Checking {
* well as for AppliedTypeTree nodes. Also checks that type arguments to
* *-type parameters are fully applied.
*/
- def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context) = {
+ def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context): Unit = {
(args, boundss).zipped.foreach { (arg, bound) =>
if (!bound.isHK && arg.tpe.isHK)
ctx.error(ex"missing type parameter(s) for $arg", arg.pos)
@@ -99,8 +99,6 @@ object Checking {
checkValidIfHKApply(ctx.addMode(Mode.AllowLambdaWildcardApply))
case Select(qual, name) if name.isTypeName =>
checkRealizable(qual.tpe, qual.pos)
- case SelectFromTypeTree(qual, name) if name.isTypeName =>
- checkRealizable(qual.tpe, qual.pos)
case SingletonTypeTree(ref) =>
checkRealizable(ref.tpe, ref.pos)
case _ =>
diff --git a/src/dotty/tools/dotc/typer/Dynamic.scala b/src/dotty/tools/dotc/typer/Dynamic.scala
index aeb3cca8c..b5ace87d3 100644
--- a/src/dotty/tools/dotc/typer/Dynamic.scala
+++ b/src/dotty/tools/dotc/typer/Dynamic.scala
@@ -2,15 +2,14 @@ package dotty.tools
package dotc
package typer
-import dotty.tools.dotc.ast.Trees.NamedArg
-import dotty.tools.dotc.ast.tpd._
+import dotty.tools.dotc.ast.Trees._
+import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.core.Constants.Constant
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Names.Name
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.Types._
-import dotty.tools.dotc.core.Mode
import dotty.tools.dotc.core.Decorators._
object Dynamic {
@@ -28,44 +27,78 @@ object Dynamic {
* The first matching rule of is applied.
*/
trait Dynamic { self: Typer with Applications =>
+ import Dynamic._
+ import tpd._
/** Translate selection that does not typecheck according to the normal rules into a applyDynamic/applyDynamicNamed.
- * foo.bar(baz0, baz1, ...) ~~> foo.applyDynamic(bar)(baz0, baz1, ...)
- * foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
+ * foo.bar(baz0, baz1, ...) ~~> foo.applyDynamic(bar)(baz0, baz1, ...)
+ * foo.bar[T0, ...](baz0, baz1, ...) ~~> foo.applyDynamic[T0, ...](bar)(baz0, baz1, ...)
+ * foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
+ * foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
*/
- def typedDynamicApply(qual: untpd.Tree, name: Name, args: List[untpd.Tree], pt: Type)(original: untpd.Apply)(
- implicit ctx: Context): Tree = {
- def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false }
- val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic
- if (dynName == nme.applyDynamicNamed && untpd.isWildcardStarArgList(args)) {
- ctx.error("applyDynamicNamed does not support passing a vararg parameter", original.pos)
- original.withType(ErrorType)
- } else {
- def namedArgTuple(name: String, arg: untpd.Tree) = untpd.Tuple(List(Literal(Constant(name)), arg))
- def namedArgs = args.map {
- case NamedArg(argName, arg) => namedArgTuple(argName.toString, arg)
- case arg => namedArgTuple("", arg)
+ def typedDynamicApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
+ def typedDynamicApply(qual: untpd.Tree, name: Name, targs: List[untpd.Tree]): Tree = {
+ def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false }
+ val args = tree.args
+ val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic
+ if (dynName == nme.applyDynamicNamed && untpd.isWildcardStarArgList(args)) {
+ ctx.error("applyDynamicNamed does not support passing a vararg parameter", tree.pos)
+ tree.withType(ErrorType)
+ } else {
+ def namedArgTuple(name: String, arg: untpd.Tree) = untpd.Tuple(List(Literal(Constant(name)), arg))
+ def namedArgs = args.map {
+ case NamedArg(argName, arg) => namedArgTuple(argName.toString, arg)
+ case arg => namedArgTuple("", arg)
+ }
+ val args1 = if (dynName == nme.applyDynamic) args else namedArgs
+ typedApply(untpd.Apply(coreDynamic(qual, dynName, name, targs), args1), pt)
}
- val args1 = if (dynName == nme.applyDynamic) args else namedArgs
- typedApply(untpd.Apply(coreDynamic(qual, dynName, name), args1), pt)
+ }
+
+ tree.fun match {
+ case Select(qual, name) if !isDynamicMethod(name) =>
+ typedDynamicApply(qual, name, Nil)
+ case TypeApply(Select(qual, name), targs) if !isDynamicMethod(name) =>
+ typedDynamicApply(qual, name, targs)
+ case TypeApply(fun, targs) =>
+ typedDynamicApply(fun, nme.apply, targs)
+ case fun =>
+ typedDynamicApply(fun, nme.apply, Nil)
}
}
/** Translate selection that does not typecheck according to the normal rules into a selectDynamic.
- * foo.bar ~~> foo.selectDynamic(bar)
+ * foo.bar ~~> foo.selectDynamic(bar)
+ * foo.bar[T0, ...] ~~> foo.selectDynamic[T0, ...](bar)
*
* Note: inner part of translation foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux) is achieved
* through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)].
*/
- def typedDynamicSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree =
- typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name), pt)
+ def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(implicit ctx: Context): Tree =
+ typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, targs), pt)
/** Translate selection that does not typecheck according to the normal rules into a updateDynamic.
* foo.bar = baz ~~> foo.updateDynamic(bar)(baz)
*/
- def typedDynamicAssign(qual: untpd.Tree, name: Name, rhs: untpd.Tree, pt: Type)(implicit ctx: Context): Tree =
- typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name), rhs), pt)
+ def typedDynamicAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = {
+ def typedDynamicAssign(qual: untpd.Tree, name: Name, targs: List[untpd.Tree]): Tree =
+ typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, targs), tree.rhs), pt)
+ tree.lhs match {
+ case Select(qual, name) if !isDynamicMethod(name) =>
+ typedDynamicAssign(qual, name, Nil)
+ case TypeApply(Select(qual, name), targs) if !isDynamicMethod(name) =>
+ typedDynamicAssign(qual, name, targs)
+ case _ =>
+ ctx.error("reassignment to val", tree.pos)
+ tree.withType(ErrorType)
+ }
+ }
- private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name)(implicit ctx: Context): untpd.Apply =
- untpd.Apply(untpd.Select(qual, dynName), Literal(Constant(name.toString)))
+ private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = {
+ val select = untpd.Select(qual, dynName)
+ val selectWithTypes =
+ if (targs.isEmpty) select
+ else untpd.TypeApply(select, targs)
+ untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
+ }
}
diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala
index e193b126a..4ce24b633 100644
--- a/src/dotty/tools/dotc/typer/FrontEnd.scala
+++ b/src/dotty/tools/dotc/typer/FrontEnd.scala
@@ -7,7 +7,8 @@ import Contexts._
import Symbols._
import dotty.tools.dotc.parsing.JavaParsers.JavaParser
import parsing.Parsers.Parser
-import config.Printers._
+import config.Config
+import config.Printers.{typr, default}
import util.Stats._
import scala.util.control.NonFatal
import ast.Trees._
@@ -34,6 +35,8 @@ class FrontEnd extends Phase {
else new Parser(unit.source).parse()
val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr
printer.println("parsed:\n" + unit.untpdTree.show)
+ if (Config.checkPositions)
+ unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
}
def enterSyms(implicit ctx: Context) = monitor("indexing") {
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 0a3307140..ef32e0ba6 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -28,7 +28,7 @@ import Inferencing.fullyDefinedType
import Trees._
import Hashable._
import config.Config
-import config.Printers._
+import config.Printers.{implicits, implicitsDetailed}
import collection.mutable
/** Implicit resolution */
@@ -801,14 +801,15 @@ class SearchHistory(val searchDepth: Int, val seen: Map[ClassSymbol, Int]) {
def updateMap(csyms: List[ClassSymbol], seen: Map[ClassSymbol, Int]): SearchHistory = csyms match {
case csym :: csyms1 =>
seen get csym match {
+ // proto complexity is >= than the last time it was seen → diverge
case Some(prevSize) if size >= prevSize => this
case _ => updateMap(csyms1, seen.updated(csym, size))
}
- case nil =>
- if (csyms.isEmpty) this
- else new SearchHistory(searchDepth + 1, seen)
+ case _ =>
+ new SearchHistory(searchDepth + 1, seen)
}
- updateMap(proto.classSymbols, seen)
+ if (proto.classSymbols.isEmpty) this
+ else updateMap(proto.classSymbols, seen)
}
}
}
diff --git a/src/dotty/tools/dotc/typer/ImportInfo.scala b/src/dotty/tools/dotc/typer/ImportInfo.scala
index 2ca90311f..3aa289181 100644
--- a/src/dotty/tools/dotc/typer/ImportInfo.scala
+++ b/src/dotty/tools/dotc/typer/ImportInfo.scala
@@ -60,10 +60,11 @@ class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree], val isRootImp
def recur(sels: List[untpd.Tree]): Unit = sels match {
case sel :: sels1 =>
sel match {
- case Pair(Ident(name: TermName), Ident(nme.WILDCARD)) =>
+ case Thicket(Ident(name: TermName) :: Ident(nme.WILDCARD) :: Nil) =>
myExcluded += name
- case Pair(Ident(from: TermName), Ident(to: TermName)) =>
+ case Thicket(Ident(from: TermName) :: Ident(to: TermName) :: Nil) =>
myMapped = myMapped.updated(to, from)
+ myExcluded += from
myOriginals += from
case Ident(nme.WILDCARD) =>
myWildcardImport = true
@@ -98,7 +99,7 @@ class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree], val isRootImp
lazy val hiddenRoot: Symbol = {
val sym = site.termSymbol
def hasMaskingSelector = selectors exists {
- case Pair(_, Ident(nme.WILDCARD)) => true
+ case Thicket(_ :: Ident(nme.WILDCARD) :: Nil) => true
case _ => false
}
if ((defn.RootImportTypes exists (_.symbol == sym)) && hasMaskingSelector) sym else NoSymbol
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 719e8d7fc..9a1a42e44 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -15,7 +15,7 @@ import util.{Stats, SimpleMap}
import util.common._
import Decorators._
import Uniques._
-import config.Printers._
+import config.Printers.{typr, constr}
import annotation.tailrec
import reporting._
import collection.mutable
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index d90f37860..cfd49fd87 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -15,7 +15,7 @@ import annotation.tailrec
import ErrorReporting._
import tpd.ListOfTreeDecorator
import config.Config
-import config.Printers._
+import config.Printers.{typr, completions, noPrinter}
import Annotations._
import Inferencing._
import transform.ValueClasses._
@@ -273,6 +273,7 @@ class Namer { typer: Typer =>
}
val inSuperCall = if (ctx.mode is Mode.InSuperCall) InSuperCall else EmptyFlags
+
tree match {
case tree: TypeDef if tree.isClassDef =>
val name = checkNoConflict(tree.name.encode).asTypeName
@@ -280,7 +281,7 @@ class Namer { typer: Typer =>
val cls = recordSym(ctx.newClassSymbol(
ctx.owner, name, flags | inSuperCall,
cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree),
- privateWithinClass(tree.mods), tree.pos, ctx.source.file), tree)
+ privateWithinClass(tree.mods), tree.namePos, ctx.source.file), tree)
cls.completer.asInstanceOf[ClassCompleter].init()
cls
case tree: MemberDef =>
@@ -315,7 +316,7 @@ class Namer { typer: Typer =>
recordSym(ctx.newSymbol(
ctx.owner, name, flags | deferred | method | higherKinded | inSuperCall1,
adjustIfModule(completer, tree),
- privateWithinClass(tree.mods), tree.pos), tree)
+ privateWithinClass(tree.mods), tree.namePos), tree)
case tree: Import =>
recordSym(ctx.newSymbol(
ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos), tree)
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index f209c99be..80f0fd186 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -15,7 +15,7 @@ import util.common._
import Decorators._
import Uniques._
import ErrorReporting.errorType
-import config.Printers._
+import config.Printers.typr
import collection.mutable
object ProtoTypes {
@@ -182,6 +182,8 @@ object ProtoTypes {
if ((args eq this.args) && (resultType eq this.resultType) && (typer eq this.typer)) this
else new FunProto(args, resultType, typer)
+ override def notApplied = WildcardType
+
/** Forget the types of any arguments that have been typed producing a constraint in a
* typer state that is not yet committed into the one of the current context `ctx`.
* This is necessary to avoid "orphan" PolyParams that are referred to from
@@ -319,6 +321,8 @@ object ProtoTypes {
if ((targs eq this.targs) && (resType eq this.resType)) this
else PolyProto(targs, resType)
+ override def notApplied = WildcardType
+
def map(tm: TypeMap)(implicit ctx: Context): PolyProto =
derivedPolyProto(targs mapConserve tm, tm(resultType))
diff --git a/src/dotty/tools/dotc/typer/ReTyper.scala b/src/dotty/tools/dotc/typer/ReTyper.scala
index a4f92271a..9750957bf 100644
--- a/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -38,12 +38,6 @@ class ReTyper extends Typer {
untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)
}
- override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): Tree = {
- assert(tree.hasType)
- val qual1 = typed(tree.qualifier, AnySelectionProto)
- untpd.cpy.SelectFromTypeTree(tree)(qual1, tree.name).withType(tree.typeOpt)
- }
-
override def typedLiteral(tree: untpd.Literal)(implicit ctc: Context): Literal =
promote(tree)
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 2838866fd..1f150c519 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -525,7 +525,7 @@ object RefChecks {
subclassMsg(concreteSym, abstractSym)
else ""
- undefined(s"\n(Note that $pa does not match $pc$addendum)")
+ undefined(s"\n(Note that ${pa.show} does not match ${pc.show}$addendum)")
case xs =>
undefined(s"\n(The class implements a member with a different type: ${concrete.showDcl})")
}
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 36404a68f..ba8f35cd8 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -8,7 +8,7 @@ import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._,
import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._
import TypeApplications.AppliedType
import util.Positions._
-import config.Printers._
+import config.Printers.typr
import ast.Trees._
import NameOps._
import collection.mutable
@@ -81,10 +81,11 @@ trait TypeAssigner {
parentType.findMember(decl.name, info.cls.thisType, Private)
.suchThat(decl.matches(_))
val inheritedInfo = inherited.info
- if (inheritedInfo.exists && decl.info <:< inheritedInfo && !(inheritedInfo <:< decl.info))
- typr.echo(
- i"add ref $parent $decl --> ",
- RefinedType(parent, decl.name, decl.info))
+ if (inheritedInfo.exists && decl.info <:< inheritedInfo && !(inheritedInfo <:< decl.info)) {
+ val r = RefinedType(parent, decl.name, decl.info)
+ typr.println(i"add ref $parent $decl --> " + r)
+ r
+ }
else
parent
}
@@ -168,7 +169,9 @@ trait TypeAssigner {
val d2 = pre.nonPrivateMember(name)
if (reallyExists(d2) && firstTry)
test(tpe.shadowed.withDenot(d2), false)
- else {
+ else if (pre.derivesFrom(defn.DynamicClass)) {
+ TryDynamicCallType
+ } else {
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
val what = alts match {
case Nil =>
@@ -260,9 +263,6 @@ trait TypeAssigner {
tree.withType(tp)
}
- def assignType(tree: untpd.SelectFromTypeTree, qual: Tree)(implicit ctx: Context) =
- tree.withType(accessibleSelectionType(tree, qual))
-
def assignType(tree: untpd.New, tpt: Tree)(implicit ctx: Context) =
tree.withType(tpt.tpe)
@@ -321,21 +321,30 @@ trait TypeAssigner {
case pt: PolyType =>
val paramNames = pt.paramNames
if (hasNamedArg(args)) {
- val argMap = new mutable.HashMap[Name, Type]
+ // Type arguments which are specified by name (immutable after this first loop)
+ val namedArgMap = new mutable.HashMap[Name, Type]
for (NamedArg(name, arg) <- args)
- if (argMap.contains(name))
+ if (namedArgMap.contains(name))
ctx.error("duplicate name", arg.pos)
else if (!paramNames.contains(name))
ctx.error(s"undefined parameter name, required: ${paramNames.mkString(" or ")}", arg.pos)
else
- argMap(name) = arg.tpe
+ namedArgMap(name) = arg.tpe
+
+ // Holds indexes of non-named typed arguments in paramNames
val gapBuf = new mutable.ListBuffer[Int]
- def nextPoly = {
- val idx = gapBuf.length
+ def nextPoly(idx: Int) = {
+ val newIndex = gapBuf.length
gapBuf += idx
- PolyParam(pt, idx)
+ // Re-index unassigned type arguments that remain after transformation
+ PolyParam(pt, newIndex)
}
- val normArgs = paramNames.map(pname => argMap.getOrElse(pname, nextPoly))
+
+ // Type parameters after naming assignment, conserving paramNames order
+ val normArgs: List[Type] = paramNames.zipWithIndex.map { case (pname, idx) =>
+ namedArgMap.getOrElse(pname, nextPoly(idx))
+ }
+
val transform = new TypeMap {
def apply(t: Type) = t match {
case PolyParam(`pt`, idx) => normArgs(idx)
@@ -347,25 +356,23 @@ trait TypeAssigner {
else {
val gaps = gapBuf.toList
pt.derivedPolyType(
- gaps.map(paramNames.filterNot(argMap.contains)),
+ gaps.map(paramNames),
gaps.map(idx => transform(pt.paramBounds(idx)).bounds),
resultType1)
}
}
else {
val argTypes = args.tpes
- if (sameLength(argTypes, paramNames)|| ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes)
+ if (sameLength(argTypes, paramNames) || ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes)
else wrongNumberOfArgs(fn.tpe, "type ", pt.paramNames.length, tree.pos)
}
case _ =>
errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos)
}
+
tree.withType(ownType)
}
- def assignType(tree: untpd.Pair, left: Tree, right: Tree)(implicit ctx: Context) =
- tree.withType(defn.PairType.appliedTo(left.tpe :: right.tpe :: Nil))
-
def assignType(tree: untpd.Typed, tpt: Tree)(implicit ctx: Context) =
tree.withType(tpt.tpe)
@@ -383,8 +390,8 @@ trait TypeAssigner {
def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context) =
tree.withType(
- if (target.isEmpty) meth.tpe.widen.toFunctionType(tree.env.length)
- else target.tpe)
+ if (target.isEmpty) meth.tpe.widen.toFunctionType(tree.env.length)
+ else target.tpe)
def assignType(tree: untpd.CaseDef, body: Tree)(implicit ctx: Context) =
tree.withType(body.tpe)
@@ -487,7 +494,7 @@ trait TypeAssigner {
def assignType(tree: untpd.Import, sym: Symbol)(implicit ctx: Context) =
tree.withType(sym.nonMemberTermRef)
- def assignType(tree: untpd.Annotated, annot: Tree, arg: Tree)(implicit ctx: Context) =
+ def assignType(tree: untpd.Annotated, arg: Tree, annot: Tree)(implicit ctx: Context) =
tree.withType(AnnotatedType(arg.tpe.widen, Annotation(annot)))
def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context) =
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index fdcfe347b..562af75f6 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -31,7 +31,7 @@ import collection.mutable
import annotation.tailrec
import Implicits._
import util.Stats.{track, record}
-import config.Printers._
+import config.Printers.{typr, gadts}
import rewrite.Rewrites.patch
import NavigateAST._
import transform.SymUtils._
@@ -72,6 +72,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
private var importedFromRoot: Set[Symbol] = Set()
+ /** Temporary data item for single call to typed ident:
+ * This symbol would be found under Scala2 mode, but is not
+ * in dotty (because dotty conforms to spec section 2
+ * wrt to package member resolution but scalac doe not).
+ */
+ private var foundUnderScala2: Type = NoType
+
def newLikeThis: Typer = new Typer
/** Attribute an identifier consisting of a simple name or wildcard
@@ -133,14 +140,20 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
* imported by <tree>
* or defined in <symbol>
*/
- def bindingString(prec: Int, whereFound: Context, qualifier: String = "") =
+ def bindingString(prec: Int, whereFound: Context, qualifier: String = "")(implicit ctx: Context) =
if (prec == wildImport || prec == namedImport) ex"imported$qualifier by ${whereFound.importInfo}"
else ex"defined$qualifier in ${whereFound.owner}"
/** Check that any previously found result from an inner context
* does properly shadow the new one from an outer context.
+ * @param found The newly found result
+ * @param newPrec Its precedence
+ * @param scala2pkg Special mode where we check members of the same package, but defined
+ * in different compilation units under Scala2. If set, and the
+ * previous and new contexts do not have the same scope, we select
+ * the previous (inner) definition. This models what scalac does.
*/
- def checkNewOrShadowed(found: Type, newPrec: Int): Type =
+ def checkNewOrShadowed(found: Type, newPrec: Int, scala2pkg: Boolean = false)(implicit ctx: Context): Type =
if (!previous.exists || ctx.typeComparer.isSameRef(previous, found)) found
else if ((prevCtx.scope eq ctx.scope) &&
(newPrec == definition ||
@@ -150,7 +163,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
found
}
else {
- if (!previous.isError && !found.isError) {
+ if (!scala2pkg && !previous.isError && !found.isError) {
error(
ex"""reference to $name is ambiguous;
|it is both ${bindingString(newPrec, ctx, "")}
@@ -163,7 +176,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
/** The type representing a named import with enclosing name when imported
* from given `site` and `selectors`.
*/
- def namedImportRef(site: Type, selectors: List[untpd.Tree]): Type = {
+ def namedImportRef(site: Type, selectors: List[untpd.Tree])(implicit ctx: Context): Type = {
def checkUnambiguous(found: Type) = {
val other = namedImportRef(site, selectors.tail)
if (other.exists && found.exists && (found != other))
@@ -173,15 +186,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
val Name = name.toTermName.decode
selectors match {
- case Pair(Ident(from), Ident(Name)) :: rest =>
- val selName = if (name.isTypeName) from.toTypeName else from
- // Pass refctx so that any errors are reported in the context of the
- // reference instead of the context of the import.
- checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
- case Ident(Name) :: rest =>
- checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
- case _ :: rest =>
- namedImportRef(site, rest)
+ case selector :: rest =>
+ selector match {
+ case Thicket(fromId :: Ident(Name) :: _) =>
+ val Ident(from) = fromId
+ val selName = if (name.isTypeName) from.toTypeName else from
+ // Pass refctx so that any errors are reported in the context of the
+ // reference instead of the context of the import.
+ checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
+ case Ident(Name) =>
+ checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
+ case _ =>
+ namedImportRef(site, rest)
+ }
case nil =>
NoType
}
@@ -190,7 +207,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
/** The type representing a wildcard import with enclosing name when imported
* from given import info
*/
- def wildImportRef(imp: ImportInfo): Type = {
+ def wildImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
if (imp.isWildcardImport) {
val pre = imp.site
if (!isDisabled(imp, pre) && !(imp.excluded contains name.toTermName) && name != nme.CONSTRUCTOR) {
@@ -204,54 +221,71 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
/** Is (some alternative of) the given predenotation `denot`
* defined in current compilation unit?
*/
- def isDefinedInCurrentUnit(denot: Denotation): Boolean = denot match {
+ def isDefinedInCurrentUnit(denot: Denotation)(implicit ctx: Context): Boolean = denot match {
case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2)
case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source.file
}
/** Is `denot` the denotation of a self symbol? */
- def isSelfDenot(denot: Denotation) = denot match {
+ def isSelfDenot(denot: Denotation)(implicit ctx: Context) = denot match {
case denot: SymDenotation => denot is SelfName
case _ => false
}
- // begin findRef
- if (ctx.scope == null) previous
- else {
- val outer = ctx.outer
- if ((ctx.scope ne outer.scope) || (ctx.owner ne outer.owner)) {
- val defDenot = ctx.denotNamed(name)
- if (qualifies(defDenot)) {
- val curOwner = ctx.owner
- val found =
- if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType
- else curOwner.thisType.select(name, defDenot)
- if (!(curOwner is Package) || isDefinedInCurrentUnit(defDenot))
- return checkNewOrShadowed(found, definition) // no need to go further out, we found highest prec entry
- else if (defDenot.symbol is Package)
- return checkNewOrShadowed(previous orElse found, packageClause)
- else if (prevPrec < packageClause)
- return findRef(found, packageClause, ctx)(outer)
+ /** Would import of kind `prec` be not shadowed by a nested higher-precedence definition? */
+ def isPossibleImport(prec: Int)(implicit ctx: Context) =
+ prevPrec < prec || prevPrec == prec && (prevCtx.scope eq ctx.scope)
+
+ @tailrec def loop(implicit ctx: Context): Type = {
+ if (ctx.scope == null) previous
+ else {
+ val outer = ctx.outer
+ var result: Type = NoType
+
+ // find definition
+ if ((ctx.scope ne outer.scope) || (ctx.owner ne outer.owner)) {
+ val defDenot = ctx.denotNamed(name)
+ if (qualifies(defDenot)) {
+ val curOwner = ctx.owner
+ val found =
+ if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType
+ else curOwner.thisType.select(name, defDenot)
+ if (!(curOwner is Package) || isDefinedInCurrentUnit(defDenot))
+ result = checkNewOrShadowed(found, definition) // no need to go further out, we found highest prec entry
+ else {
+ if (ctx.scala2Mode && !foundUnderScala2.exists)
+ foundUnderScala2 = checkNewOrShadowed(found, definition, scala2pkg = true)
+ if (defDenot.symbol is Package)
+ result = checkNewOrShadowed(previous orElse found, packageClause)
+ else if (prevPrec < packageClause)
+ result = findRef(found, packageClause, ctx)(outer)
+ }
+ }
}
- }
- val curImport = ctx.importInfo
- if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
- return previous // no more conflicts possible in this case
- // would import of kind `prec` be not shadowed by a nested higher-precedence definition?
- def isPossibleImport(prec: Int) =
- prevPrec < prec || prevPrec == prec && (prevCtx.scope eq ctx.scope)
- if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
- val namedImp = namedImportRef(curImport.site, curImport.selectors)
- if (namedImp.exists)
- return findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
- if (isPossibleImport(wildImport)) {
- val wildImp = wildImportRef(curImport)
- if (wildImp.exists)
- return findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
+
+ if (result.exists) result
+ else { // find import
+ val curImport = ctx.importInfo
+ if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
+ previous // no more conflicts possible in this case
+ else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
+ val namedImp = namedImportRef(curImport.site, curImport.selectors)
+ if (namedImp.exists)
+ findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
+ else if (isPossibleImport(wildImport)) {
+ val wildImp = wildImportRef(curImport)
+ if (wildImp.exists)
+ findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
+ else loop(outer)
+ }
+ else loop(outer)
+ }
+ else loop(outer)
}
}
- findRef(previous, prevPrec, prevCtx)(outer)
}
+
+ loop
}
// begin typedIdent
@@ -264,12 +298,28 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
return typed(desugar.patternVar(tree), pt)
}
- val saved = importedFromRoot
- importedFromRoot = Set.empty
- val rawType =
- try findRef(NoType, BindingPrec.nothingBound, NoContext)
- finally importedFromRoot = saved
+ val rawType = {
+ val saved1 = importedFromRoot
+ val saved2 = foundUnderScala2
+ importedFromRoot = Set.empty
+ foundUnderScala2 = NoType
+ try {
+ var found = findRef(NoType, BindingPrec.nothingBound, NoContext)
+ if (foundUnderScala2.exists && !(foundUnderScala2 =:= found)) {
+ ctx.migrationWarning(
+ ex"""Name resolution will change.
+ | currently selected : $foundUnderScala2
+ | in the future, without -language:Scala2: $found""", tree.pos)
+ found = foundUnderScala2
+ }
+ found
+ }
+ finally {
+ importedFromRoot = saved1
+ foundUnderScala2 = saved2
+ }
+ }
val ownType =
if (rawType.exists)
@@ -313,55 +363,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
else tree
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
- def asSelect(implicit ctx: Context): Tree = {
+ def typeSelectOnTerm(implicit ctx: Context): Tree = {
val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
val select = typedSelect(tree, pt, qual1)
- pt match {
- case _: FunProto | AssignProto => select
- case _ =>
- if (select.tpe eq TryDynamicCallType) typedDynamicSelect(tree, pt)
- else select
- }
- }
-
- def asJavaSelectFromTypeTree(implicit ctx: Context): Tree = {
- // Translate names in Select/Ident nodes to type names.
- def convertToTypeName(tree: untpd.Tree): Option[untpd.Tree] = tree match {
- case Select(qual, name) => Some(untpd.Select(qual, name.toTypeName))
- case Ident(name) => Some(untpd.Ident(name.toTypeName))
- case _ => None
- }
+ if (select.tpe ne TryDynamicCallType) select
+ else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
+ else typedDynamicSelect(tree, Nil, pt)
+ }
- // Try to convert Select(qual, name) to a SelectFromTypeTree.
- def convertToSelectFromType(qual: untpd.Tree, origName: Name): Option[untpd.SelectFromTypeTree] =
- convertToTypeName(qual) match {
- case Some(qual1) => Some(untpd.SelectFromTypeTree(qual1 withPos qual.pos, origName.toTypeName))
- case _ => None
- }
+ def typeSelectOnType(qual: untpd.Tree)(implicit ctx: Context) =
+ typedSelect(untpd.cpy.Select(tree)(qual, tree.name.toTypeName), pt)
- convertToSelectFromType(tree.qualifier, tree.name) match {
- case Some(sftt) => typedSelectFromTypeTree(sftt, pt)
- case _ => ctx.error(em"Could not convert $tree to a SelectFromTypeTree"); EmptyTree
- }
+ def tryJavaSelectOnType(implicit ctx: Context): Tree = tree.qualifier match {
+ case Select(qual, name) => typeSelectOnType(untpd.Select(qual, name.toTypeName))
+ case Ident(name) => typeSelectOnType(untpd.Ident(name.toTypeName))
+ case _ => errorTree(tree, "cannot convert to type selection") // will never be printed due to fallback
}
- def selectWithFallback(fallBack: => Tree) =
- tryEither(tryCtx => asSelect(tryCtx))((_, _) => fallBack)
+ def selectWithFallback(fallBack: Context => Tree) =
+ tryAlternatively(typeSelectOnTerm(_))(fallBack)
- if (ctx.compilationUnit.isJava && tree.name.isTypeName)
+ if (tree.qualifier.isType) {
+ val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this))
+ assignType(cpy.Select(tree)(qual1, tree.name), qual1)
+ }
+ else if (ctx.compilationUnit.isJava && tree.name.isTypeName)
// SI-3120 Java uses the same syntax, A.B, to express selection from the
// value A and from the type A. We have to try both.
- selectWithFallback(asJavaSelectFromTypeTree(ctx))
+ selectWithFallback(tryJavaSelectOnType(_)) // !!! possibly exponential bcs of qualifier retyping
else if (tree.name == nme.withFilter && tree.getAttachment(desugar.MaybeFilter).isDefined)
- selectWithFallback(typedSelect(untpd.cpy.Select(tree)(tree.qualifier, nme.filter), pt))
+ selectWithFallback {
+ implicit ctx =>
+ typedSelect(untpd.cpy.Select(tree)(tree.qualifier, nme.filter), pt) // !!! possibly exponential bcs of qualifier retyping
+ }
else
- asSelect(ctx)
- }
-
- def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): Tree = track("typedSelectFromTypeTree") {
- val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this))
- assignType(cpy.SelectFromTypeTree(tree)(qual1, tree.name), qual1)
+ typeSelectOnTerm(ctx)
}
def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = track("typedThis") {
@@ -405,16 +442,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
- def typedPair(tree: untpd.Pair, pt: Type)(implicit ctx: Context) = track("typedPair") {
- val (leftProto, rightProto) = pt.argTypesLo match {
- case l :: r :: Nil if pt isRef defn.PairClass => (l, r)
- case _ => (WildcardType, WildcardType)
- }
- val left1 = typed(tree.left, leftProto)
- val right1 = typed(tree.right, rightProto)
- assignType(cpy.Pair(tree)(left1, right1), left1, right1)
- }
-
def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = track("typedTyped") {
/* Handles three cases:
* @param ifPat how to handle a pattern (_: T)
@@ -518,11 +545,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
reassignmentToVal
}
case TryDynamicCallType =>
- tree match {
- case Assign(Select(qual, name), rhs) if !isDynamicMethod(name) =>
- typedDynamicAssign(qual, name, rhs, pt)
- case _ => reassignmentToVal
- }
+ typedDynamicAssign(tree, pt)
case tpe =>
reassignmentToVal
}
@@ -533,7 +556,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = track("typedBlock") {
val exprCtx = index(tree.stats)
val stats1 = typedStats(tree.stats, ctx.owner)
- val expr1 = typedExpr(tree.expr, pt)(exprCtx)
+ val ept =
+ if (tree.isInstanceOf[untpd.InfixOpBlock])
+ // Right-binding infix operations are expanded to InfixBlocks, which may be followed by arguments.
+ // Example: `(a /: bs)(op)` expands to `{ val x = a; bs./:(x) } (op)` where `{...}` is an InfixBlock.
+ pt
+ else pt.notApplied
+ val expr1 = typedExpr(tree.expr, ept)(exprCtx)
ensureNoLocalRefs(
assignType(cpy.Block(tree)(stats1, expr1), stats1, expr1), pt, localSyms(stats1))
}
@@ -580,8 +609,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) = track("typedIf") {
val cond1 = typed(tree.cond, defn.BooleanType)
- val thenp1 = typed(tree.thenp, pt)
- val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt)
+ val thenp1 = typed(tree.thenp, pt.notApplied)
+ val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied)
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
}
@@ -754,7 +783,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val selType = widenForMatchSelector(
fullyDefinedType(sel1.tpe, "pattern selector", tree.pos))
- val cases1 = typedCases(tree.cases, selType, pt)
+ val cases1 = typedCases(tree.cases, selType, pt.notApplied)
val cases2 = harmonize(cases1).asInstanceOf[List[CaseDef]]
assignType(cpy.Match(tree)(sel1, cases2), cases2)
}
@@ -881,8 +910,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = track("typedTry") {
- val expr1 = typed(tree.expr, pt)
- val cases1 = typedCases(tree.cases, defn.ThrowableType, pt)
+ val expr1 = typed(tree.expr, pt.notApplied)
+ val cases1 = typedCases(tree.cases, defn.ThrowableType, pt.notApplied)
val finalizer1 = typed(tree.finalizer, defn.UnitType)
val expr2 :: cases2x = harmonize(expr1 :: cases1)
val cases2 = cases2x.asInstanceOf[List[CaseDef]]
@@ -1104,7 +1133,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile &&
ctx.scala2Mode && ctx.settings.rewrite.value.isDefined &&
!ctx.isAfterTyper)
- patch(Position(toUntyped(vdef).envelope.start), "@volatile ")
+ patch(Position(toUntyped(vdef).pos.start), "@volatile ")
}
def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = track("typedDefDef") {
@@ -1297,7 +1326,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val annot1 = typedExpr(tree.annot, defn.AnnotationType)
val arg1 = typed(tree.arg, pt)
if (ctx.mode is Mode.Type)
- assignType(cpy.Annotated(tree)(annot1, arg1), annot1, arg1)
+ assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1)
else {
val tpt = TypeTree(AnnotatedType(arg1.tpe.widen, Annotation(annot1)))
assignType(cpy.Typed(tree)(arg1, tpt), tpt)
@@ -1354,7 +1383,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
tree match {
case tree: untpd.Ident => typedIdent(tree, pt)
case tree: untpd.Select => typedSelect(tree, pt)
- case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt)
case tree: untpd.Bind => typedBind(tree, pt)
case tree: untpd.ValDef =>
if (tree.isEmpty) tpd.EmptyValDef
@@ -1377,7 +1405,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case tree: untpd.This => typedThis(tree)
case tree: untpd.Literal => typedLiteral(tree)
case tree: untpd.New => typedNew(tree, pt)
- case tree: untpd.Pair => typedPair(tree, pt)
case tree: untpd.Typed => typedTyped(tree, pt)
case tree: untpd.NamedArg => typedNamedArg(tree, pt)
case tree: untpd.Assign => typedAssign(tree, pt)
@@ -1478,6 +1505,17 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
+ /** Try `op1`, if there are errors, try `op2`, if `op2` also causes errors, fall back
+ * to errors and result of `op1`.
+ */
+ def tryAlternatively[T](op1: Context => T)(op2: Context => T)(implicit ctx: Context): T =
+ tryEither(op1) { (failedVal, failedState) =>
+ tryEither(op2) { (_, _) =>
+ failedState.commit
+ failedVal
+ }
+ }
+
/** Add apply node or implicit conversions. Two strategies are tried, and the first
* that is successful is picked. If neither of the strategies are successful, continues with
* `fallBack`.
@@ -1496,8 +1534,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
/** If this tree is a select node `qual.name`, try to insert an implicit conversion
- * `c` around `qual` so that `c(qual).name` conforms to `pt`. If that fails
- * return `tree` itself.
+ * `c` around `qual` so that `c(qual).name` conforms to `pt`.
*/
def tryInsertImplicitOnQualifier(tree: Tree, pt: Type)(implicit ctx: Context): Option[Tree] = ctx.traceIndented(i"try insert impl on qualifier $tree $pt") {
tree match {
diff --git a/src/dotty/tools/dotc/typer/VarianceChecker.scala b/src/dotty/tools/dotc/typer/VarianceChecker.scala
index 274218ee3..d5dd5a024 100644
--- a/src/dotty/tools/dotc/typer/VarianceChecker.scala
+++ b/src/dotty/tools/dotc/typer/VarianceChecker.scala
@@ -132,11 +132,11 @@ class VarianceChecker()(implicit ctx: Context) {
case defn: MemberDef if skip =>
ctx.debuglog(s"Skipping variance check of ${sym.showDcl}")
case tree: TypeDef =>
- checkVariance(sym, tree.envelope)
+ checkVariance(sym, tree.pos)
case tree: ValDef =>
- checkVariance(sym, tree.envelope)
+ checkVariance(sym, tree.pos)
case DefDef(_, tparams, vparamss, _, _) =>
- checkVariance(sym, tree.envelope)
+ checkVariance(sym, tree.pos)
tparams foreach traverse
vparamss foreach (_ foreach traverse)
case Template(_, _, _, body) =>
diff --git a/test/test/parsePackage.scala b/test/test/parsePackage.scala
index bef7bbe06..6fa5c0f86 100644
--- a/test/test/parsePackage.scala
+++ b/test/test/parsePackage.scala
@@ -23,8 +23,8 @@ object parsePackage extends ParserTest {
TypedSplice(t)
case SymbolLit(str) =>
tree
- case InterpolatedString(id, parts, elems) =>
- InterpolatedString(id, parts map (transformSub(_)), elems map transform)
+ case InterpolatedString(id, segments) =>
+ InterpolatedString(id, segments map transform)
case mdef @ ModuleDef(name, impl) =>
ModuleDef(name, transformSub(impl)).withMods(mdef.mods)
case Function(params, body) =>
diff --git a/tests/pending/hkt/compiler.error b/tests/disabled/not-representable/hkt/compiler.error
index b31760891..b31760891 100644
--- a/tests/pending/hkt/compiler.error
+++ b/tests/disabled/not-representable/hkt/compiler.error
diff --git a/tests/pending/hkt/hkt.scala b/tests/disabled/not-representable/hkt/hkt.scala
index 34858cd95..1a9932d73 100644
--- a/tests/pending/hkt/hkt.scala
+++ b/tests/disabled/not-representable/hkt/hkt.scala
@@ -1,3 +1,6 @@
+// This one is unavoidable. Dotty does not allow several overloaded
+// parameterless methods, so it picks the one in the subclass.
+
import scala.language.higherKinds
// Minimal reproduction for:
// scala.collection.mutable.ArrayStack.empty[Int]
diff --git a/tests/pending/run/t2337.scala b/tests/disabled/not-representable/t2337.scala
index edb574cba..9e3b8c555 100644
--- a/tests/pending/run/t2337.scala
+++ b/tests/disabled/not-representable/t2337.scala
@@ -1,4 +1,4 @@
-
+// Failure of autotupling in the presence of overloaded functions.
object Test {
def compare(first: Any, second: Any): Any = {
diff --git a/tests/neg/applydynamic_sip.check b/tests/neg/applydynamic_sip.check
new file mode 100644
index 000000000..1bd8304bf
--- /dev/null
+++ b/tests/neg/applydynamic_sip.check
@@ -0,0 +1,52 @@
+tests/neg/applydynamic_sip.scala:8: error: value applyDynamic is not a member of Dynamic(Test.qual)
+possible cause: maybe a wrong Dynamic method signature?
+ qual.sel(a, a2: _*) // error
+ ^
+tests/neg/applydynamic_sip.scala:9: error: applyDynamicNamed does not support passing a vararg parameter
+ qual.sel(arg = a, a2: _*) // error
+ ^
+tests/neg/applydynamic_sip.scala:10: error: applyDynamicNamed does not support passing a vararg parameter
+ qual.sel(arg, arg2 = "a2", a2: _*) // error
+ ^
+tests/neg/applydynamic_sip.scala:20: error: type mismatch:
+ found : String("sel")
+ required: Int
+ bad1.sel // error
+ ^
+tests/neg/applydynamic_sip.scala:21: error: type mismatch:
+ found : String("sel")
+ required: Int
+ bad1.sel(1) // error // error
+ ^
+tests/neg/applydynamic_sip.scala:21: error: method applyDynamic in class Bad1 does not take more parameters
+ bad1.sel(1) // error // error
+ ^
+tests/neg/applydynamic_sip.scala:22: error: type mismatch:
+ found : String("sel")
+ required: Int
+ bad1.sel(a = 1) // error // error
+ ^
+tests/neg/applydynamic_sip.scala:22: error: method applyDynamicNamed in class Bad1 does not take more parameters
+ bad1.sel(a = 1) // error // error
+ ^
+tests/neg/applydynamic_sip.scala:23: error: type mismatch:
+ found : String("sel")
+ required: Int
+ bad1.sel = 1 // error // error
+ ^
+tests/neg/applydynamic_sip.scala:23: error: method updateDynamic in class Bad1 does not take more parameters
+ bad1.sel = 1 // error // error
+ ^
+tests/neg/applydynamic_sip.scala:32: error: method selectDynamic in class Bad2 does not take parameters
+ bad2.sel // error
+ ^
+tests/neg/applydynamic_sip.scala:33: error: method applyDynamic in class Bad2 does not take parameters
+ bad2.sel(1) // error
+ ^
+tests/neg/applydynamic_sip.scala:34: error: method applyDynamicNamed in class Bad2 does not take parameters
+ bad2.sel(a = 1) // error
+ ^
+tests/neg/applydynamic_sip.scala:35: error: method updateDynamic in class Bad2 does not take parameters
+ bad2.sel = 1 // error
+ ^
+14 errors found
diff --git a/tests/untried/neg/applydynamic_sip.flags b/tests/neg/applydynamic_sip.flags
index 1141f9750..1141f9750 100644
--- a/tests/untried/neg/applydynamic_sip.flags
+++ b/tests/neg/applydynamic_sip.flags
diff --git a/tests/neg/applydynamic_sip.scala b/tests/neg/applydynamic_sip.scala
new file mode 100644
index 000000000..7b131e7ff
--- /dev/null
+++ b/tests/neg/applydynamic_sip.scala
@@ -0,0 +1,36 @@
+import scala.language.dynamics
+object Test extends App {
+ val qual: Dynamic = ???
+ val expr = "expr"
+ val a = "a"
+ val a2 = "a2"
+
+ qual.sel(a, a2: _*) // error
+ qual.sel(arg = a, a2: _*) // error
+ qual.sel(arg, arg2 = "a2", a2: _*) // error
+
+ class Bad1 extends Dynamic {
+ def selectDynamic(n: Int) = n
+ def applyDynamic(n: Int) = n
+ def applyDynamicNamed(n: Int) = n
+ def updateDynamic(n: Int) = n
+
+ }
+ val bad1 = new Bad1
+ bad1.sel // error
+ bad1.sel(1) // error // error
+ bad1.sel(a = 1) // error // error
+ bad1.sel = 1 // error // error
+
+ class Bad2 extends Dynamic {
+ def selectDynamic = 1
+ def applyDynamic = 1
+ def applyDynamicNamed = 1
+ def updateDynamic = 1
+ }
+ val bad2 = new Bad2
+ bad2.sel // error
+ bad2.sel(1) // error
+ bad2.sel(a = 1) // error
+ bad2.sel = 1 // error
+}
diff --git a/tests/neg/emptyCatch.scala b/tests/neg/emptyCatch.scala
new file mode 100644
index 000000000..60951d27a
--- /dev/null
+++ b/tests/neg/emptyCatch.scala
@@ -0,0 +1,3 @@
+object Test {
+ try {} catch {} // error: `catch` block does not contain a valid expression, try adding a case like - `case e: Exception =>` to the block
+}
diff --git a/tests/neg/i1503.scala b/tests/neg/i1503.scala
new file mode 100644
index 000000000..8e5dc53c6
--- /dev/null
+++ b/tests/neg/i1503.scala
@@ -0,0 +1,14 @@
+object Test {
+
+ val cond = true
+ def foo1() = println("hi")
+ def bar1() = println("there")
+
+ def foo2(x: Int) = println("hi")
+ def bar2(x: Int) = println("there")
+
+ def main(args: Array[String]) = {
+ (if (cond) foo1 else bar1)() // error: Unit does not take parameters
+ (if (cond) foo2 else bar2)(22) // error: missing arguments // error: missing arguments
+ }
+}
diff --git a/tests/untried/neg/t6355b.check b/tests/neg/t6355b.check
index f827f07e5..fb73b9c42 100644
--- a/tests/untried/neg/t6355b.check
+++ b/tests/neg/t6355b.check
@@ -1,11 +1,11 @@
t6355b.scala:14: error: value applyDynamic is not a member of A
error after rewriting to x.<applyDynamic: error>("bippy")
possible cause: maybe a wrong Dynamic method signature?
- println(x.bippy(42))
+ println(x.bippy(42)) // error
^
t6355b.scala:15: error: value applyDynamic is not a member of A
error after rewriting to x.<applyDynamic: error>("bippy")
possible cause: maybe a wrong Dynamic method signature?
- println(x.bippy("42"))
+ println(x.bippy("42")) // error
^
two errors found
diff --git a/tests/untried/neg/t6355b.scala b/tests/neg/t6355b.scala
index 5f3c97cb0..bba3c4fdc 100644
--- a/tests/untried/neg/t6355b.scala
+++ b/tests/neg/t6355b.scala
@@ -11,7 +11,7 @@ class B(method: String) {
object Test {
def main(args: Array[String]): Unit = {
val x = new A
- println(x.bippy(42))
- println(x.bippy("42"))
+ println(x.bippy(42)) // error
+ println(x.bippy("42")) // error
}
}
diff --git a/tests/untried/neg/t6663.check b/tests/neg/t6663.check
index aa4faa4a4..aa4faa4a4 100644
--- a/tests/untried/neg/t6663.check
+++ b/tests/neg/t6663.check
diff --git a/tests/untried/neg/t6663.scala b/tests/neg/t6663.scala
index 4a358dfbc..aa4ab08ed 100644
--- a/tests/untried/neg/t6663.scala
+++ b/tests/neg/t6663.scala
@@ -13,7 +13,7 @@ object Test extends App {
// but, before fixing SI-6663, became
// C(42).selectDynamic("foo").get, ignoring
// the [String] type parameter
- var v = new C(42).foo[String].get :Int
+ var v = new C(42).foo[String].get :Int // error
println(v)
}
diff --git a/tests/untried/neg/t6920.check b/tests/neg/t6920.check
index ee4eafb83..8bfd16a5f 100644
--- a/tests/untried/neg/t6920.check
+++ b/tests/neg/t6920.check
@@ -1,6 +1,6 @@
t6920.scala:9: error: too many arguments for method applyDynamicNamed: (values: Seq[(String, Any)])String
error after rewriting to CompilerError.this.test.applyDynamicNamed("crushTheCompiler")(scala.Tuple2("a", 1), scala.Tuple2("b", 2))
possible cause: maybe a wrong Dynamic method signature?
- test.crushTheCompiler(a = 1, b = 2)
+ test.crushTheCompiler(a = 1, b = 2) // error
^
one error found
diff --git a/tests/untried/neg/t6920.scala b/tests/neg/t6920.scala
index 25dc7b3b6..9601ed8d2 100644
--- a/tests/untried/neg/t6920.scala
+++ b/tests/neg/t6920.scala
@@ -6,5 +6,5 @@ class DynTest extends Dynamic {
class CompilerError {
val test = new DynTest
- test.crushTheCompiler(a = 1, b = 2)
+ test.crushTheCompiler(a = 1, b = 2) // error
}
diff --git a/tests/untried/neg/t8006.check b/tests/neg/t8006.check
index fbac26e3a..98207ba30 100644
--- a/tests/untried/neg/t8006.check
+++ b/tests/neg/t8006.check
@@ -1,6 +1,6 @@
t8006.scala:3: error: too many arguments for method applyDynamicNamed: (value: (String, Any))String
error after rewriting to X.this.d.applyDynamicNamed("meth")(scala.Tuple2("value1", 10), scala.Tuple2("value2", 100))
possible cause: maybe a wrong Dynamic method signature?
- d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed
+ d.meth(value1 = 10, value2 = 100) // error: two arguments here, but only one is allowed
^
one error found
diff --git a/tests/untried/neg/t8006.scala b/tests/neg/t8006.scala
index 8dc60697d..34946a659 100644
--- a/tests/untried/neg/t8006.scala
+++ b/tests/neg/t8006.scala
@@ -1,6 +1,6 @@
object X {
val d = new D
- d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed
+ d.meth(value1 = 10, value2 = 100) // error: two arguments here, but only one is allowed
}
import language.dynamics
class D extends Dynamic {
diff --git a/tests/pending/import-rewrite/compiler.error b/tests/pending/import-rewrite/compiler.error
deleted file mode 100644
index 0832d33bb..000000000
--- a/tests/pending/import-rewrite/compiler.error
+++ /dev/null
@@ -1,6 +0,0 @@
-$ scalac tests/pending/import-rewrite/*.scala
-$ ./bin/dotc tests/pending/import-rewrite/*.scala
-tests/pending/import-rewrite/rewrite.scala:5: error: value apply is not a member of java.io.File.type
- Seq("").map(File.apply)
- ^
-one error found
diff --git a/tests/pending/run/t2337.check b/tests/pending/run/t2337.check
deleted file mode 100644
index 18f1f66fc..000000000
--- a/tests/pending/run/t2337.check
+++ /dev/null
@@ -1,4 +0,0 @@
-(Both Int,-1,-1)
-(Both Float,1,1)
-(Float then Int,0,0)
-(Int then Float,0,0)
diff --git a/tests/pending/run/t3150.scala b/tests/pending/run/t3150.scala
index 034703b5f..dc95af373 100644
--- a/tests/pending/run/t3150.scala
+++ b/tests/pending/run/t3150.scala
@@ -1,10 +1,26 @@
-object Test {
- case object Bob { override def equals(other: Any) = true }
- def f(x: Any) = x match { case Bob => Bob }
-
- def main(args: Array[String]): Unit = {
- assert(f(Bob) eq Bob)
- assert(f(0) eq Bob)
- assert(f(Nil) eq Bob)
- }
-}
+ object Test {
+ case object Bob { override def equals(other: Any) = true }
+
+ class Bob2 {
+ override def equals(other: Any) = true
+ }
+ val Bob2 = new Bob2
+
+ def f0(x: Any) = x match { case Bob2 => Bob2 } // class cast exception at runtime, dotc only
+ def f1(x: Any) = x match { case Bob => Bob } // class cast exception at runtime, dotc only
+ def f2(x: Any): Bob.type = x match { case x @ Bob => x } // class cast exception at runtime, dotc and javac.
+
+ def main(args: Array[String]): Unit = {
+ assert(f0(Bob2) eq Bob2)
+ assert(f0(0) eq Bob2) // only dotty fails here
+ assert(f0(Nil) eq Bob2)
+
+ assert(f1(Bob) eq Bob)
+ assert(f1(0) eq Bob) // only dotty fails here
+ assert(f1(Nil) eq Bob)
+
+ assert(f2(Bob) eq Bob)
+ assert(f2(0) eq Bob) // both dotty and scalac fail here
+ assert(f2(Nil) eq Bob)
+ }
+ }
diff --git a/tests/pending/run/unapply.check b/tests/pending/run/unapply.check
deleted file mode 100644
index 847e3b381..000000000
--- a/tests/pending/run/unapply.check
+++ /dev/null
@@ -1,3 +0,0 @@
-unapply.scala:57: warning: comparing values of types Null and Null using `==' will always yield true
- assert(doMatch2(b) == null)
- ^
diff --git a/tests/pos-scala2/naming-resolution/callsite.scala b/tests/pos-scala2/naming-resolution/callsite.scala
new file mode 100644
index 000000000..036803a26
--- /dev/null
+++ b/tests/pos-scala2/naming-resolution/callsite.scala
@@ -0,0 +1,10 @@
+// This one should be rejected according to spec. The import takes precedence
+// over the type in the same package because the typeis declared in a
+// different compilation unit. scalac does not conform to spec here.
+package naming.resolution
+
+import java.nio.file._ // Imports `Files`
+
+object Resolution {
+ def gimmeFiles: Files = Files.list(Paths.get("."))
+}
diff --git a/tests/pos-scala2/naming-resolution/package.scala b/tests/pos-scala2/naming-resolution/package.scala
new file mode 100644
index 000000000..f0e26ee95
--- /dev/null
+++ b/tests/pos-scala2/naming-resolution/package.scala
@@ -0,0 +1,5 @@
+package naming
+
+package object resolution {
+ type Files = java.util.stream.Stream[java.nio.file.Path]
+}
diff --git a/tests/pending/run/t3050.scala b/tests/pos-scala2/t3050.scala
index 160f8b664..160f8b664 100644
--- a/tests/pending/run/t3050.scala
+++ b/tests/pos-scala2/t3050.scala
diff --git a/tests/pending/import-rewrite/file.scala b/tests/pos/import-rewrite/file.scala
index e52581e81..e52581e81 100644
--- a/tests/pending/import-rewrite/file.scala
+++ b/tests/pos/import-rewrite/file.scala
diff --git a/tests/pending/import-rewrite/rewrite.scala b/tests/pos/import-rewrite/rewrite.scala
index 0bda02c5e..0bda02c5e 100644
--- a/tests/pending/import-rewrite/rewrite.scala
+++ b/tests/pos/import-rewrite/rewrite.scala
diff --git a/tests/pos/t1500a.scala b/tests/pos/t1500a.scala
new file mode 100644
index 000000000..adf46329a
--- /dev/null
+++ b/tests/pos/t1500a.scala
@@ -0,0 +1,28 @@
+trait Step0
+trait Step1
+trait Step2
+trait Step3
+trait Step4
+trait Step5
+trait Step6
+
+object Steps {
+ implicit val Step0: Step0 = new Step0 {}
+ implicit def Step1(implicit p: Step0): Step1 = new Step1 {}
+ implicit def Step2(implicit p: Step1): Step2 = new Step2 {}
+ implicit def Step3(implicit p: Step2): Step3 = new Step3 {}
+ implicit def Step4(implicit p: Step3): Step4 = new Step4 {}
+ implicit def Step5(implicit p: Step4): Step5 = new Step5 {}
+ implicit def Step6(implicit p: Step5): Step6 = new Step6 {}
+}
+
+object StepsTest {
+ import Steps._
+
+ implicitly[Step0]
+ implicitly[Step1]
+ implicitly[Step2]
+ implicitly[Step3]
+ implicitly[Step4]
+ implicitly[Step6]
+}
diff --git a/tests/pos/t1513a.scala b/tests/pos/t1513a.scala
new file mode 100644
index 000000000..3c4c02376
--- /dev/null
+++ b/tests/pos/t1513a.scala
@@ -0,0 +1,36 @@
+object Test {
+ // Heterogeneous lists and natural numbers as defined in shapeless.
+
+ sealed trait HList
+ sealed trait ::[H, T <: HList] extends HList
+ sealed trait HNil extends HList
+
+ sealed trait Nat
+ sealed trait Succ[P <: Nat] extends Nat
+ sealed trait Zero extends Nat
+
+ // Accessor type class to compute the N'th element of an HList L.
+
+ trait Accessor[L <: HList, N <: Nat] { type Out }
+ object Accessor {
+ type Aux[L <: HList, N <: Nat, O] = Accessor[L, N] { type Out = O }
+
+ // (H :: T).At[Zero] = H
+ implicit def caseZero[H, T <: HList]: Aux[H :: T, Zero, H] = ???
+
+ // T.At[N] = O => (H :: T).At[Succ[N]] = O
+ implicit def caseN[H, T <: HList, N <: Nat, O]
+ (implicit a: Aux[T, N, O]): Aux[H :: T, Succ[N], O] = ???
+ }
+
+ case class Proxy[T]()
+
+ def at1[NN <: Nat, OO] (implicit e: Accessor.Aux[String :: HNil, NN, OO]): OO = ???
+ def at2[NN <: Nat, OO](p: Proxy[NN])(implicit e: Accessor.Aux[String :: HNil, NN, OO]): OO = ???
+
+ // N is fixed by a value
+ at2(Proxy[Zero]): String
+
+ // N is fixed as a type parameter (by name)
+ at1[NN = Zero]: String
+}
diff --git a/tests/pos/t1513b.scala b/tests/pos/t1513b.scala
new file mode 100644
index 000000000..546649383
--- /dev/null
+++ b/tests/pos/t1513b.scala
@@ -0,0 +1,25 @@
+object Test {
+ def f[
+ T1 <: String,
+ T2 <: Int,
+ T3 <: Boolean
+ ](a1: T1, a2: T2, a3: T3) = ()
+
+ f ("", 1, true)
+ f[T1 = String] ("", 1, true)
+ f[T2 = Int] ("", 1, true)
+ f[T3 = Boolean] ("", 1, true)
+ f[T1 = String, T2 = Int] ("", 1, true)
+ f[T1 = String, T3 = Boolean] ("", 1, true)
+ f[T2 = Int, T1 = String] ("", 1, true)
+ f[T2 = Int, T3 = Boolean] ("", 1, true)
+ f[T3 = Boolean, T2 = Int] ("", 1, true)
+ f[T3 = Boolean, T1 = String] ("", 1, true)
+ f[T1 = String, T2 = Int, T3 = Boolean]("", 1, true)
+ f[T1 = String, T3 = Boolean, T2 = Int] ("", 1, true)
+ f[T2 = Int, T1 = String, T3 = Boolean]("", 1, true)
+ f[T2 = Int, T3 = Boolean, T1 = String] ("", 1, true)
+ f[T3 = Boolean, T1 = String, T2 = Int] ("", 1, true)
+ f[T3 = Boolean, T2 = Int, T1 = String] ("", 1, true)
+ f[String, Int, Boolean] ("", 1, true)
+}
diff --git a/tests/pos/tryWithoutHandler.scala b/tests/pos/tryWithoutHandler.scala
new file mode 100644
index 000000000..ffe334984
--- /dev/null
+++ b/tests/pos/tryWithoutHandler.scala
@@ -0,0 +1,7 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ try {
+ println("hello")
+ }
+ }
+}
diff --git a/tests/pending/run/applydynamic_sip.check b/tests/run/applydynamic_sip.check
index 6d04dc452..6d04dc452 100644
--- a/tests/pending/run/applydynamic_sip.check
+++ b/tests/run/applydynamic_sip.check
diff --git a/tests/pending/run/applydynamic_sip.flags b/tests/run/applydynamic_sip.flags
index ba6d37305..ba6d37305 100644
--- a/tests/pending/run/applydynamic_sip.flags
+++ b/tests/run/applydynamic_sip.flags
diff --git a/tests/pending/run/applydynamic_sip.scala b/tests/run/applydynamic_sip.scala
index a163ab960..7f81a644a 100644
--- a/tests/pending/run/applydynamic_sip.scala
+++ b/tests/run/applydynamic_sip.scala
@@ -1,3 +1,4 @@
+import scala.language.dynamics
object Test extends dotty.runtime.LegacyApp {
object stubUpdate {
def update(as: Any*) = println(".update"+as.toList.mkString("(",", ", ")"))
diff --git a/tests/pending/run/dynamic-anyval.check b/tests/run/dynamic-anyval.check
index dee7bef8e..dee7bef8e 100644
--- a/tests/pending/run/dynamic-anyval.check
+++ b/tests/run/dynamic-anyval.check
diff --git a/tests/pending/run/dynamic-anyval.scala b/tests/run/dynamic-anyval.scala
index 605503d37..605503d37 100644
--- a/tests/pending/run/dynamic-anyval.scala
+++ b/tests/run/dynamic-anyval.scala
diff --git a/tests/run/dynamicDynamicTests.scala b/tests/run/dynamicDynamicTests.scala
index 3f8da8298..05b878f1c 100644
--- a/tests/run/dynamicDynamicTests.scala
+++ b/tests/run/dynamicDynamicTests.scala
@@ -23,7 +23,16 @@ class Baz extends scala.Dynamic {
def updateDynamic(name: String)(value: String): String = "updateDynamic(" + name + ")(" + value + ")"
}
+class Qux extends scala.Dynamic {
+ def selectDynamic[T](name: String): String = "selectDynamic(" + name + ")"
+ def applyDynamic[T](name: String)(args: String*): String = "applyDynamic(" + name + ")" + args.mkString("(", ", ", ")")
+ def applyDynamicNamed[T](name: String)(args: (String, Any)*): String = "applyDynamicNamed(" + name + ")" + args.mkString("(", ", ", ")")
+ def updateDynamic[T](name: String)(value: T): String = "updateDynamic(" + name + ")(" + value + ")"
+}
+
object Test {
+ val qux = new Qux
+
implicit class StringUpdater(str: String) {
def update(name: String, v: String) = s"$str.update(" + name + ", " + v + ")"
}
@@ -42,6 +51,7 @@ object Test {
runFooTests2()
runBarTests()
runBazTests()
+ runQuxTests()
assert(!failed)
}
@@ -161,4 +171,35 @@ object Test {
assertEquals("selectDynamic(bazSelectUpdate).update(7, value)", baz.bazSelectUpdate(7) = "value")
assertEquals("selectDynamic(bazSelectUpdate).update(7, 10)", baz.bazSelectUpdate(7) = 10)
}
+
+ /** Test correct lifting of type parameters */
+ def runQuxTests() = {
+ implicit def intToString(n: Int): String = n.toString
+
+ val qux = new Qux
+
+ assertEquals("selectDynamic(quxSelect)", qux.quxSelect)
+ assertEquals("selectDynamic(quxSelect)", qux.quxSelect[Int])
+
+ assertEquals("applyDynamic(quxApply)()", qux.quxApply())
+ assertEquals("applyDynamic(quxApply)()", qux.quxApply[Int]())
+ assertEquals("applyDynamic(quxApply)(1)", qux.quxApply(1))
+ assertEquals("applyDynamic(quxApply)(1)", qux.quxApply[Int](1))
+ assertEquals("applyDynamic(quxApply)(1, 2, 3)", qux.quxApply(1, 2, 3))
+ assertEquals("applyDynamic(quxApply)(1, 2, 3)", qux.quxApply[Int](1, 2, 3))
+ assertEquals("applyDynamic(quxApply)(1, 2, a)", qux.quxApply(1, 2, "a"))
+ assertEquals("applyDynamic(quxApply)(1, 2, a)", qux.quxApply[Int](1, 2, "a"))
+
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1))", qux.quxApplyNamed(a = 1))
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1))", qux.quxApplyNamed[Int](a = 1))
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1), (b,2))", qux.quxApplyNamed(a = 1, b = "2"))
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1), (b,2))", qux.quxApplyNamed[Int](a = 1, b = "2"))
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1), (,abc))", qux.quxApplyNamed(a = 1, "abc"))
+ assertEquals("applyDynamicNamed(quxApplyNamed)((a,1), (,abc))", qux.quxApplyNamed[Int](a = 1, "abc"))
+
+ assertEquals("updateDynamic(quxUpdate)(abc)", qux.quxUpdate = "abc")
+
+ assertEquals("selectDynamic(quxSelectUpdate).update(key, value)", qux.quxSelectUpdate("key") = "value")
+ assertEquals("selectDynamic(quxSelectUpdate).update(key, value)", qux.quxSelectUpdate[Int]("key") = "value")
+ }
}
diff --git a/tests/run/i1503.check b/tests/run/i1503.check
new file mode 100644
index 000000000..8cc0be027
--- /dev/null
+++ b/tests/run/i1503.check
@@ -0,0 +1,5 @@
+hello
+hi
+33
+hi
+hi
diff --git a/tests/run/i1503.scala b/tests/run/i1503.scala
new file mode 100644
index 000000000..56bb9af0c
--- /dev/null
+++ b/tests/run/i1503.scala
@@ -0,0 +1,38 @@
+object Test {
+
+ def test1() =
+ (new Function0[Unit] {
+ def apply() = println("hello")
+ })()
+
+ val cond = true
+ val foo = () => println("hi")
+ val bar = () => println("there")
+
+ val baz = (x: Int) => println(x)
+
+ def test2() =
+ (if (cond) foo else bar)()
+
+ def test2a() =
+ (if (cond) baz else baz)(33)
+
+ def test3() =
+ (try foo
+ catch { case ex: Exception => bar }
+ finally ())()
+
+ def test4() =
+ (cond match {
+ case true => foo
+ case false => bar
+ })()
+
+ def main(args: Array[String]) = {
+ test1()
+ test2()
+ test2a()
+ test3()
+ test4()
+ }
+}
diff --git a/tests/run/t1335.scala b/tests/run/t1335.scala
new file mode 100644
index 000000000..047f7b566
--- /dev/null
+++ b/tests/run/t1335.scala
@@ -0,0 +1,11 @@
+case class MyTuple(a: Int, b: Int)
+
+object Test {
+ def main(args: Array[String]): Unit =
+ try {
+ val mt: MyTuple = null
+ val MyTuple(a, b) = mt
+ } catch {
+ case e: MatchError => ()
+ }
+}
diff --git a/tests/run/t1500b.scala b/tests/run/t1500b.scala
new file mode 100644
index 000000000..8b52731a5
--- /dev/null
+++ b/tests/run/t1500b.scala
@@ -0,0 +1,21 @@
+sealed trait Nat
+sealed trait Succ[Prev <: Nat] extends Nat
+sealed trait Zero extends Nat
+
+case class ToInt[N <: Nat](value: Int)
+
+object ToInt {
+ implicit val caseZero: ToInt[Zero] = ToInt(0)
+ implicit def caseSucc[Prev <: Nat](implicit e: ToInt[Prev]): ToInt[Succ[Prev]] = ToInt(e.value + 1)
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ assert(implicitly[ToInt[Zero]].value == 0)
+ assert(implicitly[ToInt[Succ[Zero]]].value == 1)
+ assert(implicitly[ToInt[Succ[Succ[Zero]]]].value == 2)
+ assert(implicitly[ToInt[Succ[Succ[Succ[Zero]]]]].value == 3)
+ assert(implicitly[ToInt[Succ[Succ[Succ[Succ[Zero]]]]]].value == 4)
+ assert(implicitly[ToInt[Succ[Succ[Succ[Succ[Succ[Zero]]]]]]].value == 5)
+ }
+}
diff --git a/tests/run/t1500c.scala b/tests/run/t1500c.scala
new file mode 100644
index 000000000..5c33b7a2f
--- /dev/null
+++ b/tests/run/t1500c.scala
@@ -0,0 +1,19 @@
+sealed trait HList
+sealed trait HNil extends HList
+sealed trait ::[H, T <: HList] extends HList
+
+case class Size[L <: HList](value: Int)
+
+object Size {
+ implicit val caseHNil: Size[HNil] = Size(0)
+ implicit def caseHCons[H, T <: HList](implicit e: Size[T]): Size[H :: T] = Size(e.value + 1)
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ assert(implicitly[Size[HNil]].value == 0)
+ assert(implicitly[Size[Int :: HNil]].value == 1)
+ assert(implicitly[Size[Int :: Int :: HNil]].value == 2)
+ assert(implicitly[Size[Int :: Int :: Int :: HNil]].value == 3)
+ }
+}
diff --git a/tests/pending/run/t298.check b/tests/run/t298.check
index 1cd1d2266..1cd1d2266 100644
--- a/tests/pending/run/t298.check
+++ b/tests/run/t298.check
diff --git a/tests/pending/run/t298.scala b/tests/run/t298.scala
index 5728bb6c9..5728bb6c9 100644
--- a/tests/pending/run/t298.scala
+++ b/tests/run/t298.scala
diff --git a/tests/pending/run/t3026.check b/tests/run/t3026.check
index 8c29b615f..8c29b615f 100644
--- a/tests/pending/run/t3026.check
+++ b/tests/run/t3026.check
diff --git a/tests/pending/run/t3026.scala b/tests/run/t3026.scala
index 22dde9cc0..22dde9cc0 100755
--- a/tests/pending/run/t3026.scala
+++ b/tests/run/t3026.scala
diff --git a/tests/pending/run/t3353.check b/tests/run/t3353.check
index 8b4ae1fe6..8b4ae1fe6 100644
--- a/tests/pending/run/t3353.check
+++ b/tests/run/t3353.check
diff --git a/tests/pending/run/t3353.scala b/tests/run/t3353.scala
index 472723b3c..472723b3c 100644
--- a/tests/pending/run/t3353.scala
+++ b/tests/run/t3353.scala
diff --git a/tests/pending/run/t4536.check b/tests/run/t4536.check
index 0c5a72ada..0c5a72ada 100644
--- a/tests/pending/run/t4536.check
+++ b/tests/run/t4536.check
diff --git a/tests/pending/run/t4536.flags b/tests/run/t4536.flags
index 1141f9750..1141f9750 100644
--- a/tests/pending/run/t4536.flags
+++ b/tests/run/t4536.flags
diff --git a/tests/pending/run/t4536.scala b/tests/run/t4536.scala
index 6661eae6a..89a93a5e0 100644
--- a/tests/pending/run/t4536.scala
+++ b/tests/run/t4536.scala
@@ -1,8 +1,4 @@
-
-
-
-
-
+import scala.language.dynamics
object dynamicObject extends Dynamic {
def applyDynamic(m: String)() = println("obj: " + m);
@@ -38,7 +34,7 @@ object dynamicMixin extends dynamicAbstractClass with dynamicTrait {
object Test {
- def main(args: Array[String]) {
+ def main(args: Array[String]) = {
val cls = new dynamicClass
dynamicMixin
}
diff --git a/tests/pending/run/t5040.check b/tests/run/t5040.check
index 3f7b5908a..3f7b5908a 100644
--- a/tests/pending/run/t5040.check
+++ b/tests/run/t5040.check
diff --git a/tests/pending/run/t5040.flags b/tests/run/t5040.flags
index 1141f9750..1141f9750 100644
--- a/tests/pending/run/t5040.flags
+++ b/tests/run/t5040.flags
diff --git a/tests/pending/run/t5040.scala b/tests/run/t5040.scala
index 6813c1b27..58d054412 100644
--- a/tests/pending/run/t5040.scala
+++ b/tests/run/t5040.scala
@@ -1,3 +1,4 @@
+import scala.language.dynamics // originaly used the flag -language:dynamics in t5040.flags, .flags are currently ignored
abstract class Prova2 extends Dynamic {
def applyDynamic(m: String)(): Unit
private def privateMethod() = println("private method")
diff --git a/tests/pending/run/t5733.check b/tests/run/t5733.check
index e697046a9..e697046a9 100644
--- a/tests/pending/run/t5733.check
+++ b/tests/run/t5733.check
diff --git a/tests/pending/run/t5733.scala b/tests/run/t5733.scala
index a9e58d77e..a9e58d77e 100644
--- a/tests/pending/run/t5733.scala
+++ b/tests/run/t5733.scala
diff --git a/tests/pending/run/t6353.check b/tests/run/t6353.check
index 5676bed24..5676bed24 100644
--- a/tests/pending/run/t6353.check
+++ b/tests/run/t6353.check
diff --git a/tests/pending/run/t6353.scala b/tests/run/t6353.scala
index 7077eaeda..7077eaeda 100644
--- a/tests/pending/run/t6353.scala
+++ b/tests/run/t6353.scala
diff --git a/tests/pending/run/t6355.check b/tests/run/t6355.check
index ce74ab38a..ce74ab38a 100644
--- a/tests/pending/run/t6355.check
+++ b/tests/run/t6355.check
diff --git a/tests/pending/run/t6355.scala b/tests/run/t6355.scala
index f1921391a..f1921391a 100644
--- a/tests/pending/run/t6355.scala
+++ b/tests/run/t6355.scala
diff --git a/tests/pending/run/t6663.check b/tests/run/t6663.check
index d81cc0710..d81cc0710 100644
--- a/tests/pending/run/t6663.check
+++ b/tests/run/t6663.check
diff --git a/tests/pending/run/t6663.flags b/tests/run/t6663.flags
index ea7fc37e1..ea7fc37e1 100644
--- a/tests/pending/run/t6663.flags
+++ b/tests/run/t6663.flags
diff --git a/tests/pending/run/t6663.scala b/tests/run/t6663.scala
index bfe464ad6..bfe464ad6 100644
--- a/tests/pending/run/t6663.scala
+++ b/tests/run/t6663.scala
diff --git a/tests/pending/run/unapply.scala b/tests/run/unapply.scala
index 43f02b9f3..7b10030ba 100644
--- a/tests/pending/run/unapply.scala
+++ b/tests/run/unapply.scala
@@ -87,8 +87,8 @@ object Mas {
object LisSeqArr {
def run(): Unit = {
- assert((1,2) == ((List(1,2,3): Any) match { case List(x,y,_*) => (x,y)}))
- assert((1,2) == ((List(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}))
+ assert((1,2) == ((List(1,2,3): Any) match { case List(x,y,_: _*) => (x,y)}))
+ assert((1,2) == ((List(1,2,3): Any) match { case Seq(x,y,_: _*) => (x,y)}))
}
}
diff --git a/tests/untried/neg/applydynamic_sip.check b/tests/untried/neg/applydynamic_sip.check
deleted file mode 100644
index 2cb2e7f09..000000000
--- a/tests/untried/neg/applydynamic_sip.check
+++ /dev/null
@@ -1,73 +0,0 @@
-applydynamic_sip.scala:7: error: applyDynamic does not support passing a vararg parameter
- qual.sel(a, a2: _*)
- ^
-applydynamic_sip.scala:8: error: applyDynamicNamed does not support passing a vararg parameter
- qual.sel(arg = a, a2: _*)
- ^
-applydynamic_sip.scala:8: error: not found: value arg
- qual.sel(arg = a, a2: _*)
- ^
-applydynamic_sip.scala:9: error: applyDynamicNamed does not support passing a vararg parameter
- qual.sel(arg, arg2 = "a2", a2: _*)
- ^
-applydynamic_sip.scala:9: error: not found: value arg
- qual.sel(arg, arg2 = "a2", a2: _*)
- ^
-applydynamic_sip.scala:9: error: not found: value arg2
- qual.sel(arg, arg2 = "a2", a2: _*)
- ^
-applydynamic_sip.scala:18: error: type mismatch;
- found : String("sel")
- required: Int
-error after rewriting to Test.this.bad1.selectDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad1.sel
- ^
-applydynamic_sip.scala:19: error: type mismatch;
- found : String("sel")
- required: Int
-error after rewriting to Test.this.bad1.applyDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad1.sel(1)
- ^
-applydynamic_sip.scala:20: error: type mismatch;
- found : String("sel")
- required: Int
-error after rewriting to Test.this.bad1.applyDynamicNamed("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad1.sel(a = 1)
- ^
-applydynamic_sip.scala:20: error: reassignment to val
- bad1.sel(a = 1)
- ^
-applydynamic_sip.scala:21: error: type mismatch;
- found : String("sel")
- required: Int
-error after rewriting to Test.this.bad1.updateDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad1.sel = 1
- ^
-applydynamic_sip.scala:29: error: Int does not take parameters
-error after rewriting to Test.this.bad2.selectDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad2.sel
- ^
-applydynamic_sip.scala:30: error: Int does not take parameters
-error after rewriting to Test.this.bad2.applyDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad2.sel(1)
- ^
-applydynamic_sip.scala:31: error: Int does not take parameters
-error after rewriting to Test.this.bad2.applyDynamicNamed("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad2.sel(a = 1)
- ^
-applydynamic_sip.scala:31: error: reassignment to val
- bad2.sel(a = 1)
- ^
-applydynamic_sip.scala:32: error: Int does not take parameters
-error after rewriting to Test.this.bad2.updateDynamic("sel")
-possible cause: maybe a wrong Dynamic method signature?
- bad2.sel = 1
- ^
-16 errors found
diff --git a/tests/untried/neg/applydynamic_sip.scala b/tests/untried/neg/applydynamic_sip.scala
deleted file mode 100644
index ee4432ebe..000000000
--- a/tests/untried/neg/applydynamic_sip.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-object Test extends App {
- val qual: Dynamic = ???
- val expr = "expr"
- val a = "a"
- val a2 = "a2"
-
- qual.sel(a, a2: _*)
- qual.sel(arg = a, a2: _*)
- qual.sel(arg, arg2 = "a2", a2: _*)
-
- val bad1 = new Dynamic {
- def selectDynamic(n: Int) = n
- def applyDynamic(n: Int) = n
- def applyDynamicNamed(n: Int) = n
- def updateDynamic(n: Int) = n
-
- }
- bad1.sel
- bad1.sel(1)
- bad1.sel(a = 1)
- bad1.sel = 1
-
- val bad2 = new Dynamic {
- def selectDynamic = 1
- def applyDynamic = 1
- def applyDynamicNamed = 1
- def updateDynamic = 1
- }
- bad2.sel
- bad2.sel(1)
- bad2.sel(a = 1)
- bad2.sel = 1
-}