diff options
31 files changed, 374 insertions, 159 deletions
diff --git a/project/Build.scala b/project/Build.scala index 25fb31cf5b..ea0e84f0cc 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -23,7 +23,7 @@ object ScalaBuild extends Build with Layers { lazy val buildFixed = AttributeKey[Boolean]("build-uri-fixed") // Build wide settings: - override lazy val settings = super.settings ++ Seq( + override lazy val settings = super.settings ++ Versions.settings ++ Seq( autoScalaLibrary := false, resolvers += Resolver.url( "Typesafe nightlies", @@ -34,7 +34,7 @@ object ScalaBuild extends Build with Layers { ScalaToolsSnapshots ), organization := "org.scala-lang", - version := "2.10.0-SNAPSHOT", + version <<= Versions.mavenVersion, pomExtra := <xml:group> <inceptionYear>2002</inceptionYear> <licenses> @@ -148,13 +148,14 @@ object ScalaBuild extends Build with Layers { lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => Seq( "org.apache.ant" % "ant" % "1.8.2", - "org.scala-tools.sbt" % "compiler-interface" % v % "provided" + "org.scala-sbt" % "compiler-interface" % v % "provided" ) ) // These are setting overrides for most artifacts in the Scala build file. def settingOverrides: Seq[Setting[_]] = publishSettings ++ Seq( crossPaths := false, + autoScalaLibrary := false, publishArtifact in packageDoc := false, publishArtifact in packageSrc := false, target <<= (baseDirectory, name) apply (_ / "target" / _), @@ -327,7 +328,7 @@ object ScalaBuild extends Build with Layers { // Testing // -------------------------------------------------------------- /* lazy val scalacheckSettings: Seq[Setting[_]] = Seq(fullQuickScalaReference, crossPaths := false)*/ - lazy val scalacheck = uri("git://github.com/rickynils/scalacheck.git") + lazy val scalacheck = uri("git://github.com/jsuereth/scalacheck.git#scala-build") lazy val testsuiteSettings: Seq[Setting[_]] = compilerDependentProjectSettings ++ partestTaskSettings ++ VerifyClassLoad.settings ++ Seq( unmanagedBase <<= baseDirectory / "test/files/lib", @@ -518,7 +519,7 @@ object ScalaBuild extends Build with Layers { // Add in some more dependencies makeDistMappings <<= (makeDistMappings, packageBin in swing in Compile) map { - (dist, s, d) => + (dist, s) => dist ++ Seq(s -> "lib/scala-swing.jar") }, makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) => diff --git a/project/Layers.scala b/project/Layers.scala index d39e58014c..3d6d780f8f 100644 --- a/project/Layers.scala +++ b/project/Layers.scala @@ -16,6 +16,8 @@ trait Layers extends Build { def fjbg: Project /** A setting that adds some external dependencies. */ def externalDeps: Setting[_] + /** The root project. */ + def aaa_root: Project /** Creates a reference Scala version that can be used to build other projects. This takes in the raw * library, compiler and fjbg libraries as well as a string representing the layer name (used for compiling the compile-interface). @@ -57,7 +59,7 @@ trait Layers extends Build { // TODO - Allow other scalac option settings. scalacOptions in Compile <++= (scalaSource in Compile) map (src => Seq("-sourcepath", src.getAbsolutePath)), classpathOptions := ClasspathOptions.manual, - resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner, streams) map Release.generatePropertiesFile("library.properties"), + resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("library.properties"), referenceScala ) @@ -68,9 +70,8 @@ trait Layers extends Build { resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), unmanagedSourceDirectories in Compile <+= (baseDirectory) apply (_ / "src" / "msil"), defaultExcludes := ("tests"), - javacOptions ++= Seq("-source", "1.4"), defaultExcludes in unmanagedResources := "*.scala", - resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner, streams) map Release.generatePropertiesFile("compiler.properties"), + resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("compiler.properties"), // Note, we might be able to use the default task, but for some reason ant was filtering files out. Not sure what's up, but we'll // stick with that for now. unmanagedResources in Compile <<= (baseDirectory) map { diff --git a/project/Partest.scala b/project/Partest.scala index ad8047fa00..bbc160a41d 100644 --- a/project/Partest.scala +++ b/project/Partest.scala @@ -115,7 +115,7 @@ object partest { } } - def partestRunnerTask(classpath: ScopedTask[Classpath], javacOptions: ScopedTask[Seq[String]]): Project.Initialize[Task[PartestRunner]] = + def partestRunnerTask(classpath: ScopedTask[Classpath], javacOptions: SettingKey[Seq[String]]): Project.Initialize[Task[PartestRunner]] = (classpath, javacOptions) map ((cp, opts) => new PartestRunner(Build.data(cp), opts mkString " ")) } diff --git a/project/Release.scala b/project/Release.scala index 5ed77548fc..1a17956c13 100644 --- a/project/Release.scala +++ b/project/Release.scala @@ -1,115 +1,15 @@ import sbt._ import Keys._ -import _root_.com.jsuereth.git.GitRunner object Release { - // TODO - move more of the dist project over here... + // TODO - Just make the STARR artifacts and dump the sha1 files. lazy val pushStarr = Command.command("push-starr") { (state: State) => - def f(s: Setting[_]): Setting[_] = s.key.key match { - case version.key => // TODO - use full version - s.asInstanceOf[Setting[String]].mapInit( (_,_) => timeFormat format (new java.util.Date)) - case organization.key => - s.asInstanceOf[Setting[String]].mapInit( (_,_) => "org.scala-lang.bootstrapp") - // TODO - Switch publish repo to be typesafe starr repo. - case publishTo.key => - s.asInstanceOf[Setting[Option[Resolver]]].mapInit((_,_) => Some("Starr Repo" at "http://typesafe.artifactoryonline.com/typesafe/starr-releases/")) - case _ => s - } - val extracted = Project.extract(state) - import extracted._ - // Swap version on projects - val transformed = session.mergeSettings map ( s => f(s) ) - val newStructure = Load.reapply(transformed, structure) - val newState = Project.setProject(session, newStructure, state) - // TODO - Run tasks. Specifically, push scala-compiler + scala-library. *Then* bump the STARR version locally. - // The final course of this command should be: - // publish-local - // Project.evaluateTask(publishLocal, newState) - // bump STARR version setting - // TODO - Define Task - // Rebuild quick + test to ensure it works - // Project.evaluateTask(test, newState) - // push STARR remotely - Project.evaluateTask(publish, newState) + // TODO do something // Revert to previous project state. - Project.setProject(session, structure, state) + state } - // TODO - Autocomplete - /*lazy val setStarrHome = Command.single("set-starr-home") { (state: State, homeDir: String) => - def f(s: Setting[_]): Setting[_] = - if(s.key.key == scalaInstance.key) { - s.asInstanceOf[Setting[ScalaInstance]] mapInit { (key, value) => - if(value.version == "starr") - scalaInstance <<= appConfiguration map { app => - val launcher = app.provider.scalaProvider.launcher - ScalaInstance("starr", new File(homeDir), launcher) - } - else value - } - } else s - val extracted = Project.extract(state) - import extracted._ - val transformed = session.mergeSettings map f - val newStructure = Load.reapply(transformed, structure) - Project.setProject(session, newStructure, state) - }*/ - - lazy val timeFormat = { - val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss") - formatter.setTimeZone(java.util.TimeZone.getTimeZone("GMT")) - formatter - } - - /** This generates a properties file, if it does not already exist, with the maximum lastmodified timestamp - * of any source file. */ - def generatePropertiesFile(name: String)(baseDirectory: File, version: String, dir: File, git: GitRunner, s: TaskStreams): Seq[File] = { - // TODO - We can probably clean this up by moving caching bits elsewhere perhaps.... - val target = dir / name - // TODO - Regenerate on triggers, like recompilation or something... - val fullVersion = makeFullVersionString(baseDirectory, version, git, s) - def hasSameVersion: Boolean = { - val props = new java.util.Properties - val in = new java.io.FileInputStream(target) - try props.load(in) finally in.close() - def withoutDate(s: String): String = s.reverse.dropWhile (_ != '.').reverse - withoutDate(fullVersion) == withoutDate(props getProperty "version.number") - } - if (!target.exists || !hasSameVersion) { - makePropertiesFile(target, fullVersion) - } - target :: Nil - } - - // This creates the *.properties file used to determine the current version of scala at runtime. TODO - move these somewhere utility like. - def makePropertiesFile(f: File, version: String): Unit = - IO.write(f, "version.number = "+version+"\ncopyright.string = Copyright 2002-2011, LAMP/EPFL") - - def makeFullVersionString(baseDirectory: File, baseVersion: String, git: GitRunner, s: TaskStreams) = baseVersion+"."+getGitRevision(baseDirectory, git, currentDay, s) - - // TODO - do we want this in the build number? - def currentDay = (new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")) format (new java.util.Date) - - - - def getGitRevision(baseDirectory: File, git: GitRunner, date: String, s: TaskStreams) = { - - val mergeBase = { - // TODO - Cache this value. - // git("merge-base","v2.8.2","v2.9.1","master")(baseDirectory, s.log) - "df13e31bbb" - } - // current commit sha - val sha = - git("rev-list", "-n", "1", "HEAD")(baseDirectory, s.log) - - val commits = - git("--no-pager", "log", "--pretty=oneline", mergeBase +"..HEAD")(baseDirectory, s.log) split "[\r\n]+" size - - "rdev-%d-%s-g%s" format (commits, date, sha.substring(0,7)) - } - } diff --git a/project/ShaResolve.scala b/project/ShaResolve.scala index f54e96c0c6..e6824ee464 100644 --- a/project/ShaResolve.scala +++ b/project/ShaResolve.scala @@ -40,6 +40,8 @@ object ShaResolve { throw t } + // TODO - Finish this publishing aspect. + def getShaFromShafile(file: File): String = parseShaFile(file)._2 // This should calculate the SHA sum of a file the same as the linux process. diff --git a/project/Versions.scala b/project/Versions.scala new file mode 100644 index 0000000000..b588ec55ac --- /dev/null +++ b/project/Versions.scala @@ -0,0 +1,142 @@ +import sbt._ +import Keys._ +import java.util.Properties +import scala.util.control.Exception.catching +import java.lang.{NumberFormatException => NFE} +import java.io.FileInputStream +import com.jsuereth.git.GitRunner +import com.jsuereth.git.GitKeys.gitRunner + +case class VersionInfo(canonical: String, + maven: String, + osgi: String) + +/** this file is responsible for setting up Scala versioning schemes and updating all the necessary bits. */ +object Versions { + val buildNumberFile = SettingKey[File]("scala-build-number-file") + // TODO - Make this a setting? + val buildNumberProps = SettingKey[BaseBuildNumber]("scala-build-number-props") + val buildRelease = SettingKey[Boolean]("scala-build-release", "This is set to true if we're building a release.") + val mavenSuffix = SettingKey[String]("scala-maven-suffix", "This is set to whatever maven suffix is required.") + + val gitSha = TaskKey[String]("scala-git-sha", "The sha of the current git commit.") + val gitDate = TaskKey[String]("scala-git-date", "The date of the current git commit.") + + val mavenVersion = SettingKey[String]("scala-maven-version", "The maven version number.") + val osgiVersion = TaskKey[String]("scala-osgi-version", "The OSGi version number.") + val canonicalVersion = TaskKey[String]("scala-canonical-version", "The canonical version number.") + + val scalaVersions = TaskKey[VersionInfo]("scala-version-info", "The scala versions used for this build.") + + + + def settings: Seq[Setting[_]] = Seq( + buildNumberFile <<= baseDirectory apply (_ / "build.number"), + buildNumberProps <<= buildNumberFile apply loadBuildNumberProps, + buildRelease := Option(System.getProperty("build.release")) map (!_.isEmpty) getOrElse false, + mavenSuffix <<= buildRelease apply pickMavenSuffix, + mavenVersion <<= (buildNumberProps, mavenSuffix) apply makeMavenVersion, + gitSha <<= (gitRunner, baseDirectory, streams) map getGitSha, + gitDate <<= (gitRunner, baseDirectory, streams) map getGitDate, + osgiVersion <<= (buildNumberProps, gitDate, gitSha) map makeOsgiVersion, + canonicalVersion <<= (buildRelease, mavenVersion, buildNumberProps, gitDate, gitSha) map makeCanonicalVersion, + scalaVersions <<= (canonicalVersion, mavenVersion, osgiVersion) map VersionInfo.apply + ) + + + /** This generates a properties file, if it does not already exist, with the maximum lastmodified timestamp + * of any source file. */ + def generateVersionPropertiesFile(name: String)(dir: File, versions: VersionInfo, skip: Boolean, s: TaskStreams): Seq[File] = { + // TODO - We can probably clean this up by moving caching bits elsewhere perhaps.... + val target = dir / name + // TODO - Regenerate on triggers, like recompilation or something... + def hasSameVersion: Boolean = { + val props = new java.util.Properties + val in = new java.io.FileInputStream(target) + try props.load(in) finally in.close() + versions.canonical == (props getProperty "version.number") + } + if (!target.exists || !(skip || hasSameVersion)) { + makeVersionPropertiesFile(target, versions) + } + target :: Nil + } + + // This creates the *.properties file used to determine the current version of scala at runtime. TODO - move these somewhere utility like. + def makeVersionPropertiesFile(f: File, versions: VersionInfo): Unit = + IO.write(f, "version.number = "+versions.canonical+"\n"+ + "osgi.number = "+versions.osgi+"\n"+ + "maven.number = "+versions.maven+"\n"+ + "copyright.string = Copyright 2002-2011, LAMP/EPFL") + + def makeCanonicalVersion(isRelease: Boolean, mvnVersion: String, base: BaseBuildNumber, gitDate: String, gitSha: String): String = + if(isRelease) mvnVersion + else { + val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" + "%s.%s.%s%s-%s-%s" format (base.major, base.minor, base.patch, suffix, gitDate, gitSha) + } + + def makeMavenVersion(base: BaseBuildNumber, suffix: String): String = { + val firstSuffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" + "%d.%d.%d%s%s" format (base.major, base.minor, base.patch, firstSuffix, suffix) + } + + def makeOsgiVersion(base: BaseBuildNumber, gitDate: String, gitSha: String): String = { + val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" + "%s.%s.%s.v%s%s-%s" format (base.major, base.minor, base.patch, gitDate, suffix, gitSha) + } + + /** Determines what the maven sufffix should be for this build. */ + def pickMavenSuffix(isRelease: Boolean): String = { + def default = if(isRelease) "" else "-SNAPSHOT" + Option(System.getProperty("maven.version.suffix")) getOrElse default + } + + /** Loads the build.number properties file into SBT. */ + def loadBuildNumberProps(file: File): BaseBuildNumber = { + val fin = new FileInputStream(file) + try { + val props = new Properties() + props.load(fin) + def getProp(name: String): Int = + (for { + v <- Option(props.getProperty(name)) + v2 <- catching(classOf[NFE]) opt v.toInt + } yield v2) getOrElse sys.error("Could not convert %s to integer!" format (name)) + + BaseBuildNumber( + major=getProp("version.major"), + minor=getProp("version.minor"), + patch=getProp("version.patch"), + bnum =getProp("version.bnum") + ) + } finally fin.close() + } + + + def getGitDate(git: GitRunner, baseDirectory: File, s: TaskStreams): String = { + val lines = getGitLines("log","-1","--format=\"%ci\"")(git,baseDirectory, s) + val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head + // Lines *always* start with " for some reason... + line drop 1 split "\\s+" match { + case Array(date, time, _*) => "%s-%s" format (date.replaceAll("\\-", ""), time.replaceAll(":","")) + case _ => sys.error("Could not parse git date: " + line) + } + } + + def getGitSha(git: GitRunner, baseDirectory: File, s: TaskStreams): String = { + val lines = getGitLines("log","-1","--format=\"%H\"", "HEAD")(git,baseDirectory, s) + val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head + val noquote = if(line startsWith "\"") line drop 1 else line + val nog = if(noquote startsWith "g") noquote drop 1 else noquote + nog take 10 + } + + def getGitLines(args: String*)(git: GitRunner, baseDirectory: File, s: TaskStreams): Seq[String] = + git(args: _*)(baseDirectory, s.log) split "[\r\n]+" +} + + +case class BaseBuildNumber(major: Int, minor: Int, patch: Int, bnum: Int) { + override def toString = "BaseBuildNumber(%d.%d.%d-%d)" format (major, minor, patch, bnum) +} diff --git a/project/project/Build.scala b/project/project/Build.scala index 1ceb7e2ef2..bd1250fc39 100644 --- a/project/project/Build.scala +++ b/project/project/Build.scala @@ -2,6 +2,6 @@ import sbt._ object PluginDef extends Build { override def projects = Seq(root) lazy val root = Project("plugins", file(".")) dependsOn(proguard, git) - lazy val proguard = uri("git://github.com/jsuereth/xsbt-proguard-plugin.git") + lazy val proguard = uri("git://github.com/jsuereth/xsbt-proguard-plugin.git#sbt-0.11") lazy val git = uri("git://github.com/sbt/sbt-git-plugin.git#scala-build") } diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index edafde1346..0612dcdfd4 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -1207,7 +1207,7 @@ trait Definitions extends reflect.api.StandardDefinitions { def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym def isNonUnitValueClass(sym: Symbol) = isPrimitiveValueClass(sym) && (sym != UnitClass) def isSpecializableClass(sym: Symbol) = isPrimitiveValueClass(sym) || (sym == AnyRefClass) - def isScalaValueType(tp: Type) = ScalaValueClasses contains tp.typeSymbol + def isPrimitiveValueType(tp: Type) = isPrimitiveValueClass(tp.typeSymbol) /** Is symbol a boxed value class, e.g. java.lang.Integer? */ def isBoxedValueClass(sym: Symbol) = boxedValueClassesSet(sym) diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 2a5b759f94..724e5bf628 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -2088,7 +2088,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** String representation of symbol's definition key word */ final def keyString: String = if (isJavaInterface) "interface" - else if (isTrait) "trait" + else if (isTrait && !isImplClass) "trait" else if (isClass) "class" else if (isType && !isParameter) "type" else if (isVariable) "var" @@ -2116,6 +2116,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET") else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ") else if (isVariable) ("field", "variable", "VAR") + else if (isImplClass) ("implementation class", "class", "IMPL") else if (isTrait) ("trait", "trait", "TRT") else if (isClass) ("class", "class", "CLS") else if (isType) ("type", "type", "TPE") @@ -2232,7 +2233,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def infosString = infos.toString - def debugLocationString = fullLocationString + " " + debugFlagString + def debugLocationString = fullLocationString + " (flags: " + debugFlagString + ")" private def defStringCompose(infoString: String) = compose( flagString, diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index e2d9310424..3e7f23800c 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -145,11 +145,12 @@ trait Trees extends api.Trees { self: SymbolTable => */ def summaryString: String = tree match { case Literal(const) => "Literal(" + const + ")" - case Select(qual, name) => qual.summaryString + "." + name.decode + case Ident(name) => "Ident(%s)".format(name.decode) + case Select(qual, name) => "Select(%s, %s)".format(qual.summaryString, name.decode) case t: NameTree => t.name.longString case t => t.shortClass + ( - if (t.symbol != null && t.symbol != NoSymbol) " " + t.symbol + if (t.symbol != null && t.symbol != NoSymbol) "(" + t.symbol + ")" else "" ) } diff --git a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala index eb384f9a85..1424226042 100644 --- a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -7,7 +7,7 @@ trait TraceSymbolActivity { val global: SymbolTable import global._ - if (traceSymbolActivity) + if (traceSymbolActivity && !global.inReflexiveMirror) scala.sys addShutdownHook showAllSymbols() private type Set[T] = scala.collection.immutable.Set[T] diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index d3564017f9..de270a76f1 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -162,7 +162,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Register new context; called for every created context */ - def registerContext(c: analyzer.Context) {} + def registerContext(c: analyzer.Context) { + lastSeenContext = c + } /** Register top level class (called on entering the class) */ @@ -894,6 +896,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb curRun = null } + object typeDeconstruct extends { + val global: Global.this.type = Global.this + } with interpreter.StructuredTypeStrings + /** There are common error conditions where when the exception hits * here, currentRun.currentUnit is null. This robs us of the knowledge * of what file was being compiled when it broke. Since I really @@ -901,6 +907,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb */ private var lastSeenSourceFile: SourceFile = NoSourceFile + /** Let's share a lot more about why we crash all over the place. + * People will be very grateful. + */ + private var lastSeenContext: analyzer.Context = null + /** The currently active run */ def currentRun: Run = curRun @@ -929,25 +940,64 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op) @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op) + def explainContext(c: analyzer.Context): String = ( + if (c == null) "" else ( + """| context owners: %s + | + |Enclosing block or template: + |%s""".format( + c.owner.ownerChain.takeWhile(!_.isPackageClass).mkString(" -> "), + nodePrinters.nodeToString(c.enclClassOrMethod.tree) + ) + ) + ) + // Owners up to and including the first package class. + private def ownerChainString(sym: Symbol): String = ( + if (sym == null) "" + else sym.ownerChain.span(!_.isPackageClass) match { + case (xs, pkg :: _) => (xs :+ pkg) mkString " -> " + case _ => sym.ownerChain mkString " -> " // unlikely + } + ) + private def formatExplain(pairs: (String, Any)*): String = ( + pairs.toList collect { case (k, v) if v != null => "%20s: %s".format(k, v) } mkString "\n" + ) + + def explainTree(t: Tree): String = formatExplain( + ) + /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. */ override def supplementErrorMessage(errorMessage: String): String = try { - """| - | while compiling: %s - | current phase: %s - | library version: %s - | compiler version: %s - | reconstructed args: %s - | - |%s""".stripMargin.format( - currentSource.path, - phase, - scala.util.Properties.versionString, - Properties.versionString, - settings.recreateArgs.mkString(" "), - if (opt.debug) "Current unit body:\n" + currentUnit.body + "\n" + errorMessage else errorMessage + val tree = analyzer.lastTreeToTyper + val sym = tree.symbol + val tpe = tree.tpe + val enclosing = lastSeenContext.enclClassOrMethod.tree + + val info1 = formatExplain( + "while compiling" -> currentSource.path, + "during phase" -> phase, + "library version" -> scala.util.Properties.versionString, + "compiler version" -> Properties.versionString, + "reconstructed args" -> settings.recreateArgs.mkString(" ") + ) + val info2 = formatExplain( + "last tree to typer" -> tree.summaryString, + "symbol" -> Option(sym).fold("null")(_.debugLocationString), + "symbol definition" -> Option(sym).fold("null")(_.defString), + "tpe" -> tpe, + "symbol owners" -> ownerChainString(sym), + "context owners" -> ownerChainString(lastSeenContext.owner) ) + val info3: List[String] = ( + ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) ) + ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) ) + ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) + ++ ( List(errorMessage) ) + ) + + ("\n" + info1) :: info2 :: info3 mkString "\n\n" } catch { case x: Exception => errorMessage } diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index a93d9efded..23fcffd657 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -236,7 +236,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { mkMethodCall( PredefModule, wrapArrayMethodName(elemtp), - if (isScalaValueType(elemtp)) Nil else List(elemtp), + if (isPrimitiveValueType(elemtp)) Nil else List(elemtp), List(tree) ) } @@ -261,7 +261,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { * elem type elemtp to expected type pt. */ def mkCastArray(tree: Tree, elemtp: Type, pt: Type) = - if (elemtp.typeSymbol == AnyClass && isScalaValueType(tree.tpe.typeArgs.head)) + if (elemtp.typeSymbol == AnyClass && isPrimitiveValueType(tree.tpe.typeArgs.head)) mkCast(mkRuntimeCall(nme.toObjectArray, List(tree)), pt) else mkCast(tree, pt) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 4aeb537f9b..f7541a4739 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1208,7 +1208,7 @@ abstract class GenICode extends SubComponent { if (!tree.symbol.isPackageClass) tree.symbol else tree.symbol.info.member(nme.PACKAGE) match { case NoSymbol => assert(false, "Cannot use package as value: " + tree) ; NoSymbol - case s => Console.err.println("Bug: found package class where package object expected. Converting.") ; s.moduleClass + case s => debugwarn("Bug: found package class where package object expected. Converting.") ; s.moduleClass } ) debuglog("LOAD_MODULE from %s: %s".format(tree.shortClass, sym)) diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index 61f3670f5f..c3525037cd 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -179,7 +179,7 @@ trait ModelFactoryImplicitSupport { hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName)) // Filter out non-sensical conversions from value types - if (isScalaValueType(sym.tpe)) + if (isPrimitiveValueType(sym.tpe)) conversions = conversions.filter((ic: ImplicitConversion) => hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName)) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 9e7e4b3f4f..3625b19dd4 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -619,7 +619,7 @@ abstract class Erasure extends AddInterfaces tree.duplicate setType pt } else if (tree.tpe != null && tree.tpe.typeSymbol == ArrayClass && pt.typeSymbol == ArrayClass) { // See SI-2386 for one example of when this might be necessary. - val needsExtraCast = isScalaValueType(tree.tpe.typeArgs.head) && !isScalaValueType(pt.typeArgs.head) + val needsExtraCast = isPrimitiveValueType(tree.tpe.typeArgs.head) && !isPrimitiveValueType(pt.typeArgs.head) val tree1 = if (needsExtraCast) gen.mkRuntimeCall(nme.toObjectArray, List(tree)) else tree gen.mkAttributedCast(tree1, pt) } else gen.mkAttributedCast(tree, pt) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index aea29a27dd..7e780304e7 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -67,7 +67,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { import definitions.{ RootClass, BooleanClass, UnitClass, ArrayClass, - ScalaValueClasses, isPrimitiveValueClass, isScalaValueType, + ScalaValueClasses, isPrimitiveValueClass, isPrimitiveValueType, SpecializedClass, UnspecializedClass, AnyRefClass, ObjectClass, AnyRefModule, GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass } @@ -145,7 +145,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def includes(t1: TypeEnv, t2: TypeEnv) = t1 forall { case (sym, tpe) => t2 get sym exists { t2tp => - (tpe == t2tp) || !(isScalaValueType(tpe) || isScalaValueType(t2tp)) // u.t.b. (t2tp <:< AnyRefClass.tpe) + (tpe == t2tp) || !(isPrimitiveValueType(tpe) || isPrimitiveValueType(t2tp)) // u.t.b. (t2tp <:< AnyRefClass.tpe) } } @@ -266,7 +266,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * specialized type. */ def survivingArgs(sym: Symbol, args: List[Type]): List[Type] = - for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isScalaValueType(tpe)) + for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isPrimitiveValueType(tpe)) yield tpe val specializedType = new TypeMap { @@ -448,7 +448,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Type parameters that survive when specializing in the specified environment. */ def survivingParams(params: List[Symbol], env: TypeEnv) = - params.filter(p => !p.isSpecialized || !isScalaValueType(env(p))) + params.filter(p => !p.isSpecialized || !isPrimitiveValueType(env(p))) /** Produces the symbols from type parameters `syms` of the original owner, * in the given type environment `env`. The new owner is `nowner`. @@ -1588,7 +1588,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // val (_, origtparams) = splitParams(source.typeParams) val env = typeEnv(symbol) val boundTvars = env.keySet - val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam))) + val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isPrimitiveValueType(env(tparam))) if (origtparams.nonEmpty || symbol.typeParams.nonEmpty) debuglog("substituting " + origtparams + " for " + symbol.typeParams) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 484c8beb1b..6faa9a3cb7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -254,6 +254,12 @@ trait SyntheticMethods extends ast.TreeDSL { Block(valdef :: mixes, finish) } } + def chooseHashcode = { + if (accessors exists (x => isPrimitiveValueType(x.tpe.finalResultType))) + specializedHashcode + else + forwardToRuntime(Object_hashCode) + } def valueClassMethods = List( Any_hashCode -> (() => hashCodeDerivedValueClassMethod), @@ -261,7 +267,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def caseClassMethods = productMethods ++ productNMethods ++ Seq( - Object_hashCode -> (() => specializedHashcode), + Object_hashCode -> (() => chooseHashcode), Object_toString -> (() => forwardToRuntime(Object_toString)), Object_equals -> (() => equalsCaseClassMethod) ) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 343636ff1e..34e1aaedfd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -31,7 +31,6 @@ trait Typers extends Modes with Adaptations with Taggings { import global._ import definitions._ - import patmat.DefaultOverrideMatchAttachment final def forArgMode(fun: Tree, mode: Int) = @@ -85,6 +84,12 @@ trait Typers extends Modes with Adaptations with Taggings { private def isPastTyper = phase.id > currentRun.typerPhase.id + // To enable decent error messages when the typer crashes. + // TODO - this only catches trees which go through def typed, + // but there are all kinds of back ways - typedClassDef, etc. etc. + // Funnel everything through one doorway. + var lastTreeToTyper: Tree = EmptyTree + // when true: // - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope) // - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction @@ -4972,6 +4977,7 @@ trait Typers extends Modes with Adaptations with Taggings { * @return ... */ def typed(tree: Tree, mode: Int, pt: Type): Tree = { + lastTreeToTyper = tree indentTyping() var alreadyTyped = false diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala index 750e270c18..5d994eeb37 100644 --- a/src/partest/scala/tools/partest/nest/SBTRunner.scala +++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala @@ -54,15 +54,17 @@ object SBTRunner extends DirectRunner { val config = parseArgs(args, CommandLineOptions()) fileManager.SCALAC_OPTS = config.scalacOptions fileManager.CLASSPATH = config.classpath getOrElse sys.error("No classpath set") + + def findClasspath(jar: String, name: String): Option[String] = { + val optJar = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches (".*"+jar+".*\\.jar"))).headOption + val optClassDir = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches (".*"+name+File.separator+"classes"))).headOption + optJar orElse optClassDir + } // Find scala library jar file... - val lib: Option[String] = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches ".*scala-library.*\\.jar")).headOption - fileManager.LATEST_LIB = lib getOrElse sys.error("No scala-library found! Classpath = " + fileManager.CLASSPATH) - val comp: Option[String] = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches ".*scala-compiler.*\\.jar")).headOption - fileManager.LATEST_COMP = comp getOrElse sys.error("No scala-compiler found! Classpath = " + fileManager.CLASSPATH) - val partest: Option[String] = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches ".*scala-partest.*\\.jar")).headOption - fileManager.LATEST_PARTEST = partest getOrElse sys.error("No scala-partest found! Classpath = " + fileManager.CLASSPATH) - val actors: Option[String] = (fileManager.CLASSPATH split File.pathSeparator filter (_ matches ".*scala-actors.*\\.jar")).headOption - fileManager.LATEST_ACTORS = actors getOrElse sys.error("No scala-actors found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_LIB = findClasspath("scala-library", "scala-library") getOrElse sys.error("No scala-library found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_COMP = findClasspath("scala-compiler", "scala-compiler") getOrElse sys.error("No scala-compiler found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_PARTEST = findClasspath("scala-partest", "partest") getOrElse sys.error("No scala-partest found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_ACTORS = findClasspath("scala-actors", "actors") getOrElse sys.error("No scala-actors found! Classpath = " + fileManager.CLASSPATH) // TODO - Do something useful here!!! fileManager.JAVAC_CMD = "javac" diff --git a/test/files/pos/t4651.scala b/test/files/pos/t4651.scala new file mode 100644 index 0000000000..0612a8fcfb --- /dev/null +++ b/test/files/pos/t4651.scala @@ -0,0 +1,12 @@ +object Test { + def analyze(x: Any) = x match { + case s: String => println("It's a string: " + s) + case 1 => println("It's a one") + case (a: Int, b) => println("It's a pair of and int " + a + + " and something " + b) + case 1 :: 2 :: _ => println("It's a list starting with 1, 2") + case List(a, b, c) => println("It's a three-element list with " + + a + ", " + b + ", " + c) + case _ => println("It's something different") + } +} diff --git a/test/files/run/t3702.check b/test/files/run/t3702.check new file mode 100644 index 0000000000..31c2ac4ed1 --- /dev/null +++ b/test/files/run/t3702.check @@ -0,0 +1,2 @@ +() +6 diff --git a/test/files/run/t3702.scala b/test/files/run/t3702.scala new file mode 100644 index 0000000000..021abcb625 --- /dev/null +++ b/test/files/run/t3702.scala @@ -0,0 +1,11 @@ +object Test { + def foo(h: Any, t: List[Any]) = h match { + case 5 :: _ => () + case List(from) => from + } + + def main(args: Array[String]): Unit = { + println(foo(5 :: Nil, List(1,2,3))) + println(foo(6 :: Nil, List(1,2,3))) + } +} diff --git a/test/files/run/t4482.check b/test/files/run/t4482.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/files/run/t4482.check @@ -0,0 +1 @@ +2 diff --git a/test/files/run/t4482.scala b/test/files/run/t4482.scala new file mode 100644 index 0000000000..392861c22e --- /dev/null +++ b/test/files/run/t4482.scala @@ -0,0 +1,15 @@ +trait Foo { def i: Int } +trait Bar + +case class Spam(i: Int) extends Foo with Bar + +object Test { + def matchParent(p:Any) = p match { + case f:Foo if f.i == 1 => 1 + case _:Bar => 2 + case _:Foo => 3 + } + def main(args: Array[String]): Unit = { + println(matchParent(Spam(3))) + } +} diff --git a/test/pending/pos/t1832.scala b/test/pending/pos/t1832.scala new file mode 100644 index 0000000000..bca863f4bd --- /dev/null +++ b/test/pending/pos/t1832.scala @@ -0,0 +1,10 @@ +// Edit by paulp: reduced. +trait Cloning { + trait Foo + def fn(g: Int => Unit): Foo + + implicit def mkStar(i: Int) = new { def *(a: Foo): Foo = null } + + val pool1 = 4 * fn { case i => i * 2 } + val pool2 = 4 * fn { case i: Int => i * 2 } +} diff --git a/test/pending/pos/t3439.scala b/test/pending/pos/t3439.scala new file mode 100644 index 0000000000..425f1aeeb5 --- /dev/null +++ b/test/pending/pos/t3439.scala @@ -0,0 +1,2 @@ +abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg } +case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg) diff --git a/test/pending/pos/t4717.scala b/test/pending/pos/t4717.scala index 43cf412bc6..7eaa3dd487 100644 --- a/test/pending/pos/t4717.scala +++ b/test/pending/pos/t4717.scala @@ -1,7 +1,7 @@ -trait Bug1[@specialized +A] extends TraversableOnce[A] { - def ++[B >: A](that: TraversableOnce[B]): Iterator[B] = new Iterator[B] { - lazy val it = that.toIterator - def hasNext = it.hasNext - def next = it.next +trait Bounds[@specialized A] { + // okay without `>: A` + def x[B >: A]: Unit = new Bounds[B] { + lazy val it = ??? // def or val okay + it } }
\ No newline at end of file diff --git a/test/pending/pos/t5091.scala b/test/pending/pos/t5091.scala new file mode 100644 index 0000000000..217e83f66d --- /dev/null +++ b/test/pending/pos/t5091.scala @@ -0,0 +1,11 @@ +object RecursiveValueNeedsType { + + def foo(param: String) = 42 + def bar(n: Int) = 42 + + { + val xxx = foo(param = null) + val param = bar(xxx) + } + +} diff --git a/test/pending/pos/t5231.scala b/test/pending/pos/t5231.scala new file mode 100644 index 0000000000..77e6631ebb --- /dev/null +++ b/test/pending/pos/t5231.scala @@ -0,0 +1,18 @@ +object Client { + sealed trait ConfigLike { + def clientID: Int + } + + object Config { + def apply() : ConfigBuilder = new ConfigBuilder() + implicit def build( cb: ConfigBuilder ) : Config = cb.build + } + + final class Config private[Client]( val clientID: Int ) + extends ConfigLike + + final class ConfigBuilder private () extends ConfigLike { + var clientID: Int = 0 + def build : Config = new Config( clientID ) + } +} diff --git a/test/pending/pos/t5265.scala b/test/pending/pos/t5265.scala new file mode 100644 index 0000000000..3be7d2187e --- /dev/null +++ b/test/pending/pos/t5265.scala @@ -0,0 +1,21 @@ +import java.util.Date + +trait TDate + +trait TT[A1,T1] + +trait TTFactory[F,G] { + def create(f: F) : TT[F,G] + def sample: F +} + +object Impls { + + // If the c1 is declared before c2, it compiles fine + implicit def c2(s: Date) = c1.create(s) + + implicit val c1 = new TTFactory[Date,TDate] { + def create(v: Date): TT[Date,TDate] = sys.error("") + def sample = new Date + } +}
\ No newline at end of file |