summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-30 14:01:12 +0100
committeraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-30 14:01:12 +0100
commit5f4c97c448f161b3bab7ae3271e30620eb9bea76 (patch)
tree337ba5231b800c680869931af1184b3ed77a692b
parenta70d338afaef9a42bf13334267d07a43ad10c5c0 (diff)
parent5e9dd4a05c25f463f29d0fbc2f1bec194bf7700b (diff)
downloadscala-5f4c97c448f161b3bab7ae3271e30620eb9bea76.tar.gz
scala-5f4c97c448f161b3bab7ae3271e30620eb9bea76.tar.bz2
scala-5f4c97c448f161b3bab7ae3271e30620eb9bea76.zip
Merge branch 'master' into issue/5374
-rw-r--r--src/compiler/scala/reflect/internal/AnnotationCheckers.scala1
-rw-r--r--src/compiler/scala/reflect/internal/AnnotationInfos.scala2
-rw-r--r--src/compiler/scala/reflect/internal/BaseTypeSeqs.scala51
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala254
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala4
-rw-r--r--src/compiler/scala/reflect/internal/InfoTransformers.scala2
-rw-r--r--src/compiler/scala/reflect/internal/NameManglers.scala33
-rw-r--r--src/compiler/scala/reflect/internal/Names.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Scopes.scala50
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala2
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala12
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala237
-rw-r--r--src/compiler/scala/reflect/internal/TreePrinters.scala19
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala3
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala514
-rw-r--r--src/compiler/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/ConversionUtil.scala48
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala4
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala3
-rw-r--r--src/compiler/scala/reflect/runtime/Settings.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/SymbolTable.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedOps.scala51
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala119
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedTypes.scala87
-rw-r--r--src/compiler/scala/reflect/runtime/ToolBoxes.scala22
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala2
-rw-r--r--src/compiler/scala/tools/ant/sabbus/ScalacFork.scala3
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala124
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/MsilFile.scala4
-rw-r--r--src/compiler/scala/tools/nsc/io/NoAbstractFile.scala30
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala2
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala2
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala15
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala35
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala78
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala44
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala1056
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala133
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala139
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala352
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala42
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala148
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala110
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala78
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala167
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala110
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala1232
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala23
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala4
-rw-r--r--src/detach/plugin/scala/tools/detach/Detach.scala4
-rw-r--r--src/library/scala/collection/SeqLike.scala5
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala11
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala6
-rw-r--r--src/library/scala/collection/immutable/Range.scala36
-rw-r--r--src/library/scala/collection/immutable/Stream.scala10
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala3
-rw-r--r--src/library/scala/collection/parallel/Tasks.scala57
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashMap.scala19
-rw-r--r--src/library/scala/collection/parallel/package.scala2
-rw-r--r--src/library/scala/math/BigInt.scala6
-rwxr-xr-xsrc/library/scala/reflect/api/Names.scala33
-rwxr-xr-xsrc/library/scala/reflect/api/StandardDefinitions.scala4
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala91
-rw-r--r--src/library/scala/reflect/api/Trees.scala7
-rwxr-xr-xsrc/library/scala/reflect/api/Types.scala39
-rw-r--r--src/partest-alternative/README50
-rw-r--r--src/partest-alternative/scala/tools/partest/Actions.scala189
-rw-r--r--src/partest-alternative/scala/tools/partest/Alarms.scala86
-rw-r--r--src/partest-alternative/scala/tools/partest/BuildContributors.scala102
-rw-r--r--src/partest-alternative/scala/tools/partest/Categories.scala70
-rw-r--r--src/partest-alternative/scala/tools/partest/Compilable.scala106
-rw-r--r--src/partest-alternative/scala/tools/partest/Config.scala115
-rw-r--r--src/partest-alternative/scala/tools/partest/Dispatcher.scala162
-rw-r--r--src/partest-alternative/scala/tools/partest/Entities.scala74
-rw-r--r--src/partest-alternative/scala/tools/partest/Housekeeping.scala187
-rw-r--r--src/partest-alternative/scala/tools/partest/Partest.scala81
-rw-r--r--src/partest-alternative/scala/tools/partest/PartestSpec.scala104
-rw-r--r--src/partest-alternative/scala/tools/partest/Properties.scala17
-rw-r--r--src/partest-alternative/scala/tools/partest/Results.scala121
-rw-r--r--src/partest-alternative/scala/tools/partest/Runner.scala36
-rw-r--r--src/partest-alternative/scala/tools/partest/Statistics.scala46
-rw-r--r--src/partest-alternative/scala/tools/partest/Universe.scala96
-rw-r--r--src/partest-alternative/scala/tools/partest/ant/JavaTask.scala57
-rw-r--r--src/partest-alternative/scala/tools/partest/antlib.xml3
-rw-r--r--src/partest-alternative/scala/tools/partest/category/AllCategories.scala20
-rw-r--r--src/partest-alternative/scala/tools/partest/category/Analysis.scala64
-rw-r--r--src/partest-alternative/scala/tools/partest/category/Compiler.scala140
-rw-r--r--src/partest-alternative/scala/tools/partest/category/Runner.scala108
-rw-r--r--src/partest-alternative/scala/tools/partest/io/ANSIWriter.scala58
-rw-r--r--src/partest-alternative/scala/tools/partest/io/Diff.java873
-rw-r--r--src/partest-alternative/scala/tools/partest/io/DiffPrint.java606
-rw-r--r--src/partest-alternative/scala/tools/partest/io/JUnitReport.scala38
-rw-r--r--src/partest-alternative/scala/tools/partest/io/Logging.scala137
-rw-r--r--src/partest-alternative/scala/tools/partest/package.scala45
-rw-r--r--src/partest-alternative/scala/tools/partest/util/package.scala61
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala38
-rw-r--r--src/partest/scala/tools/partest/nest/AntRunner.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala3
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleFileManager.scala4
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala11
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/SBTRunner.scala23
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala5
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala2
-rw-r--r--test/files/buildmanager/t2790/t2790.check1
-rw-r--r--test/files/neg/nopredefs.check2
-rw-r--r--test/files/neg/sensitive2.check10
-rw-r--r--test/files/neg/sensitive2.scala8
-rw-r--r--test/files/neg/suggest-similar.check6
-rw-r--r--test/files/neg/t1878.check5
-rw-r--r--test/files/neg/t2641.check20
-rw-r--r--test/files/neg/t2870.check2
-rw-r--r--test/files/neg/t2918.check6
-rwxr-xr-xtest/files/neg/t2918.scala2
-rw-r--r--test/files/neg/t3015.check7
-rw-r--r--test/files/neg/t3854.check5
-rw-r--r--test/files/neg/t3854.scala15
-rw-r--r--test/files/neg/t4515.check6
-rw-r--r--test/files/neg/t4515.scala41
-rw-r--r--test/files/neg/t649.check2
-rw-r--r--test/files/pos/t3999b.scala20
-rw-r--r--test/files/pos/trait-force-info.flags1
-rw-r--r--test/files/pos/trait-force-info.scala18
-rw-r--r--test/files/run/macro-range/macro_range_1.scala17
-rw-r--r--test/files/run/macro-range/macro_range_2.scala17
-rw-r--r--test/files/run/range-unit.check4178
-rw-r--r--test/files/run/range-unit.scala55
-rw-r--r--test/files/run/reflection-implClass.scala16
-rw-r--r--test/files/run/si5262.check2
-rw-r--r--test/files/run/si5262.scala26
-rw-r--r--test/files/run/si5375.check1
-rw-r--r--test/files/run/si5375.scala19
-rw-r--r--test/files/run/t4835.check7
-rw-r--r--test/files/run/t4835.scala38
-rw-r--r--test/files/run/trait-renaming.check2
-rw-r--r--test/files/run/trait-renaming/A_1.scala15
-rw-r--r--test/files/run/trait-renaming/B_2.scala5
-rw-r--r--test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala30
-rw-r--r--test/pending/run/t5418.check0
-rw-r--r--test/pending/run/t5418.scala14
-rwxr-xr-xtools/binary-repo-lib.sh27
170 files changed, 8456 insertions, 6097 deletions
diff --git a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala b/src/compiler/scala/reflect/internal/AnnotationCheckers.scala
index 666c1d74cb..449b0ca0bc 100644
--- a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala
+++ b/src/compiler/scala/reflect/internal/AnnotationCheckers.scala
@@ -49,6 +49,7 @@ trait AnnotationCheckers {
def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree
}
+ // Syncnote: Annotation checkers inaccessible to reflection, so no sync in var necessary.
/** The list of annotation checkers that have been registered */
private var annotationCheckers: List[AnnotationChecker] = Nil
diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
index 255e69c3c6..c3dde3e6d1 100644
--- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
@@ -178,7 +178,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
private var rawpos: Position = NoPosition
def pos = rawpos
- def setPos(pos: Position): this.type = {
+ def setPos(pos: Position): this.type = { // Syncnote: Setpos inaccessible to reflection, so no sync in rawpos necessary.
rawpos = pos
this
}
diff --git a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala
index 38277b5a09..9e5c93753f 100644
--- a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala
@@ -29,7 +29,14 @@ trait BaseTypeSeqs {
this: SymbolTable =>
import definitions._
- class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
+ protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) =
+ new BaseTypeSeq(parents, elems)
+
+ /** Note: constructor is protected to force everyone to use the factory method newBaseTypeSeq instead.
+ * This is necessary because when run from reflection every base type sequence needs to have a
+ * SynchronizedBaseTypeSeq as mixin.
+ */
+ class BaseTypeSeq protected[BaseTypeSeqs] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) {
self =>
incCounter(baseTypeSeqCount)
incCounter(baseTypeSeqLenTotal, elems.length)
@@ -41,7 +48,7 @@ trait BaseTypeSeqs {
// (while NoType is in there to indicate a cycle in this BTS, during the execution of
// the mergePrefixAndArgs below, the elems get copied without the pending map,
// so that NoType's are seen instead of the original type --> spurious compile error)
- val pending = new mutable.BitSet(length)
+ private val pending = new mutable.BitSet(length)
/** The type at i'th position in this sequence; lazy types are returned evaluated. */
def apply(i: Int): Type =
@@ -89,11 +96,11 @@ trait BaseTypeSeqs {
/** Return all evaluated types in this sequence as a list */
def toList: List[Type] = elems.toList
- protected def copy(head: Type, offset: Int): BaseTypeSeq = {
+ def copy(head: Type, offset: Int): BaseTypeSeq = {
val arr = new Array[Type](elems.length + offset)
compat.Platform.arraycopy(elems, 0, arr, offset, elems.length)
arr(0) = head
- new BaseTypeSeq(parents, arr)
+ newBaseTypeSeq(parents, arr)
}
/** Compute new base type sequence with `tp` prepended to this sequence */
@@ -113,21 +120,10 @@ trait BaseTypeSeqs {
arr(i) = f(elems(i))
i += 1
}
- new BaseTypeSeq(parents, arr)
+ newBaseTypeSeq(parents, arr)
}
- def lateMap(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents map f, elems) {
- override def apply(i: Int) = f(self.apply(i))
- override def rawElem(i: Int) = f(self.rawElem(i))
- override def typeSymbol(i: Int) = self.typeSymbol(i)
- override def toList = self.toList map f
- override protected def copy(head: Type, offset: Int) = (self map f).copy(head, offset)
- override def map(g: Type => Type) = lateMap(g)
- override def lateMap(g: Type => Type) = self.lateMap(x => g(f(x)))
- override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
- override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max
- override def toString = elems.mkString("MBTS(", ",", ")")
- }
+ def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f)
def exists(p: Type => Boolean): Boolean = elems exists p
@@ -177,10 +173,10 @@ trait BaseTypeSeqs {
/** A merker object for a base type sequence that's no yet computed.
* used to catch inheritance cycles
*/
- val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(List(), Array())
+ val undetBaseTypeSeq: BaseTypeSeq = newBaseTypeSeq(List(), Array())
/** Create a base type sequence consisting of a single type */
- def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp))
+ def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = newBaseTypeSeq(List(), Array(tp))
/** Create the base type sequence of a compound type wuth given tp.parents */
def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = {
@@ -244,8 +240,21 @@ trait BaseTypeSeqs {
val elems = new Array[Type](btsSize)
buf.copyToArray(elems, 0)
// Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG
- new BaseTypeSeq(parents, elems)
+ newBaseTypeSeq(parents, elems)
}
-
+
+ class MappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) extends BaseTypeSeq(orig.parents map f, orig.elems) {
+ override def apply(i: Int) = f(orig.apply(i))
+ override def rawElem(i: Int) = f(orig.rawElem(i))
+ override def typeSymbol(i: Int) = orig.typeSymbol(i)
+ override def toList = orig.toList map f
+ override def copy(head: Type, offset: Int) = (orig map f).copy(head, offset)
+ override def map(g: Type => Type) = lateMap(g)
+ override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x)))
+ override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
+ override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max
+ override def toString = elems.mkString("MBTS(", ",", ")")
+ }
+
val CyclicInheritance = new Throwable
}
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index f7e276fdab..8114be20d5 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -14,9 +14,17 @@ import PartialFunction._
trait Definitions extends reflect.api.StandardDefinitions {
self: SymbolTable =>
+ /** Since both the value parameter types and the result type may
+ * require access to the type parameter symbols, we model polymorphic
+ * creation as a function from those symbols to (formal types, result type).
+ * The Option is to distinguish between nullary methods and empty-param-list
+ * methods.
+ */
+ private type PolyMethodCreator = List[Symbol] => (Option[List[Type]], Type)
+
private def newClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = {
val clazz = owner.newClassSymbol(name, NoPosition, flags)
- clazz setInfoAndEnter ClassInfoType(parents, new Scope, clazz)
+ clazz setInfoAndEnter ClassInfoType(parents, newScope, clazz)
}
private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol = {
val msym = owner.newMethod(name.encode, NoPosition, flags)
@@ -29,8 +37,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
self: definitions.type =>
private[Definitions] def valueCache(name: Name) = {
- if (name.isTypeName) ScalaPackageClass.info member name
- else ScalaPackageClass.info member name suchThat (_ hasFlag MODULE)
+ val res = (
+ if (name.isTypeName) ScalaPackageClass.info member name
+ else ScalaPackageClass.info member name suchThat (_ hasFlag MODULE)
+ )
+ if (res eq NoSymbol)
+ abort("Could not find value classes! This is a catastrophic failure. scala " + scala.util.Properties.versionString)
+ else res
}
private[Definitions] def valueModuleMethod(className: Name, methodName: Name): Symbol = {
valueCache(className.toTermName).moduleClass.tpe member methodName
@@ -206,7 +219,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) {
locally {
this initFlags ABSTRACT | TRAIT | FINAL
- this setInfoAndEnter ClassInfoType(List(parent.tpe), new Scope, this)
+ this setInfoAndEnter ClassInfoType(List(parent.tpe), newScope, this)
}
final override def isBottomClass = true
}
@@ -306,17 +319,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val RemoteInterfaceClass = getRequiredClass("java.rmi.Remote")
lazy val RemoteExceptionClass = getRequiredClass("java.rmi.RemoteException")
- lazy val RepeatedParamClass = newCovariantPolyClass(
- ScalaPackageClass,
- tpnme.REPEATED_PARAM_CLASS_NAME,
- tparam => seqType(tparam.typeConstructor)
- )
-
- lazy val JavaRepeatedParamClass = newCovariantPolyClass(
- ScalaPackageClass,
- tpnme.JAVA_REPEATED_PARAM_CLASS_NAME,
- tparam => arrayType(tparam.typeConstructor)
- )
+ lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyClass.typeConstructor)
+ lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.typeConstructor)
+ lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.typeConstructor))
+ lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.typeConstructor))
def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
@@ -345,15 +351,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
case _ => false
}
- lazy val ByNameParamClass = newCovariantPolyClass(
- ScalaPackageClass,
- tpnme.BYNAME_PARAM_CLASS_NAME,
- tparam => AnyClass.typeConstructor
- )
- lazy val EqualsPatternClass = {
- val clazz = newClass(ScalaPackageClass, tpnme.EQUALS_PATTERN_NAME, Nil)
- clazz setInfo polyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz))
- }
lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy")
// collections classes
@@ -424,24 +421,27 @@ trait Definitions extends reflect.api.StandardDefinitions {
* information into the toString method.
*/
def manifestToType(m: OptManifest[_]): Type = m match {
- case x: AnyValManifest[_] =>
- getClassIfDefined("scala." + x).tpe
case m: ClassManifest[_] =>
- val name = m.erasure.getName
- if (name endsWith nme.MODULE_SUFFIX_STRING)
- getModuleIfDefined(name stripSuffix nme.MODULE_SUFFIX_STRING).tpe
- else {
- val sym = getClassIfDefined(name)
- val args = m.typeArguments
-
- if (sym eq NoSymbol) NoType
- else if (args.isEmpty) sym.tpe
- else appliedType(sym.typeConstructor, args map manifestToType)
- }
+ val sym = manifestToSymbol(m)
+ val args = m.typeArguments
+
+ if ((sym eq NoSymbol) || args.isEmpty) sym.tpe
+ else appliedType(sym.typeConstructor, args map manifestToType)
case _ =>
NoType
}
+ def manifestToSymbol(m: ClassManifest[_]): Symbol = m match {
+ case x: scala.reflect.AnyValManifest[_] =>
+ getMember(ScalaPackageClass, newTypeName("" + x))
+ case _ =>
+ val name = m.erasure.getName
+ if (name endsWith nme.MODULE_SUFFIX_STRING)
+ getModuleIfDefined(name stripSuffix nme.MODULE_SUFFIX_STRING)
+ else
+ getClassIfDefined(name)
+ }
+
// The given symbol represents either String.+ or StringAdd.+
def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+
def isArrowAssoc(sym: Symbol) = ArrowAssocClass.tpe.decls.toList contains sym
@@ -589,6 +589,14 @@ trait Definitions extends reflect.api.StandardDefinitions {
case _ => NoType
}
+ /** To avoid unchecked warnings on polymorphic classes, translate
+ * a Foo[T] into a Foo[_] for use in the pattern matcher.
+ */
+ def typeCaseType(clazz: Symbol) = clazz.tpe.normalize match {
+ case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe)
+ case tp => tp
+ }
+
def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg))
def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg))
def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg))
@@ -610,7 +618,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val ValueTypeClass: Symbol = getClass(sn.ValueType)
// System.MulticastDelegate
lazy val DelegateClass: Symbol = getClass(sn.Delegate)
- var Delegate_scalaCallers: List[Symbol] = List()
+ var Delegate_scalaCallers: List[Symbol] = List() // Syncnote: No protection necessary yet as only for .NET where reflection is not supported.
// Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType)
// var Delegate_scalaCallerInfos: HashMap[Symbol, (Symbol, Type)] = _
lazy val Delegate_scalaCallerTargets: mutable.HashMap[Symbol, Symbol] = mutable.HashMap()
@@ -630,31 +638,40 @@ trait Definitions extends reflect.api.StandardDefinitions {
case _ => false
})
}
-
+
// members of class scala.Any
- var Any_== : Symbol = _
- var Any_!= : Symbol = _
- var Any_equals : Symbol = _
- var Any_hashCode : Symbol = _
- var Any_toString : Symbol = _
- var Any_getClass : Symbol = _
- var Any_isInstanceOf: Symbol = _
- var Any_asInstanceOf: Symbol = _
- var Any_## : Symbol = _
-
- // members of class java.lang.{Object, String}
- var Object_eq : Symbol = _
- var Object_ne : Symbol = _
- var Object_== : Symbol = _
- var Object_!= : Symbol = _
- var Object_## : Symbol = _
- var Object_synchronized: Symbol = _
- lazy val Object_isInstanceOf = newPolyMethod(
- ObjectClass, newTermName("$isInstanceOf"),
- tparam => MethodType(List(), booltype)) setFlag (FINAL | SYNTHETIC)
- lazy val Object_asInstanceOf = newPolyMethod(
- ObjectClass, newTermName("$asInstanceOf"),
- tparam => MethodType(List(), tparam.typeConstructor)) setFlag (FINAL | SYNTHETIC)
+ lazy val Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL)
+ lazy val Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype, FINAL)
+ lazy val Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype)
+ lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype)
+ lazy val Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype)
+ lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL)
+
+ // Any_getClass requires special handling. The return type is determined on
+ // a per-call-site basis as if the function being called were actually:
+ //
+ // // Assuming `target.getClass()`
+ // def getClass[T](target: T): Class[_ <: T]
+ //
+ // Since getClass is not actually a polymorphic method, this requires compiler
+ // participation. At the "Any" level, the return type is Class[_] as it is in
+ // java.lang.Object. Java also special cases the return type.
+ lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED)
+ lazy val Any_isInstanceOf = newT1NullaryMethod(AnyClass, nme.isInstanceOf_, FINAL)(_ => booltype)
+ lazy val Any_asInstanceOf = newT1NullaryMethod(AnyClass, nme.asInstanceOf_, FINAL)(_.typeConstructor)
+
+ // members of class java.lang.{ Object, String }
+ lazy val Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL)
+ lazy val Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL)
+ lazy val Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL)
+ lazy val Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL)
+ lazy val Object_ne = newMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL)
+ lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC)(_ => booltype)
+ lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC)(_.typeConstructor)
+ lazy val Object_synchronized = newPolyMethod(1, ObjectClass, nme.synchronized_, FINAL)(tps =>
+ (Some(List(tps.head.typeConstructor)), tps.head.typeConstructor)
+ )
+ lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL)
def Object_getClass = getMember(ObjectClass, nme.getClass_)
def Object_clone = getMember(ObjectClass, nme.clone_)
@@ -665,8 +682,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
def Object_hashCode = getMember(ObjectClass, nme.hashCode_)
def Object_toString = getMember(ObjectClass, nme.toString_)
- var String_+ : Symbol = _
-
// boxed classes
lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef")
lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef")
@@ -811,39 +826,36 @@ trait Definitions extends reflect.api.StandardDefinitions {
*/
private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length)
- private def newCovariantPolyClass(owner: Symbol, name: TypeName, parent: Symbol => Type): Symbol = {
- val clazz = newClass(owner, name, List())
- val tparam = newTypeParam(clazz, 0) setFlag COVARIANT
- val p = parent(tparam)
-/* p.typeSymbol.initialize
- println(p.typeSymbol + " flags: " + Flags.flagsToString(p.typeSymbol.flags))
- val parents = /*if (p.typeSymbol.isTrait)
- List(definitions.AnyRefClass.tpe, p)
- else*/ List(p)
- println("creating " + name + " with parents " + parents) */
- clazz.setInfo(
- polyType(
- List(tparam),
- ClassInfoType(List(AnyRefClass.tpe, p), new Scope, clazz)))
- }
-
private def newAlias(owner: Symbol, name: TypeName, alias: Type): Symbol =
owner.newAliasType(name) setInfoAndEnter alias
-
- /** tcon receives the type parameter symbol as argument */
- private def newPolyMethod(owner: Symbol, name: TermName, tcon: Symbol => Type): Symbol =
- newPolyMethodCon(owner, name, tparam => msym => tcon(tparam))
-
- /** tcon receives the type parameter symbol and the method symbol as arguments */
- private def newPolyMethodCon(owner: Symbol, name: TermName, tcon: Symbol => Symbol => Type): Symbol = {
- val msym = owner.info.decls enter owner.newMethod(name.encode)
- val tparam = newTypeParam(msym, 0)
-
- msym setInfo polyType(List(tparam), tcon(tparam)(msym))
+
+ private def specialPolyClass(name: TypeName, flags: Long)(parentFn: Symbol => Type): Symbol = {
+ val clazz = newClass(ScalaPackageClass, name, Nil)
+ val tparam = clazz.newSyntheticTypeParam("T0", flags)
+ val parents = List(AnyRefClass.tpe, parentFn(tparam))
+
+ clazz setInfo polyType(List(tparam), ClassInfoType(parents, newScope, clazz))
}
+
+ def newPolyMethod(typeParamCount: Int, owner: Symbol, name: TermName, flags: Long)(createFn: PolyMethodCreator): Symbol = {
+ val msym = owner.newMethod(name.encode, NoPosition, flags)
+ val tparams = msym.newSyntheticTypeParams(typeParamCount)
+ val mtpe = createFn(tparams) match {
+ case (Some(formals), restpe) => MethodType(msym.newSyntheticValueParams(formals), restpe)
+ case (_, restpe) => NullaryMethodType(restpe)
+ }
- private def newTypeParam(owner: Symbol, index: Int): Symbol =
- owner.newTypeParameter(newTypeName("T" + index)) setInfo TypeBounds.empty
+ msym setInfoAndEnter polyType(tparams, mtpe)
+ }
+
+ /** T1 means one type parameter.
+ */
+ def newT1NullaryMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = {
+ newPolyMethod(1, owner, name, flags)(tparams => (None, createFn(tparams.head)))
+ }
+ def newT1NoParamsMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = {
+ newPolyMethod(1, owner, name, flags)(tparams => (Some(Nil), createFn(tparams.head)))
+ }
lazy val boxedClassValues = boxedClass.values.toSet
lazy val isUnbox = unboxMethod.values.toSet
@@ -941,43 +953,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
RootClass.info.decls enter EmptyPackage
RootClass.info.decls enter RootPackage
-
- // members of class scala.Any
- Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL)
- Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype, FINAL)
- Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype)
- Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype)
- Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype)
- Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL)
-
- // Any_getClass requires special handling. The return type is determined on
- // a per-call-site basis as if the function being called were actually:
- //
- // // Assuming `target.getClass()`
- // def getClass[T](target: T): Class[_ <: T]
- //
- // Since getClass is not actually a polymorphic method, this requires compiler
- // participation. At the "Any" level, the return type is Class[_] as it is in
- // java.lang.Object. Java also special cases the return type.
- Any_getClass =
- newMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED)
- Any_isInstanceOf = newPolyMethod(
- AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL
- Any_asInstanceOf = newPolyMethod(
- AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL
-
- // members of class java.lang.{ Object, String }
- Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL)
- Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL)
- Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL)
- Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL)
- Object_ne = newMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL)
- Object_synchronized = newPolyMethodCon(
- ObjectClass, nme.synchronized_,
- tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL
-
- String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL)
-
+
val forced = List( // force initialization of every symbol that is entered as a side effect
AnnotationDefaultAttr, // #2264
RepeatedParamClass,
@@ -990,8 +966,24 @@ trait Definitions extends reflect.api.StandardDefinitions {
NothingClass,
SingletonClass,
EqualsPatternClass,
+ Any_==,
+ Any_!=,
+ Any_equals,
+ Any_hashCode,
+ Any_toString,
+ Any_getClass,
+ Any_isInstanceOf,
+ Any_asInstanceOf,
+ Any_##,
+ Object_eq,
+ Object_ne,
+ Object_==,
+ Object_!=,
+ Object_##,
+ Object_synchronized,
Object_isInstanceOf,
- Object_asInstanceOf
+ Object_asInstanceOf,
+ String_+
)
/** Removing the anyref parent they acquire from having a source file.
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala
index 53380952c0..23b443919a 100644
--- a/src/compiler/scala/reflect/internal/Importers.scala
+++ b/src/compiler/scala/reflect/internal/Importers.scala
@@ -210,9 +210,9 @@ trait Importers { self: SymbolTable =>
result
}
- // !!! todo: override to vcater for PackageScopes
+ // !!! todo: override to cater for PackageScopes
def importScope(decls: from.Scope): Scope =
- new Scope(decls.toList map importSymbol)
+ newScopeWith(decls.toList map importSymbol: _*)
def importName(name: from.Name): Name =
if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString)
diff --git a/src/compiler/scala/reflect/internal/InfoTransformers.scala b/src/compiler/scala/reflect/internal/InfoTransformers.scala
index 9c54b1b4cd..96d9d8f076 100644
--- a/src/compiler/scala/reflect/internal/InfoTransformers.scala
+++ b/src/compiler/scala/reflect/internal/InfoTransformers.scala
@@ -9,6 +9,8 @@ package internal
trait InfoTransformers {
self: SymbolTable =>
+ /* Syncnote: This should not need to be protected, as reflection does not run in multiple phases.
+ */
abstract class InfoTransformer {
var prev: InfoTransformer = this
var next: InfoTransformer = this
diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala
index ef092f16bb..97a74c2383 100644
--- a/src/compiler/scala/reflect/internal/NameManglers.scala
+++ b/src/compiler/scala/reflect/internal/NameManglers.scala
@@ -85,7 +85,7 @@ trait NameManglers {
def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
- def isImplClassName(name: Name) = stripAnonNumberSuffix(name) endsWith IMPL_CLASS_SUFFIX
+ def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
@@ -176,25 +176,18 @@ trait NameManglers {
else name.toTermName
}
- /** !!! I'm putting this logic in place because I can witness
- * trait impls get lifted and acquiring names like 'Foo$class$1'
- * while clearly still being what they were. It's only being used on
- * isImplClassName. However, it's anyone's guess how much more
- * widely this logic actually ought to be applied. Anything which
- * tests for how a name ends is a candidate for breaking down once
- * something is lifted from a method.
- *
- * TODO: resolve this significant problem.
- */
- def stripAnonNumberSuffix(name: Name): Name = {
- val str = "" + name
- if (str == "" || !str.endChar.isDigit) name
- else {
- val idx = name.lastPos('$')
- if (idx < 0 || str.substring(idx + 1).exists(c => !c.isDigit)) name
- else name.subName(0, idx)
- }
- }
+ // This isn't needed at the moment since I fixed $class$1 but
+ // I expect it will be at some point.
+ //
+ // def anonNumberSuffix(name: Name): Name = {
+ // ("" + name) lastIndexOf '$' match {
+ // case -1 => nme.EMPTY
+ // case idx =>
+ // val s = name drop idx
+ // if (s.toString forall (_.isDigit)) s
+ // else nme.EMPTY
+ // }
+ // }
def stripModuleSuffix(name: Name): Name = (
if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name
diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/compiler/scala/reflect/internal/Names.scala
index b960695f51..907b564d4c 100644
--- a/src/compiler/scala/reflect/internal/Names.scala
+++ b/src/compiler/scala/reflect/internal/Names.scala
@@ -77,7 +77,11 @@ trait Names extends api.Names {
def newTermName(cs: Array[Char]): TermName = newTermName(cs, 0, cs.length)
def newTypeName(cs: Array[Char]): TypeName = newTypeName(cs, 0, cs.length)
- /** Create a term name from the characters in cs[offset..offset+len-1]. */
+ /** Create a term name from the characters in cs[offset..offset+len-1].
+ * TODO - have a mode where name validation is performed at creation time
+ * (e.g. if a name has the string "$class" in it, then fail if that
+ * string is not at the very end.)
+ */
protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = {
val h = hashValue(cs, offset, len) & HASH_MASK
var n = termHashtable(h)
diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala
index fb3012adff..54d3de09cd 100644
--- a/src/compiler/scala/reflect/internal/Scopes.scala
+++ b/src/compiler/scala/reflect/internal/Scopes.scala
@@ -37,9 +37,18 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
def unapplySeq(decls: Scope): Some[Seq[Symbol]] = Some(decls.toList)
}
- class Scope(initElems: ScopeEntry) extends Iterable[Symbol] {
+ /** Note: constructor is protected to force everyone to use the factory methods newScope or newNestedScope instead.
+ * This is necessary because when run from reflection every scope needs to have a
+ * SynchronizedScope as mixin.
+ */
+ class Scope protected[Scopes] (initElems: ScopeEntry = null) extends Iterable[Symbol] {
+
+ protected[Scopes] def this(base: Scope) = {
+ this(base.elems)
+ nestinglevel = base.nestinglevel + 1
+ }
- var elems: ScopeEntry = initElems
+ private[scala] var elems: ScopeEntry = initElems
/** The number of times this scope is nested in another
*/
@@ -65,20 +74,8 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
if (size >= MIN_HASH) createHash()
- def this() = this(null: ScopeEntry)
-
- def this(base: Scope) = {
- this(base.elems)
- nestinglevel = base.nestinglevel + 1
- }
-
- def this(decls: List[Symbol]) = {
- this()
- decls foreach enter
- }
-
/** Returns a new scope with the same content as this one. */
- def cloneScope: Scope = new Scope(this.toList)
+ def cloneScope: Scope = newScopeWith(this.toList: _*)
/** is the scope empty? */
override def isEmpty: Boolean = elems eq null
@@ -311,7 +308,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
override def foreach[U](p: Symbol => U): Unit = toList foreach p
override def filter(p: Symbol => Boolean): Scope =
- if (!(toList forall p)) new Scope(toList filter p) else this
+ if (!(toList forall p)) newScopeWith(toList filter p: _*) else this
override def mkString(start: String, sep: String, end: String) =
toList.map(_.defString).mkString(start, sep, end)
@@ -321,21 +318,26 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
}
/** Create a new scope */
- def newScope: Scope = new Scope
+ def newScope: Scope = new Scope()
+
+ /** Create a new scope nested in another one with which it shares its elements */
+ def newNestedScope(outer: Scope): Scope = new Scope(outer)
+
+ /** Create a new scope with given initial elements */
+ def newScopeWith(elems: Symbol*): Scope = {
+ val scope = newScope
+ elems foreach scope.enter
+ scope
+ }
/** Create new scope for the members of package `pkg` */
- def newPackageScope(pkgClass: Symbol): Scope = new Scope
+ def newPackageScope(pkgClass: Symbol): Scope = newScope
/** Transform scope of members of `owner` using operation `op`
* This is overridden by the reflective compiler to avoid creating new scopes for packages
*/
def scopeTransform(owner: Symbol)(op: => Scope): Scope = op
- def newScopeWith(elems: Symbol*): Scope = {
- val scope = newScope
- elems foreach scope.enter
- scope
- }
/** The empty scope (immutable).
*/
@@ -347,7 +349,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** The error scope.
*/
- class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry)
+ class ErrorScope(owner: Symbol) extends Scope
private final val maxRecursions = 1000
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index aba00088f9..b3069adfb4 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -291,6 +291,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val array_update : NameType = "array_update"
val arraycopy: NameType = "arraycopy"
val asInstanceOf_ : NameType = "asInstanceOf"
+ val asInstanceOf_Ob : NameType = "$asInstanceOf"
val asTypeConstructor: NameType = "asTypeConstructor"
val assert_ : NameType = "assert"
val assume_ : NameType = "assume"
@@ -336,6 +337,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val isDefinedAt: NameType = "isDefinedAt"
val isEmpty: NameType = "isEmpty"
val isInstanceOf_ : NameType = "isInstanceOf"
+ val isInstanceOf_Ob : NameType = "$isInstanceOf"
val java: NameType = "java"
val lang: NameType = "lang"
val length: NameType = "length"
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index ace4d55b90..fb827b0658 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -33,12 +33,17 @@ abstract class SymbolTable extends api.Universe
{
def rootLoader: LazyType
def log(msg: => AnyRef): Unit
- def abort(msg: String): Nothing = throw new FatalError(msg)
+ def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
+
+ @deprecated("2.10.0", "Give us a reason")
def abort(): Nothing = abort("unknown error")
/** Override with final implementation for inlining. */
def debuglog(msg: => String): Unit = if (settings.debug.value) log(msg)
def debugwarn(msg: => String): Unit = if (settings.debug.value) Console.err.println(msg)
+
+ /** Overridden when we know more about what was happening during a failure. */
+ def supplementErrorMessage(msg: String): String = msg
private[scala] def printResult[T](msg: String)(result: T) = {
Console.err.println(msg + ": " + result)
@@ -271,4 +276,9 @@ abstract class SymbolTable extends api.Universe
/** The phase which has given index as identifier. */
val phaseWithId: Array[Phase]
+
+ /** Is this symbol table part of reflexive mirror? In this case
+ * operations need to be made thread safe.
+ */
+ def inReflexiveMirror = false
}
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 0e729bc7ea..94d764067f 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -16,10 +16,13 @@ import api.Modifier
trait Symbols extends api.Symbols { self: SymbolTable =>
import definitions._
- private var ids = 0
+ protected var ids = 0
+
+ val emptySymbolArray = new Array[Symbol](0)
+
def symbolCount = ids // statistics
- val emptySymbolArray = new Array[Symbol](0)
+ protected def nextId() = { ids += 1; ids }
/** Used for deciding in the IDE whether we can interrupt the compiler */
//protected var activeLocks = 0
@@ -31,7 +34,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var recursionTable = immutable.Map.empty[Symbol, Int]
private var nextexid = 0
- private def freshExistentialName(suffix: String) = {
+ protected def freshExistentialName(suffix: String) = {
nextexid += 1
newTypeName("_" + nextexid + suffix)
}
@@ -42,6 +45,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
m setModuleClass moduleClass
m
}
+
/** Create a new free variable. Its owner is NoSymbol.
*/
def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar =
@@ -68,7 +72,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** The class for all symbols */
- abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name)
+ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name)
extends AbsSymbolImpl
with HasFlags
with Annotatable[Symbol] {
@@ -77,14 +81,24 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
type AccessBoundaryType = Symbol
type AnnotationType = AnnotationInfo
- var rawowner = initOwner
- var rawname = initName
- var rawflags = 0L
-
+ private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api
+ private[this] var _rawname = initName
+ private[this] var _rawflags = 0L
+
+ def rawowner = _rawowner
+ def rawname = _rawname
+ def rawflags = _rawflags
+
+ protected def rawflags_=(x: FlagsType) { _rawflags = x }
+
private var rawpos = initPos
- val id = { ids += 1; ids } // identity displayed when -uniqid
+
+ val id = nextId() // identity displayed when -uniqid
- var validTo: Period = NoPeriod
+ private[this] var _validTo: Period = NoPeriod
+
+ def validTo = _validTo
+ def validTo_=(x: Period) { _validTo = x}
def pos = rawpos
def setPos(pos: Position): this.type = { this.rawpos = pos; this }
@@ -237,6 +251,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def freshName() = { cnt += 1; nme.syntheticParamName(cnt) }
mmap(argtypess)(tp => newValueParameter(freshName(), focusPos(owner.pos), SYNTHETIC) setInfo tp)
}
+
+ def newSyntheticTypeParam(): Symbol = newSyntheticTypeParam("T0", 0L)
+ def newSyntheticTypeParam(name: String, newFlags: Long): Symbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty
+ def newSyntheticTypeParams(num: Int): List[Symbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L))
/** Create a new existential type skolem with this symbol its owner,
* based on the given symbol and origin.
@@ -336,7 +354,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// True if the symbol is unlocked.
// True if the symbol is locked but still below the allowed recursion depth.
// False otherwise
- def lockOK: Boolean = {
+ private[scala] def lockOK: Boolean = {
((rawflags & LOCKED) == 0L) ||
((settings.Yrecursion.value != 0) &&
(recursionTable get this match {
@@ -345,33 +363,37 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
// Lock a symbol, using the handler if the recursion depth becomes too great.
- def lock(handler: => Unit) = {
+ private[scala] def lock(handler: => Unit): Boolean = {
if ((rawflags & LOCKED) != 0L) {
if (settings.Yrecursion.value != 0) {
recursionTable get this match {
case Some(n) =>
if (n > settings.Yrecursion.value) {
handler
+ false
} else {
recursionTable += (this -> (n + 1))
+ true
}
case None =>
recursionTable += (this -> 1)
+ true
}
- } else { handler }
+ } else { handler; false }
} else {
rawflags |= LOCKED
+ true
// activeLocks += 1
// lockedSyms += this
}
}
// Unlock a symbol
- def unlock() = {
+ private[scala] def unlock() = {
if ((rawflags & LOCKED) != 0L) {
// activeLocks -= 1
// lockedSyms -= this
- rawflags = rawflags & ~LOCKED
+ _rawflags = rawflags & ~LOCKED
if (settings.Yrecursion.value != 0)
recursionTable -= this
}
@@ -736,7 +758,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ owner attribute --------------------------------------------------------------
def owner: Symbol = rawowner
- final def owner_=(owner: Symbol) {
+ def owner_=(owner: Symbol) {
// don't keep the original owner in presentation compiler runs
// (the map will grow indefinitely, and the only use case is the
// backend).
@@ -744,8 +766,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (originalOwner contains this) ()
else originalOwner(this) = rawowner
}
-
- rawowner = owner
+ assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code")
+ _rawowner = owner
}
def ownerChain: List[Symbol] = this :: owner.ownerChain
@@ -778,7 +800,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def name: Name = rawname
- final def name_=(name: Name) {
+ def name_=(name: Name) {
if (name != rawname) {
if (owner.isClass) {
var ifs = owner.infos
@@ -787,7 +809,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
ifs = ifs.prev
}
}
- rawname = name
+ _rawname = name
}
}
@@ -855,20 +877,20 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val fs = rawflags & phase.flagMask
(fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
}
- final def flags_=(fs: Long) = rawflags = fs
+ def flags_=(fs: Long) = _rawflags = fs
/** Set the symbol's flags to the given value, asserting
* that the previous value was 0.
*/
def initFlags(mask: Long): this.type = {
assert(rawflags == 0L, this)
- rawflags = mask
+ _rawflags = mask
this
}
- def setFlag(mask: Long): this.type = { rawflags = rawflags | mask ; this }
- def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask ; this }
+ def setFlag(mask: Long): this.type = { _rawflags = rawflags | mask ; this }
+ def resetFlag(mask: Long): this.type = { _rawflags = rawflags & ~mask ; this }
final def getFlag(mask: Long): Long = flags & mask
- final def resetFlags() { rawflags = rawflags & TopLevelCreationFlags }
+ final def resetFlags() { _rawflags = rawflags & TopLevelCreationFlags }
/** Does symbol have ANY flag in `mask` set? */
final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L
@@ -954,7 +976,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
throw CyclicReference(this, tp)
}
} else {
- rawflags |= LOCKED
+ _rawflags |= LOCKED
// activeLocks += 1
// lockedSyms += this
}
@@ -963,7 +985,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
phase = phaseOf(infos.validFrom)
tp.complete(this)
} finally {
- // if (id == 431) println("completer ran "+tp.getClass+" for "+fullName)
unlock()
phase = current
}
@@ -984,7 +1005,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
assert(info ne null)
infos = TypeHistory(currentPeriod, info, null)
unlock()
- validTo = if (info.isComplete) currentPeriod else NoPeriod
+ _validTo = if (info.isComplete) currentPeriod else NoPeriod
}
/** Set initial info. */
@@ -1003,11 +1024,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** Set new info valid from start of this phase. */
- final def updateInfo(info: Type): Symbol = {
+ def updateInfo(info: Type): Symbol = {
assert(phaseId(infos.validFrom) <= phase.id)
if (phaseId(infos.validFrom) == phase.id) infos = infos.prev
infos = TypeHistory(currentPeriod, info, infos)
- validTo = if (info.isComplete) currentPeriod else NoPeriod
+ _validTo = if (info.isComplete) currentPeriod else NoPeriod
this
}
@@ -1045,11 +1066,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
infos = TypeHistory(currentPeriod + 1, info1, infos)
this.infos = infos
}
- validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
+ _validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform
itr = itr.next
}
- validTo = if (itr.pid == NoPhase.id) curPeriod
- else period(currentRunId, itr.pid)
+ _validTo = if (itr.pid == NoPhase.id) curPeriod
+ else period(currentRunId, itr.pid)
}
} finally {
phase = current
@@ -1060,7 +1081,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
// adapt to new run in fsc.
- private def adaptInfos(infos: TypeHistory): TypeHistory =
+ private def adaptInfos(infos: TypeHistory): TypeHistory = {
+ assert(!inReflexiveMirror)
if (infos == null || runId(infos.validFrom) == currentRunId) {
infos
} else {
@@ -1069,7 +1091,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else {
val pid = phaseId(infos.validFrom)
- validTo = period(currentRunId, pid)
+ _validTo = period(currentRunId, pid)
phase = phaseWithId(pid)
val info1 = (
@@ -1085,6 +1107,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
}
+ }
/** Initialize the symbol */
final def initialize: this.type = {
@@ -1094,6 +1117,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Was symbol's type updated during given phase? */
final def isUpdatedAt(pid: Phase#Id): Boolean = {
+ assert(!inReflexiveMirror)
var infos = this.infos
while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev
infos ne null
@@ -1101,6 +1125,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Was symbol's type updated during given phase? */
final def hasTypeAt(pid: Phase#Id): Boolean = {
+ assert(!inReflexiveMirror)
var infos = this.infos
while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev
infos ne null
@@ -1212,7 +1237,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def reset(completer: Type) {
resetFlags()
infos = null
- validTo = NoPeriod
+ _validTo = NoPeriod
//limit = NoPhase.id
setInfo(completer)
}
@@ -1239,7 +1264,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ----- annotations ------------------------------------------------------------
// null is a marker that they still need to be obtained.
- private var _annotations: List[AnnotationInfo] = Nil
+ private[this] var _annotations: List[AnnotationInfo] = Nil
def annotationsString = if (annotations.isEmpty) "" else annotations.mkString("(", ", ", ")")
@@ -1425,7 +1450,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def sourceModule: Symbol = NoSymbol
- /** The implementation class of a trait. */
+ /** The implementation class of a trait. If available it will be the
+ * symbol with the same owner, and the name of this symbol with $class
+ * appended to it.
+ */
final def implClass: Symbol = owner.info.decl(nme.implClassName(name))
/** The class that is logically an outer class of given `clazz`.
@@ -1804,6 +1832,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
+ /** Remove any access boundary and clear flags PROTECTED | PRIVATE.
+ */
+ def makePublic = this setPrivateWithin NoSymbol resetFlag AccessFlags
+
+ /** The first parameter to the first argument list of this method,
+ * or NoSymbol if inapplicable.
+ */
+ def firstParam = info.params match {
+ case p :: _ => p
+ case _ => NoSymbol
+ }
+
/** change name by appending $$<fully-qualified-name-of-class `base`>
* Do the same for any accessed symbols or setters/getters
*/
@@ -1874,36 +1914,43 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else if (isTerm && (!isParameter || isParamAccessor)) "val"
else ""
+ private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String)
+ private def symbolKind: SymbolKind = {
+ val kind =
+ if (isInstanceOf[FreeVar]) ("free variable", "free variable", "FV")
+ else if (isPackage) ("package", "package", "PK")
+ else if (isPackageClass) ("package class", "package", "PKC")
+ else if (isPackageObject) ("package object", "package", "PKO")
+ else if (isPackageObjectClass) ("package object class", "package", "PKOC")
+ else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC")
+ else if (isRefinementClass) ("refinement class", "", "RC")
+ else if (isModule) ("module", "object", "MOD")
+ else if (isModuleClass) ("module class", "object", "MODC")
+ else if (isGetter) ("getter", if (isSourceMethod) "method" else "value", "GET")
+ 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 (isTrait) ("trait", "trait", "TRT")
+ else if (isClass) ("class", "class", "CLS")
+ else if (isType) ("type", "type", "TPE")
+ else if (isClassConstructor) ("constructor", "constructor", "CTOR")
+ else if (isSourceMethod) ("method", "method", "METH")
+ else if (isTerm) ("value", "value", "VAL")
+ else ("", "", "???")
+ SymbolKind(kind._1, kind._2, kind._3)
+ }
+
/** Accurate string representation of symbols' kind, suitable for developers. */
final def accurateKindString: String =
- if (isPackage) "package"
- else if (isPackageClass) "package class"
- else if (isPackageObject) "package object"
- else if (isPackageObjectClass) "package object class"
- else if (isRefinementClass) "refinement class"
- else if (isModule) "module"
- else if (isModuleClass) "module class"
- else if (isGetter) "getter"
- else if (isSetter) "setter"
- else if (isVariable) "field"
- else sanitizedKindString
+ symbolKind.accurate
/** String representation of symbol's kind, suitable for the masses. */
private def sanitizedKindString: String =
- if (isPackage || isPackageClass) "package"
- else if (isModule || isModuleClass) "object"
- else if (isAnonymousClass) "anonymous class"
- else if (isRefinementClass) ""
- else if (isTrait) "trait"
- else if (isClass) "class"
- else if (isType) "type"
- else if (isInstanceOf[FreeVar]) "free variable"
- else if (isTerm && isLazy) "lazy value"
- else if (isVariable) "variable"
- else if (isClassConstructor) "constructor"
- else if (isSourceMethod) "method"
- else if (isTerm) "value"
- else ""
+ symbolKind.sanitized
+
+ /** String representation of symbol's kind, suitable for the masses. */
+ protected[scala] def abbreviatedKindString: String =
+ symbolKind.abbreviation
final def kindString: String =
if (settings.debug.value) accurateKindString
@@ -1926,12 +1973,25 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If !settings.debug translates expansions of operators back to operator symbol.
* E.g. $eq => =.
* If settings.uniqid, adds id.
+ * If settings.Yshowsymkinds, adds abbreviated symbol kind.
*/
def nameString: String = (
- if (settings.uniqid.value) decodedName + "#" + id
- else "" + decodedName
+ if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + decodedName
+ else if (settings.uniqid.value && !settings.Yshowsymkinds.value) decodedName + "#" + id
+ else if (!settings.uniqid.value && settings.Yshowsymkinds.value) decodedName + "#" + abbreviatedKindString
+ else decodedName + "#" + id + "#" + abbreviatedKindString
)
+ def fullNameString: String = {
+ def recur(sym: Symbol): String = {
+ if (sym.isRoot || sym.isRootPackage || sym == NoSymbol) sym.nameString
+ else if (sym.owner.isEffectiveRoot) sym.nameString
+ else recur(sym.effectiveOwner.enclClass) + "." + sym.nameString
+ }
+
+ recur(this)
+ }
+
/** If settings.uniqid is set, the symbol's id, else "" */
final def idString = if (settings.uniqid.value) "#"+id else ""
@@ -2046,15 +2106,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** A class for term symbols */
- class TermSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
extends Symbol(initOwner, initPos, initName) {
final override def isTerm = true
override def name: TermName = rawname.toTermName
privateWithin = NoSymbol
- var referenced: Symbol = NoSymbol
-
+ private[this] var _referenced: Symbol = NoSymbol
+
+ def referenced: Symbol = _referenced
+ def referenced_=(x: Symbol) { _referenced = x }
+
def existentialBound = singletonBounds(this.tpe)
def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
@@ -2136,7 +2199,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** A class for module symbols */
- class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
extends TermSymbol(initOwner, initPos, initName) {
private var flatname: TermName = null
@@ -2159,7 +2222,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** A class for method symbols */
- class MethodSymbol(initOwner: Symbol, initPos: Position, initName: TermName)
+ class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
extends TermSymbol(initOwner, initPos, initName) {
private var mtpePeriod = NoPeriod
private var mtpePre: Type = _
@@ -2185,7 +2248,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
- class AliasTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
+ class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
extends TypeSymbol(initOwner, initPos, initName) {
// Temporary programmatic help tracking down who might do such a thing
override def setFlag(mask: Long): this.type = {
@@ -2226,7 +2289,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** A class of type symbols. Alias and abstract types are direct instances
* of this class. Classes are instances of a subclass.
*/
- sealed abstract class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) {
+ abstract class TypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) {
privateWithin = NoSymbol
private var tyconCache: Type = null
private var tyconRunId = NoRunId
@@ -2364,7 +2427,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*
* origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL)
*/
- class TypeSkolem(initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
+ class TypeSkolem protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
extends TypeSymbol(initOwner, initPos, initName) {
/** The skolemization level in place when the skolem was constructed */
@@ -2393,11 +2456,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** A class for class symbols */
- class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
+ class ClassSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
extends TypeSymbol(initOwner, initPos, initName) {
- private var flatname: TypeName = null
- private var source: AbstractFileType = null
- private var thissym: Symbol = this
+ private[this] var flatname: TypeName = null
+ private[this] var source: AbstractFileType = null
+ private[this] var thissym: Symbol = this
final override def isClass = true
final override def isNonClassType = false
@@ -2459,7 +2522,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
typeOfThisCache
}
- else thissym.tpe
+ else thisSym.tpe
}
/** Sets the self type of the class */
@@ -2479,7 +2542,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def sourceModule =
if (isModuleClass) companionModule else NoSymbol
- private var childSet: Set[Symbol] = Set()
+ private[this] var childSet: Set[Symbol] = Set()
override def children = childSet
override def addChild(sym: Symbol) { childSet = childSet + sym }
@@ -2490,7 +2553,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* Note: Not all module classes are of this type; when unpickled, we get
* plain class symbols!
*/
- class ModuleClassSymbol(owner: Symbol, pos: Position, name: TypeName)
+ class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName)
extends ClassSymbol(owner, pos, name) {
private var module: Symbol = null
private var implicitMembersCacheValue: List[Symbol] = List()
@@ -2523,10 +2586,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** An object representing a missing symbol */
- object NoSymbol extends Symbol(null, NoPosition, nme.NO_NAME) {
- setInfo(NoType)
- privateWithin = this
- override def info_=(info: Type) {
+ class NoSymbol protected[Symbols]() extends Symbol(null, NoPosition, nme.NO_NAME) {
+ synchronized {
+ setInfo(NoType)
+ privateWithin = this
+ }
+ override def info_=(info: Type) = {
infos = TypeHistory(1, NoType, null)
unlock()
validTo = currentPeriod
@@ -2557,6 +2622,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)")
}
+ protected def makeNoSymbol = new NoSymbol
+
+ lazy val NoSymbol = makeNoSymbol
+
/** Derives a new list of symbols from the given list by mapping the given
* list across the given function. Then fixes the info of all the new symbols
* by substituting the new symbols for the original symbols.
diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala
index dcc395ddd2..63e4c9f1fa 100644
--- a/src/compiler/scala/reflect/internal/TreePrinters.scala
+++ b/src/compiler/scala/reflect/internal/TreePrinters.scala
@@ -27,10 +27,20 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
/** Turns a path into a String, introducing backquotes
* as necessary.
*/
- def backquotedPath(t: Tree): String = t match {
- case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name))
- case Ident(name) => quotedName(name)
- case _ => t.toString
+ def backquotedPath(t: Tree): String = {
+ def suffix(t: Tree) = {
+ var suffix = ""
+ if (t.hasSymbol && settings.uniqid.value) suffix += ("#" + t.symbol.id)
+ if (t.hasSymbol && settings.Yshowsymkinds.value) suffix += ("#" + t.symbol.abbreviatedKindString)
+ suffix
+ }
+
+ t match {
+ case Select(qual, name) if name.isTermName => "%s.%s".format(backquotedPath(qual), quotedName(name)) + suffix(t)
+ case Select(qual, name) if name.isTypeName => "%s#%s".format(backquotedPath(qual), quotedName(name)) + suffix(t)
+ case Ident(name) => quotedName(name) + suffix(t)
+ case _ => t.toString
+ }
}
class TreePrinter(out: PrintWriter) extends super.TreePrinter {
@@ -397,7 +407,6 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
// case SelectFromArray(qualifier, name, _) =>
// print(qualifier); print(".<arr>"); print(symName(tree, name))
-
case tree =>
xprintTree(this, tree)
}
diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala
index a2c55a89d6..5bb0c98bfb 100644
--- a/src/compiler/scala/reflect/internal/Trees.scala
+++ b/src/compiler/scala/reflect/internal/Trees.scala
@@ -129,6 +129,9 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree
def shortClass: String = tree.getClass.getName split "[.$]" last
+
+ def isErrorTyped = (tree.tpe ne null) && tree.tpe.isError
+
/** When you want to know a little more than the class, but a lot
* less than the whole tree.
*/
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 73f1f3db84..fab10f7896 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -109,15 +109,19 @@ trait Types extends api.Types { self: SymbolTable =>
/** A log of type variable with their original constraints. Used in order
* to undo constraints in the case of isSubType/isSameType failure.
*/
- object undoLog {
- private type UndoLog = List[(TypeVar, TypeConstraint)]
- private[scala] var log: UndoLog = List()
-
+ lazy val undoLog = newUndoLog
+
+ protected def newUndoLog = new UndoLog
+
+ class UndoLog {
+ private type UndoPairs = List[(TypeVar, TypeConstraint)]
+ private var log: UndoPairs = List()
+
// register with the auto-clearing cache manager
perRunCaches.recordCache(this)
/** Undo all changes to constraints to type variables upto `limit`. */
- private def undoTo(limit: UndoLog) {
+ private def undoTo(limit: UndoPairs) {
while ((log ne limit) && log.nonEmpty) {
val (tv, constr) = log.head
tv.constr = constr
@@ -125,9 +129,14 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
- private[Types] def record(tv: TypeVar) = {
+ /** No sync necessary, because record should only
+ * be called from within a undo or undoUnless block,
+ * which is already synchronized.
+ */
+ private[reflect] def record(tv: TypeVar) = {
log ::= ((tv, tv.constr.cloneInternal))
}
+
private[scala] def clear() {
if (settings.debug.value)
self.log("Clearing " + log.size + " entries from the undoLog.")
@@ -249,8 +258,7 @@ trait Types extends api.Types { self: SymbolTable =>
abstract class AbsTypeImpl extends AbsType { this: Type =>
def declaration(name: Name): Symbol = decl(name)
def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name)
- def allDeclarations = decls
- def allMembers = members
+ def declarations = decls
def typeArguments = typeArgs
def erasedType = transformedType(this)
}
@@ -873,16 +881,7 @@ trait Types extends api.Types { self: SymbolTable =>
* after `maxTostringRecursions` recursion levels. Uses `safeToString`
* to produce a string on each level.
*/
- override def toString: String =
- if (tostringRecursions >= maxTostringRecursions)
- "..."
- else
- try {
- tostringRecursions += 1
- safeToString
- } finally {
- tostringRecursions -= 1
- }
+ override def toString: String = typeToString(this)
/** Method to be implemented in subclasses.
* Converts this type to a string in calling toString for its parts.
@@ -992,7 +991,9 @@ trait Types extends api.Types { self: SymbolTable =>
if (membertpe eq null) membertpe = self.memberType(member)
(membertpe matches self.memberType(sym))
})) {
- members = new Scope(List(member, sym))
+ members = newScope
+ members enter member
+ members enter sym
}
} else {
var prevEntry = members.lookupEntry(sym.name)
@@ -1105,7 +1106,7 @@ trait Types extends api.Types { self: SymbolTable =>
/** A base class for types that represent a single value
* (single-types and this-types).
*/
- abstract class SingletonType extends SubType with SimpleTypeProxy with AbsSingletonType {
+ abstract class SingletonType extends SubType with SimpleTypeProxy {
def supertype = underlying
override def isTrivial = false
override def isStable = true
@@ -1204,7 +1205,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (settings.debug.value) sym.nameString + ".this."
else if (sym.isAnonOrRefinementClass) "this."
else if (sym.isOmittablePrefix) ""
- else if (sym.isModuleClass) sym.fullName + "."
+ else if (sym.isModuleClass) sym.fullNameString + "."
else sym.nameString + ".this."
override def safeToString: String =
if (sym.isRoot) "<root>"
@@ -1231,18 +1232,15 @@ trait Types extends api.Types { self: SymbolTable =>
override val isTrivial: Boolean = pre.isTrivial
// override def isNullable = underlying.isNullable
override def isNotNull = underlying.isNotNull
- private var underlyingCache: Type = NoType
- private var underlyingPeriod = NoPeriod
+ private[reflect] var underlyingCache: Type = NoType
+ private[reflect] var underlyingPeriod = NoPeriod
override def underlying: Type = {
- val period = underlyingPeriod
- if (period != currentPeriod) {
- underlyingPeriod = currentPeriod
- if (!isValid(period)) {
- underlyingCache = pre.memberType(sym).resultType;
- assert(underlyingCache ne this, this)
- }
+ val cache = underlyingCache
+ if (underlyingPeriod == currentPeriod && cache != null) cache
+ else {
+ defineUnderlyingOfSingleType(this)
+ underlyingCache
}
- underlyingCache
}
// more precise conceptually, but causes cyclic errors: (paramss exists (_ contains sym))
@@ -1281,6 +1279,17 @@ trait Types extends api.Types { self: SymbolTable =>
unique(new UniqueSingleType(pre, sym))
}
}
+
+ protected def defineUnderlyingOfSingleType(tpe: SingleType) = {
+ val period = tpe.underlyingPeriod
+ if (period != currentPeriod) {
+ tpe.underlyingPeriod = currentPeriod
+ if (!isValid(period)) {
+ tpe.underlyingCache = tpe.pre.memberType(tpe.sym).resultType;
+ assert(tpe.underlyingCache ne tpe, tpe)
+ }
+ }
+ }
abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType {
override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial
@@ -1333,105 +1342,36 @@ trait Types extends api.Types { self: SymbolTable =>
*/
abstract class CompoundType extends Type {
- var baseTypeSeqCache: BaseTypeSeq = _
- private var baseTypeSeqPeriod = NoPeriod
- private var baseClassesCache: List[Symbol] = _
- private var baseClassesPeriod = NoPeriod
+ private[reflect] var baseTypeSeqCache: BaseTypeSeq = _
+ private[reflect] var baseTypeSeqPeriod = NoPeriod
+ private[reflect] var baseClassesCache: List[Symbol] = _
+ private[reflect] var baseClassesPeriod = NoPeriod
override def baseTypeSeq: BaseTypeSeq = {
- val period = baseTypeSeqPeriod;
- if (period != currentPeriod) { // no caching in IDE
- baseTypeSeqPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- if (parents.exists(_.exists(_.isInstanceOf[TypeVar]))) {
- // rename type vars to fresh type params, take base type sequence of
- // resulting type, and rename back all the entries in that sequence
- var tvs = Set[TypeVar]()
- for (p <- parents)
- for (t <- p) t match {
- case tv: TypeVar => tvs += tv
- case _ =>
- }
- val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap
- val paramToVarMap = varToParamMap map (_.swap)
- val varToParam = new TypeMap {
- def apply(tp: Type) = varToParamMap get tp match {
- case Some(sym) => sym.tpe
- case _ => mapOver(tp)
- }
- }
- val paramToVar = new TypeMap {
- def apply(tp: Type) = tp match {
- case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym)
- case _ => mapOver(tp)
- }
- }
- val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq
- baseTypeSeqCache = bts lateMap paramToVar
- } else {
- incCounter(compoundBaseTypeSeqCount)
- baseTypeSeqCache = undetBaseTypeSeq
- baseTypeSeqCache = if (typeSymbol.isRefinementClass)
- memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe)
- else
- compoundBaseTypeSeq(this)
- // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors
- // when compiling with
- // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala
- // I have not yet figured out precisely why this is the case.
- // My current assumption is that taking memos forces baseTypeSeqs to be computed
- // at stale types (i.e. the underlying typeSymbol has already another type).
- // I do not yet see precisely why this would cause a problem, but it looks
- // fishy in any case.
- }
- }
- //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG
+ val cached = baseTypeSeqCache
+ if (baseTypeSeqPeriod == currentPeriod && cached != null && cached != undetBaseTypeSeq)
+ cached
+ else {
+ defineBaseTypeSeqOfCompoundType(this)
+ if (baseTypeSeqCache eq undetBaseTypeSeq)
+ throw new RecoverableCyclicReference(typeSymbol)
+
+ baseTypeSeqCache
}
- if (baseTypeSeqCache eq undetBaseTypeSeq)
- throw new TypeError("illegal cyclic inheritance involving " + typeSymbol)
- baseTypeSeqCache
}
override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
override def baseClasses: List[Symbol] = {
- def computeBaseClasses: List[Symbol] =
- if (parents.isEmpty) List(typeSymbol)
- else {
- //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
- // optimized, since this seems to be performance critical
- val superclazz = parents.head
- var mixins = parents.tail
- val sbcs = superclazz.baseClasses
- var bcs = sbcs
- def isNew(clazz: Symbol): Boolean = (
- superclazz.baseTypeIndex(clazz) < 0 &&
- { var p = bcs;
- while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
- p eq sbcs
- }
- );
- while (!mixins.isEmpty) {
- def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
- if (mbcs.isEmpty) bcs
- else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
- else addMixinBaseClasses(mbcs.tail);
- bcs = addMixinBaseClasses(mixins.head.baseClasses)
- mixins = mixins.tail
- }
- typeSymbol :: bcs
- }
- val period = baseClassesPeriod
- if (period != currentPeriod) {
- baseClassesPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- baseClassesCache = null
- baseClassesCache = memo(computeBaseClasses)(typeSymbol :: _.baseClasses.tail)
- }
+ val cached = baseClassesCache
+ if (baseClassesPeriod == currentPeriod && cached != null) cached
+ else {
+ defineBaseClassesOfCompoundType(this)
+ if (baseClassesCache eq null)
+ throw new RecoverableCyclicReference(typeSymbol)
+
+ baseClassesCache
}
- if (baseClassesCache eq null)
- throw new TypeError("illegal cyclic reference involving " + typeSymbol)
- baseClassesCache
}
/** The slightly less idiomatic use of Options is due to
@@ -1475,6 +1415,97 @@ trait Types extends api.Types { self: SymbolTable =>
(if (settings.debug.value || parents.isEmpty || (decls.elems ne null))
decls.mkString("{", "; ", "}") else "")
}
+
+ protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = {
+ val period = tpe.baseTypeSeqPeriod;
+ if (period != currentPeriod) {
+ tpe.baseTypeSeqPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ if (tpe.parents.exists(_.exists(_.isInstanceOf[TypeVar]))) {
+ // rename type vars to fresh type params, take base type sequence of
+ // resulting type, and rename back all the entries in that sequence
+ var tvs = Set[TypeVar]()
+ for (p <- tpe.parents)
+ for (t <- p) t match {
+ case tv: TypeVar => tvs += tv
+ case _ =>
+ }
+ val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap
+ val paramToVarMap = varToParamMap map (_.swap)
+ val varToParam = new TypeMap {
+ def apply(tp: Type) = varToParamMap get tp match {
+ case Some(sym) => sym.tpe
+ case _ => mapOver(tp)
+ }
+ }
+ val paramToVar = new TypeMap {
+ def apply(tp: Type) = tp match {
+ case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym)
+ case _ => mapOver(tp)
+ }
+ }
+ val bts = copyRefinedType(tpe.asInstanceOf[RefinedType], tpe.parents map varToParam, varToParam mapOver tpe.decls).baseTypeSeq
+ tpe.baseTypeSeqCache = bts lateMap paramToVar
+ } else {
+ incCounter(compoundBaseTypeSeqCount)
+ tpe.baseTypeSeqCache = undetBaseTypeSeq
+ tpe.baseTypeSeqCache = if (tpe.typeSymbol.isRefinementClass)
+ tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe)
+ else
+ compoundBaseTypeSeq(tpe)
+ // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors
+ // when compiling with
+ // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala
+ // I have not yet figured out precisely why this is the case.
+ // My current assumption is that taking memos forces baseTypeSeqs to be computed
+ // at stale types (i.e. the underlying typeSymbol has already another type).
+ // I do not yet see precisely why this would cause a problem, but it looks
+ // fishy in any case.
+ }
+ }
+ }
+ //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG
+ if (tpe.baseTypeSeqCache eq undetBaseTypeSeq)
+ throw new TypeError("illegal cyclic inheritance involving " + tpe.typeSymbol)
+ }
+
+ protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = {
+ def computeBaseClasses: List[Symbol] =
+ if (tpe.parents.isEmpty) List(tpe.typeSymbol)
+ else {
+ //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
+ // optimized, since this seems to be performance critical
+ val superclazz = tpe.parents.head
+ var mixins = tpe.parents.tail
+ val sbcs = superclazz.baseClasses
+ var bcs = sbcs
+ def isNew(clazz: Symbol): Boolean =
+ superclazz.baseTypeIndex(clazz) < 0 &&
+ { var p = bcs;
+ while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
+ p eq sbcs
+ }
+ while (!mixins.isEmpty) {
+ def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
+ if (mbcs.isEmpty) bcs
+ else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
+ else addMixinBaseClasses(mbcs.tail)
+ bcs = addMixinBaseClasses(mixins.head.baseClasses)
+ mixins = mixins.tail
+ }
+ tpe.typeSymbol :: bcs
+ }
+ val period = tpe.baseClassesPeriod
+ if (period != currentPeriod) {
+ tpe.baseClassesPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ tpe.baseClassesCache = null
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ }
+ }
+ if (tpe.baseClassesCache eq null)
+ throw new TypeError("illegal cyclic reference involving " + tpe.typeSymbol)
+ }
/** A class representing intersection types with refinements of the form
* `<parents_0> with ... with <parents_n> { decls }`
@@ -1583,7 +1614,7 @@ trait Types extends api.Types { self: SymbolTable =>
* by a path which contains at least one expansive reference.
* @See Kennedy, Pierce: On Decidability of Nominal Subtyping with Variance
*/
- def expansiveRefs(tparam: Symbol) = {
+ private[scala] def expansiveRefs(tparam: Symbol) = {
if (state == UnInitialized) {
computeRefs()
while (state != Initialized) propagate()
@@ -1597,10 +1628,16 @@ trait Types extends api.Types { self: SymbolTable =>
/** The type parameters which are referenced type parameters of this class.
* Two entries: refs(0): Non-expansive references
* refs(1): Expansive references
+ * Syncnote: This var need not be protected with synchronized, because
+ * it is accessed only from expansiveRefs, which is called only from
+ * Typer.
*/
private var refs: Array[RefMap] = _
/** The initialization state of the class: UnInialized --> Initializing --> Initialized
+ * Syncnote: This var need not be protected with synchronized, because
+ * it is accessed only from expansiveRefs, which is called only from
+ * Typer.
*/
private var state = UnInitialized
@@ -1750,6 +1787,10 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected
+ * with synchronized, because they are accessed only from isVolatile, which is called only from
+ * Typer.
+ */
private var volatileRecursions: Int = 0
private val pendingVolatiles = new mutable.HashSet[Symbol]
@@ -1831,13 +1872,18 @@ trait Types extends api.Types { self: SymbolTable =>
if (sym == clazz) this
else transform(sym.info.baseType(clazz))
}
+
trait NonClassTypeRef extends TypeRef {
require(sym.isNonClassType, sym)
+ /* Syncnote: These are pure caches for performance; no problem to evaluate these
+ * several times. Hence, no need to protected with synchronzied in a mutli-threaded
+ * usage scenario.
+ */
private var relativeInfoCache: Type = _
private var memberInfoCache: Type = _
- private def relativeInfo = {
+ private[Types] def relativeInfo = {
val memberInfo = pre.memberInfo(sym)
if (relativeInfoCache == null || (memberInfo ne memberInfoCache)) {
memberInfoCache = memberInfo
@@ -1846,25 +1892,27 @@ trait Types extends api.Types { self: SymbolTable =>
relativeInfoCache
}
- override def baseType(clazz: Symbol): Type = (
- if (sym == clazz) this else try {
- basetypeRecursions += 1
- if (basetypeRecursions < LogPendingBaseTypesThreshold)
- relativeInfo.baseType(clazz)
- else if (pendingBaseTypes contains this)
- if (clazz == AnyClass) clazz.tpe else NoType
- else
- try {
- pendingBaseTypes += this
- relativeInfo.baseType(clazz)
- } finally {
- pendingBaseTypes -= this
- }
+ override def baseType(clazz: Symbol): Type =
+ if (sym == clazz) this else baseTypeOfNonClassTypeRef(this, clazz)
+ }
+
+ protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = try {
+ basetypeRecursions += 1
+ if (basetypeRecursions < LogPendingBaseTypesThreshold)
+ tpe.relativeInfo.baseType(clazz)
+ else if (pendingBaseTypes contains tpe)
+ if (clazz == AnyClass) clazz.tpe else NoType
+ else
+ try {
+ pendingBaseTypes += tpe
+ tpe.relativeInfo.baseType(clazz)
} finally {
- basetypeRecursions -= 1
+ pendingBaseTypes -= tpe
}
- )
+ } finally {
+ basetypeRecursions -= 1
}
+
trait AliasTypeRef extends NonClassTypeRef {
require(sym.isAliasType, sym)
@@ -1912,6 +1960,8 @@ trait Types extends api.Types { self: SymbolTable =>
trait AbstractTypeRef extends NonClassTypeRef {
require(sym.isAbstractType, sym)
+ /** Syncnote: Pure performance caches; no need to synchronize in multi-threaded environment
+ */
private var symInfoCache: Type = _
private var thisInfoCache: Type = _
@@ -1938,6 +1988,7 @@ trait Types extends api.Types { self: SymbolTable =>
volatileRecursions -= 1
}
}
+
override def thisInfo = {
val symInfo = sym.info
if (thisInfoCache == null || (symInfo ne symInfoCache)) {
@@ -1946,7 +1997,7 @@ trait Types extends api.Types { self: SymbolTable =>
// If a subtyping cycle is not detected here, we'll likely enter an infinite
// loop before a sensible error can be issued. SI-5093 is one example.
case x: SubType if x.supertype eq this =>
- throw new TypeError("illegal cyclic reference involving " + sym)
+ throw new RecoverableCyclicReference(sym)
case tp => tp
}
}
@@ -1955,7 +2006,7 @@ trait Types extends api.Types { self: SymbolTable =>
override def isStable = bounds.hi.typeSymbol isSubClass SingletonClass
override def bounds = thisInfo.bounds
// def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies)
- override protected def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this
+ override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this
}
/** A class for named types of the form
@@ -1966,11 +2017,11 @@ trait Types extends api.Types { self: SymbolTable =>
* @M: a higher-kinded type is represented as a TypeRef with sym.typeParams.nonEmpty, but args.isEmpty
*/
abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type {
- private var parentsCache: List[Type] = _
- private var parentsPeriod = NoPeriod
- private var baseTypeSeqCache: BaseTypeSeq = _
- private var baseTypeSeqPeriod = NoPeriod
- private var normalized: Type = _
+ private[reflect] var parentsCache: List[Type] = _
+ private[reflect] var parentsPeriod = NoPeriod
+ private[reflect] var baseTypeSeqCache: BaseTypeSeq = _
+ private[reflect] var baseTypeSeqPeriod = NoPeriod
+ private var normalized: Type = _
// @M: propagate actual type params (args) to `tp`, by replacing
// formal type parameters with actual ones. If tp is higher kinded,
@@ -2030,16 +2081,12 @@ trait Types extends api.Types { self: SymbolTable =>
sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull
override def parents: List[Type] = {
- val period = parentsPeriod
- if (period != currentPeriod) {
- parentsPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- parentsCache = thisInfo.parents map transform
- } else if (parentsCache == null) { // seems this can happen if things are corrupted enough, see #2641
- parentsCache = List(AnyClass.tpe)
- }
+ val cache = parentsCache
+ if (parentsPeriod == currentPeriod && cache != null) cache
+ else {
+ defineParentsOfTypeRef(this)
+ parentsCache
}
- parentsCache
}
override def decls: Scope = {
@@ -2051,21 +2098,19 @@ trait Types extends api.Types { self: SymbolTable =>
thisInfo.decls
}
- protected def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform
+ protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform
override def baseTypeSeq: BaseTypeSeq = {
- val period = baseTypeSeqPeriod
- if (period != currentPeriod) {
- baseTypeSeqPeriod = currentPeriod
- if (!isValidForBaseClasses(period)) {
- incCounter(typerefBaseTypeSeqCount)
- baseTypeSeqCache = undetBaseTypeSeq
- baseTypeSeqCache = baseTypeSeqImpl
- }
+ val cache = baseTypeSeqCache
+ if (baseTypeSeqPeriod == currentPeriod && cache != null && cache != undetBaseTypeSeq)
+ cache
+ else {
+ defineBaseTypeSeqOfTypeRef(this)
+ if (baseTypeSeqCache == undetBaseTypeSeq)
+ throw new RecoverableCyclicReference(sym)
+
+ baseTypeSeqCache
}
- if (baseTypeSeqCache == undetBaseTypeSeq)
- throw new TypeError("illegal cyclic inheritance involving " + sym)
- baseTypeSeqCache
}
private def preString = (
@@ -2074,11 +2119,11 @@ trait Types extends api.Types { self: SymbolTable =>
else pre.prefixString
)
private def argsString = if (args.isEmpty) "" else args.mkString("[", ",", "]")
- private def refinementString = (
+ def refinementString = (
if (sym.isStructuralRefinement) (
decls filter (sym => sym.isPossibleInRefinement && sym.isPublic)
map (_.defString)
- mkString(" {", "; ", "}")
+ mkString("{", "; ", "}")
)
else ""
)
@@ -2151,6 +2196,32 @@ trait Types extends api.Types { self: SymbolTable =>
}
})
}
+
+ protected def defineParentsOfTypeRef(tpe: TypeRef) = {
+ val period = tpe.parentsPeriod
+ if (period != currentPeriod) {
+ tpe.parentsPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ tpe.parentsCache = tpe.thisInfo.parents map tpe.transform
+ } else if (tpe.parentsCache == null) { // seems this can happen if things are corrupted enough, see #2641
+ tpe.parentsCache = List(AnyClass.tpe)
+ }
+ }
+ }
+
+ protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = {
+ val period = tpe.baseTypeSeqPeriod
+ if (period != currentPeriod) {
+ tpe.baseTypeSeqPeriod = currentPeriod
+ if (!isValidForBaseClasses(period)) {
+ incCounter(typerefBaseTypeSeqCount)
+ tpe.baseTypeSeqCache = undetBaseTypeSeq
+ tpe.baseTypeSeqCache = tpe.baseTypeSeqImpl
+ }
+ }
+ if (tpe.baseTypeSeqCache == undetBaseTypeSeq)
+ throw new TypeError("illegal cyclic inheritance involving " + tpe.sym)
+ }
/** A class representing a method type with parameters.
* Note that a parameterless method is represented by a NullaryMethodType:
@@ -2498,7 +2569,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (args.isEmpty && params.isEmpty) new TypeVar(origin, constr)
else if (args.size == params.size) new AppliedTypeVar(origin, constr, params zip args)
else if (args.isEmpty) new HKTypeVar(origin, constr, params)
- else throw new TypeError("Invalid TypeVar construction: " + ((origin, constr, args, params)))
+ else throw new Error("Invalid TypeVar construction: " + ((origin, constr, args, params)))
)
trace("create", "In " + tv.originLocation)(tv)
@@ -2577,7 +2648,12 @@ trait Types extends api.Types { self: SymbolTable =>
override def typeArgs: List[Type] = Nil
override def isHigherKinded = false
- /** The constraint associated with the variable */
+ /** The constraint associated with the variable
+ * Syncnote: Type variables are assumed to be used from only one
+ * thread. They are not exposed in api.Types and are used only locally
+ * in operations that are exposed from types. Hence, no syncing of `constr`
+ * or `encounteredHigherLevel` or `suspended` accesses should be necessary.
+ */
var constr = constr0
def instValid = constr.instValid
@@ -2599,7 +2675,7 @@ trait Types extends api.Types { self: SymbolTable =>
TypeVar.trace("applyArgs", "In " + originLocation + ", apply args " + newArgs.mkString(", ") + " to " + originName)(tv)
}
else
- throw new TypeError("Invalid type application in TypeVar: " + params + ", " + newArgs)
+ throw new Error("Invalid type application in TypeVar: " + params + ", " + newArgs)
)
// newArgs.length may differ from args.length (could've been empty before)
//
@@ -3048,7 +3124,7 @@ trait Types extends api.Types { self: SymbolTable =>
* @return ...
*/
def refinedType(parents: List[Type], owner: Symbol): Type =
- refinedType(parents, owner, new Scope, owner.pos)
+ refinedType(parents, owner, newScope, owner.pos)
def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) =
if ((parents eq original.parents) && (decls eq original.decls)) original
@@ -3079,7 +3155,7 @@ trait Types extends api.Types { self: SymbolTable =>
// don't expand cyclical type alias
// we require that object is initialized, thus info.typeParams instead of typeParams.
if (sym1.isAliasType && sameLength(sym1.info.typeParams, args) && !sym1.lockOK)
- throw new TypeError("illegal cyclic reference involving " + sym1)
+ throw new RecoverableCyclicReference(sym1)
val pre1 = pre match {
case x: SuperType if sym1.isEffectivelyFinal || sym1.isDeferred =>
@@ -3101,7 +3177,7 @@ trait Types extends api.Types { self: SymbolTable =>
def copyTypeRef(tp: Type, pre: Type, sym: Symbol, args: List[Type]): Type = tp match {
case TypeRef(pre0, sym0, _) if pre == pre0 && sym0.name == sym.name =>
if (sym.isAliasType && sameLength(sym.info.typeParams, args) && !sym.lockOK)
- throw new TypeError("illegal cyclic reference involving " + sym)
+ throw new RecoverableCyclicReference(sym)
TypeRef(pre, sym, args)
case _ =>
@@ -3266,6 +3342,20 @@ trait Types extends api.Types { self: SymbolTable =>
mapOver(tp)
}
}
+
+ /** Type with all top-level occurrences of abstract types replaced by their bounds */
+ def abstractTypesToBounds(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala )
+ case TypeRef(_, sym, _) if sym.isAbstractType =>
+ abstractTypesToBounds(tp.bounds.hi)
+ case TypeRef(_, sym, _) if sym.isAliasType =>
+ abstractTypesToBounds(tp.normalize)
+ case rtp @ RefinedType(parents, decls) =>
+ copyRefinedType(rtp, parents mapConserve abstractTypesToBounds, decls)
+ case AnnotatedType(_, underlying, _) =>
+ abstractTypesToBounds(underlying)
+ case _ =>
+ tp
+ }
// Set to true for A* => Seq[A]
// (And it will only rewrite A* in method result types.)
@@ -3338,7 +3428,7 @@ trait Types extends api.Types { self: SymbolTable =>
private var uniques: util.HashSet[Type] = _
private var uniqueRunId = NoRunId
- private def unique[T <: Type](tp: T): T = {
+ protected def unique[T <: Type](tp: T): T = {
incCounter(rawTypeCount)
if (uniqueRunId != currentRunId) {
uniques = util.HashSet[Type]("uniques", initialUniquesCapacity)
@@ -3362,6 +3452,12 @@ trait Types extends api.Types { self: SymbolTable =>
def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType)
def this(bounds: TypeBounds) = this(List(bounds.lo), List(bounds.hi))
def this() = this(List(), List())
+
+ /* Syncnote: Type constraints are assumed to be used from only one
+ * thread. They are not exposed in api.Types and are used only locally
+ * in operations that are exposed from types. Hence, no syncing of any
+ * variables should be ncessesary.
+ */
/** Guard these lists against AnyClass and NothingClass appearing,
* else loBounds.isEmpty will have different results for an empty
@@ -3634,7 +3730,7 @@ trait Types extends api.Types { self: SymbolTable =>
val elems = scope.toList
val elems1 = mapOver(elems)
if (elems1 eq elems) scope
- else new Scope(elems1)
+ else newScopeWith(elems1: _*)
}
/** Map this function over given list of symbols */
@@ -3699,6 +3795,11 @@ trait Types extends api.Types { self: SymbolTable =>
def traverse(tp: Type): Unit
def apply(tp: Type): Type = { traverse(tp); tp }
}
+
+ abstract class TypeTraverserWithResult[T] extends TypeTraverser {
+ def result: T
+ def clear(): Unit
+ }
abstract class TypeCollector[T](initial: T) extends TypeTraverser {
var result: T = _
@@ -3753,7 +3854,7 @@ trait Types extends api.Types { self: SymbolTable =>
* the conversion of raw types to existential types might not have taken place
* in ClassFileparser.sigToType (where it is usually done).
*/
- object rawToExistential extends TypeMap {
+ def rawToExistential = new TypeMap {
private var expanded = immutable.Set[Symbol]()
private var generated = immutable.Set[Type]()
def apply(tp: Type): Type = tp match {
@@ -3971,15 +4072,17 @@ trait Types extends api.Types { self: SymbolTable =>
else instParamRelaxed(ps.tail, as.tail)
//Console.println("instantiating " + sym + " from " + basesym + " with " + basesym.typeParams + " and " + baseargs+", pre = "+pre+", symclazz = "+symclazz);//DEBUG
- if (sameLength(basesym.typeParams, baseargs)) {
+ if (sameLength(basesym.typeParams, baseargs))
instParam(basesym.typeParams, baseargs)
- } else {
- throw new TypeError(
- "something is wrong (wrong class file?): "+basesym+
- " with type parameters "+
- basesym.typeParams.map(_.name).mkString("[",",","]")+
- " gets applied to arguments "+baseargs.mkString("[",",","]")+", phase = "+phase)
- }
+ else
+ if (symclazz.tpe.parents.exists(_.isErroneous))
+ ErrorType // don't be to overzealous with throwing exceptions, see #2641
+ else
+ throw new Error(
+ "something is wrong (wrong class file?): "+basesym+
+ " with type parameters "+
+ basesym.typeParams.map(_.name).mkString("[",",","]")+
+ " gets applied to arguments "+baseargs.mkString("[",",","]")+", phase = "+phase)
case ExistentialType(tparams, qtpe) =>
capturedSkolems = capturedSkolems union tparams
toInstance(qtpe, clazz)
@@ -4365,15 +4468,20 @@ trait Types extends api.Types { self: SymbolTable =>
private def commonOwner(tps: List[Type]): Symbol = {
if (tps.isEmpty) NoSymbol
else {
- commonOwnerMap.result = null
+ commonOwnerMap.clear()
tps foreach (commonOwnerMap traverse _)
val result = if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol
debuglog(tps.mkString("commonOwner(", ", ", ") == " + result))
result
}
}
- private object commonOwnerMap extends TypeTraverser {
+
+ protected def commonOwnerMap: CommonOwnerMap = commonOwnerMapObj
+
+ protected class CommonOwnerMap extends TypeTraverserWithResult[Symbol] {
var result: Symbol = _
+
+ def clear() { result = null }
private def register(sym: Symbol) {
// First considered type is the trivial result.
@@ -4390,12 +4498,15 @@ trait Types extends api.Types { self: SymbolTable =>
case _ => mapOver(tp)
}
}
+
+ private lazy val commonOwnerMapObj = new CommonOwnerMap
class MissingAliasControl extends ControlThrowable
val missingAliasException = new MissingAliasControl
class MissingTypeControl extends ControlThrowable
object adaptToNewRunMap extends TypeMap {
+
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
if (phase.flatClasses) {
sym
@@ -5832,7 +5943,7 @@ trait Types extends api.Types { self: SymbolTable =>
}
/** The least upper bound wrt <:< of a list of types */
- def lub(ts: List[Type], depth: Int): Type = {
+ private def lub(ts: List[Type], depth: Int): Type = {
def lub0(ts0: List[Type]): Type = elimSub(ts0, depth) match {
case List() => NothingClass.tpe
case List(t) => t
@@ -5983,7 +6094,7 @@ trait Types extends api.Types { self: SymbolTable =>
/** The greatest lower bound wrt <:< of a list of types, which have been normalized
* wrt elimSuper */
- private def glbNorm(ts: List[Type], depth: Int): Type = {
+ protected def glbNorm(ts: List[Type], depth: Int): Type = {
def glb0(ts0: List[Type]): Type = ts0 match {
case List() => AnyClass.tpe
case List(t) => t
@@ -6264,6 +6375,12 @@ trait Types extends api.Types { self: SymbolTable =>
def this(msg: String) = this(NoPosition, msg)
}
+ // TODO: RecoverableCyclicReference should be separated from TypeError,
+ // but that would be a big change. Left for further refactoring.
+ /** An exception for cyclic references from which we can recover */
+ case class RecoverableCyclicReference(sym: Symbol)
+ extends TypeError("illegal cyclic reference involving " + sym)
+
class NoCommonType(tps: List[Type]) extends Throwable(
"lub/glb of incompatible types: " + tps.mkString("", " and ", "")) with ControlThrowable
@@ -6272,14 +6389,11 @@ trait Types extends api.Types { self: SymbolTable =>
def this(pre: Type, tp: String) = this("malformed type: " + pre + "#" + tp)
}
- /** An exception signalling a variance annotation/usage conflict */
- class VarianceError(msg: String) extends TypeError(msg)
-
/** The current indentation string for traces */
private var indent: String = ""
/** Perform operation `p` on arguments `tp1`, `arg2` and print trace of computation. */
- private def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
+ protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
Console.println(indent + tp1 + " " + op + " " + arg2 + "?" /* + "("+tp1.getClass+","+arg2.getClass+")"*/)
indent = indent + " "
val result = p(tp1, arg2)
@@ -6324,4 +6438,16 @@ trait Types extends api.Types { self: SymbolTable =>
final val maxTostringRecursions = 50
private var tostringRecursions = 0
+
+ protected def typeToString(tpe: Type): String =
+ if (tostringRecursions >= maxTostringRecursions)
+ "..."
+ else
+ try {
+ tostringRecursions += 1
+ tpe.safeToString
+ } finally {
+ tostringRecursions -= 1
+ }
+
}
diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
index 6980d28bfb..0092f73fe3 100644
--- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
@@ -38,6 +38,7 @@ abstract class MutableSettings extends AbsSettings {
def explaintypes: BooleanSetting
def verbose: BooleanSetting
def uniqid: BooleanSetting
+ def Yshowsymkinds: BooleanSetting
def Xprintpos: BooleanSetting
def Yrecursion: IntSetting
def maxClassfileName: IntSetting
diff --git a/src/compiler/scala/reflect/runtime/ConversionUtil.scala b/src/compiler/scala/reflect/runtime/ConversionUtil.scala
index bd40200310..e75fd78590 100644
--- a/src/compiler/scala/reflect/runtime/ConversionUtil.scala
+++ b/src/compiler/scala/reflect/runtime/ConversionUtil.scala
@@ -17,36 +17,42 @@ trait ConversionUtil { self: SymbolTable =>
private val toScalaMap = new HashMap[J, S]
private val toJavaMap = new HashMap[S, J]
- def enter(j: J, s: S) = {
+ def enter(j: J, s: S) = synchronized {
debugInfo("cached: "+j+"/"+s)
toScalaMap(j) = s
toJavaMap(s) = j
}
- def toScala(key: J)(body: => S): S = toScalaMap get key match {
- case Some(v) =>
- v
- case none =>
- val result = body
- enter(key, result)
- result
+ def toScala(key: J)(body: => S): S = synchronized {
+ toScalaMap get key match {
+ case Some(v) =>
+ v
+ case none =>
+ val result = body
+ enter(key, result)
+ result
+ }
}
- def toJava(key: S)(body: => J): J = toJavaMap get key match {
- case Some(v) =>
- v
- case none =>
- val result = body
- enter(result, key)
- result
+ def toJava(key: S)(body: => J): J = synchronized {
+ toJavaMap get key match {
+ case Some(v) =>
+ v
+ case none =>
+ val result = body
+ enter(result, key)
+ result
+ }
}
- def toJavaOption(key: S)(body: => Option[J]): Option[J] = toJavaMap get key match {
- case None =>
- val result = body
- for (value <- result) enter(value, key)
- result
- case some => some
+ def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized {
+ toJavaMap get key match {
+ case None =>
+ val result = body
+ for (value <- result) enter(value, key)
+ result
+ case some => some
+ }
}
}
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index bc5d616ae3..b4bcc52a23 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -175,7 +175,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
load(sym)
completeRest()
}
- def completeRest(): Unit = {
+ def completeRest(): Unit = self.synchronized {
val tparams = clazz.rawInfo.typeParams
val parents = try {
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala
index 7aca052fa9..4b35a5b37e 100644
--- a/src/compiler/scala/reflect/runtime/Loaders.scala
+++ b/src/compiler/scala/reflect/runtime/Loaders.scala
@@ -97,9 +97,9 @@ trait Loaders { self: SymbolTable =>
0 < dp && dp < (name.length - 1)
}
- class PackageScope(pkgClass: Symbol) extends Scope {
+ class PackageScope(pkgClass: Symbol) extends Scope() with SynchronizedScope {
assert(pkgClass.isType)
- private var negatives = mutable.Set[Name]()
+ private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected.
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
if (e != null)
diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala
index 09a4bbe198..4808326902 100644
--- a/src/compiler/scala/reflect/runtime/Mirror.scala
+++ b/src/compiler/scala/reflect/runtime/Mirror.scala
@@ -51,7 +51,8 @@ class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxe
override def typeToClass(tpe: Type): java.lang.Class[_] = typeToJavaClass(tpe)
override def symbolToClass(sym: Symbol): java.lang.Class[_] = classToJava(sym)
-
+
+ override def inReflexiveMirror = true
}
object Mirror extends Mirror
diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala
index 2a6cdea519..b4f0123114 100644
--- a/src/compiler/scala/reflect/runtime/Settings.scala
+++ b/src/compiler/scala/reflect/runtime/Settings.scala
@@ -28,6 +28,7 @@ class Settings extends internal.settings.MutableSettings {
val explaintypes = new BooleanSetting(false)
val verbose = new BooleanSetting(false)
val uniqid = new BooleanSetting(false)
+ val Yshowsymkinds = new BooleanSetting(false)
val Xprintpos = new BooleanSetting(false)
val printtypes = new BooleanSetting(false)
val Yrecursion = new IntSetting(0)
diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala
index d1a806bcef..5331f0a53e 100644
--- a/src/compiler/scala/reflect/runtime/SymbolTable.scala
+++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala
@@ -6,7 +6,7 @@ package runtime
* It can be used either from the reflexive mirror itself (class Universe), or else from
* a runtime compiler that uses reflection to get a class information (class scala.tools.nsc.ReflectGlobal)
*/
-trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders {
+trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders with SynchronizedOps {
/** If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
* <owner>.<name>, otherwise return NoSymbol.
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala
new file mode 100644
index 0000000000..72adbd4004
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala
@@ -0,0 +1,51 @@
+package scala.reflect
+package runtime
+
+trait SynchronizedOps extends internal.SymbolTable
+ with SynchronizedSymbols
+ with SynchronizedTypes { self: SymbolTable =>
+
+// Names
+
+ private lazy val nameLock = new Object
+
+ override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) }
+ override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) }
+
+// BaseTypeSeqs
+
+ override protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) =
+ new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq
+
+ trait SynchronizedBaseTypeSeq extends BaseTypeSeq {
+ override def apply(i: Int): Type = synchronized { super.apply(i) }
+ override def rawElem(i: Int) = synchronized { super.rawElem(i) }
+ override def typeSymbol(i: Int): Symbol = synchronized { super.typeSymbol(i) }
+ override def toList: List[Type] = synchronized { super.toList }
+ override def copy(head: Type, offset: Int): BaseTypeSeq = synchronized { super.copy(head, offset) }
+ override def map(f: Type => Type): BaseTypeSeq = synchronized { super.map(f) }
+ override def exists(p: Type => Boolean): Boolean = synchronized { super.exists(p) }
+ override lazy val maxDepth = synchronized { maxDepthOfElems }
+ override def toString = synchronized { super.toString }
+
+ override def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq
+ }
+
+// Scopes
+
+ override def newScope = new Scope() with SynchronizedScope
+ override def newNestedScope(outer: Scope): Scope = new Scope(outer) with SynchronizedScope
+
+ trait SynchronizedScope extends Scope {
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+ override def size: Int = synchronized { super.size }
+ override def enter(sym: Symbol) = synchronized { super.enter(sym) }
+ override def rehash(sym: Symbol, newname: Name) = synchronized { super.rehash(sym, newname) }
+ override def unlink(e: ScopeEntry) = synchronized { super.unlink(e) }
+ override def unlink(sym: Symbol) = synchronized { super.unlink(sym) }
+ override def lookupAll(name: Name) = synchronized { super.lookupAll(name) }
+ override def lookupEntry(name: Name) = synchronized { super.lookupEntry(name) }
+ override def lookupNextEntry(entry: ScopeEntry) = synchronized { super.lookupNextEntry(entry) }
+ override def toList: List[Symbol] = synchronized { super.toList }
+ }
+}
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
new file mode 100644
index 0000000000..9baf94f71d
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -0,0 +1,119 @@
+package scala.reflect
+package runtime
+
+import internal.Flags.DEFERRED
+
+trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
+
+ override protected def nextId() = synchronized { super.nextId() }
+
+ override protected def freshExistentialName(suffix: String) =
+ synchronized { super.freshExistentialName(suffix) }
+
+ // Set the fields which point companions at one another. Returns the module.
+ override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol =
+ synchronized { super.connectModuleToClass(m, moduleClass) }
+
+ override def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar =
+ new FreeVar(name, value) with SynchronizedTermSymbol initFlags newFlags setInfo tpe
+
+ override protected def makeNoSymbol = new NoSymbol with SynchronizedSymbol
+
+ trait SynchronizedSymbol extends Symbol {
+
+ override def rawowner = synchronized { super.rawowner }
+ override def rawname = synchronized { super.rawname }
+ override def rawflags = synchronized { super.rawflags }
+
+ override def rawflags_=(x: FlagsType) = synchronized { super.rawflags_=(x) }
+ override def name_=(x: Name) = synchronized { super.name_=(x) }
+ override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) }
+
+ override def validTo = synchronized { super.validTo }
+ override def validTo_=(x: Period) = synchronized { super.validTo_=(x) }
+
+ override def pos = synchronized { super.pos }
+ override def setPos(pos: Position): this.type = { synchronized { super.setPos(pos) }; this }
+
+ override def privateWithin = synchronized { super.privateWithin }
+ override def privateWithin_=(sym: Symbol) = synchronized { super.privateWithin_=(sym) }
+
+ override def info = synchronized { super.info }
+ override def info_=(info: Type) = synchronized { super.info_=(info) }
+ override def updateInfo(info: Type): Symbol = synchronized { super.updateInfo(info) }
+ override def rawInfo: Type = synchronized { super.rawInfo }
+
+ override def typeParams: List[Symbol] = synchronized { super.typeParams }
+
+ override def reset(completer: Type) = synchronized { super.reset(completer) }
+
+ override def infosString: String = synchronized { super.infosString }
+
+ override def annotations: List[AnnotationInfo] = synchronized { super.annotations }
+ override def setAnnotations(annots: List[AnnotationInfo]): this.type = { synchronized { super.setAnnotations(annots) }; this }
+
+
+// ------ creators -------------------------------------------------------------------
+
+ override def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
+
+ override def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
+ new AbstractTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags
+
+ override def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
+ new AliasTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags
+
+ override def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
+ new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
+
+ override def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
+ new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags
+
+ override def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
+ new ClassSymbol(this, pos, name) with SynchronizedClassSymbol initFlags newFlags
+
+ override def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ new ModuleClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags
+
+ override def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem =
+ if ((newFlags & DEFERRED) == 0L)
+ new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags
+ else
+ new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin with SynchronizedTypeSymbol initFlags newFlags
+ }
+
+// ------- subclasses ---------------------------------------------------------------------
+
+ trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol {
+ override def referenced: Symbol = synchronized { super.referenced }
+ override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) }
+ }
+
+ trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol {
+ override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) }
+ }
+
+ trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol {
+ override def typeConstructor: Type = synchronized { super.typeConstructor }
+ override def tpe: Type = synchronized { super.tpe }
+ }
+
+ trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol {
+ override def sourceFile = synchronized { super.sourceFile }
+ override def sourceFile_=(f: AbstractFileType) = synchronized { super.sourceFile_=(f) }
+ override def thisSym: Symbol = synchronized { super.thisSym }
+ override def thisType: Type = synchronized { super.thisType }
+ override def typeOfThis: Type = synchronized { super.typeOfThis }
+ override def typeOfThis_=(tp: Type) = synchronized { super.typeOfThis_=(tp) }
+ override def children = synchronized { super.children }
+ override def addChild(sym: Symbol) = synchronized { super.addChild(sym) }
+ }
+
+ trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol {
+ override def sourceModule = synchronized { super.sourceModule }
+ override def sourceModule_=(module: Symbol) = synchronized { super.sourceModule_=(module: Symbol) }
+ override def implicitMembers: List[Symbol] = synchronized { super.implicitMembers }
+ }
+}
+
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
new file mode 100644
index 0000000000..c842d3dd01
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
@@ -0,0 +1,87 @@
+package scala.reflect
+package runtime
+
+/** This trait overrides methods in reflect.internal, bracketing
+ * them in synchronized { ... } to make them thread-safe
+ */
+trait SynchronizedTypes extends internal.Types { self: SymbolTable =>
+
+ // No sharing of map objects:
+ override protected def commonOwnerMap = new CommonOwnerMap
+
+ private val uniqueLock = new Object
+ override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { super.unique(tp) }
+
+ class SynchronizedUndoLog extends UndoLog {
+
+ override def clear() =
+ synchronized { super.clear() }
+
+ override def undo[T](block: => T): T =
+ synchronized { super.undo(block) }
+
+ override def undoUnless(block: => Boolean): Boolean =
+ synchronized { super.undoUnless(block) }
+ }
+
+ override protected def newUndoLog = new SynchronizedUndoLog
+
+ override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) =
+ synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) }
+
+ private val subsametypeLock = new Object
+
+ override def isSameType(tp1: Type, tp2: Type): Boolean =
+ subsametypeLock.synchronized { super.isSameType(tp1, tp2) }
+
+ override def isDifferentType(tp1: Type, tp2: Type): Boolean =
+ subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) }
+
+ override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean =
+ subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) }
+
+ private val lubglbLock = new Object
+
+ override def glb(ts: List[Type]): Type =
+ lubglbLock.synchronized { super.glb(ts) }
+
+ override def lub(ts: List[Type]): Type =
+ lubglbLock.synchronized { super.lub(ts) }
+
+ private val indentLock = new Object
+
+ override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
+ indentLock.synchronized { super.explain(op, p, tp1, arg2) }
+ }
+
+ private val toStringLock = new Object
+
+ override protected def typeToString(tpe: Type): String =
+ toStringLock.synchronized(super.typeToString(tpe))
+
+ /* The idea of caches is as follows.
+ * When in reflexive mode, a cache is either null, or one sentinal
+ * value representing undefined or the final defined
+ * value. Hence, we can ask in non-synchronized ode whether the cache field
+ * is non null and different from the sentinel (if a sentinel exists).
+ * If that's true, the cache value is current.
+ * Otherwise we arrive in one of the defined... methods listed below
+ * which go through all steps in synchronized mode.
+ */
+
+ override protected def defineUnderlyingOfSingleType(tpe: SingleType) =
+ tpe.synchronized { super.defineUnderlyingOfSingleType(tpe) }
+
+ override protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) =
+ tpe.synchronized { super.defineBaseTypeSeqOfCompoundType(tpe) }
+
+ override protected def defineBaseClassesOfCompoundType(tpe: CompoundType) =
+ tpe.synchronized { super.defineBaseClassesOfCompoundType(tpe) }
+
+ override protected def defineParentsOfTypeRef(tpe: TypeRef) =
+ tpe.synchronized { super.defineParentsOfTypeRef(tpe) }
+
+ override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) =
+ tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) }
+
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
index 8afd6d2231..46d890c5d1 100644
--- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala
+++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
@@ -57,7 +57,7 @@ trait ToolBoxes extends { self: Universe =>
def wrapInObject(expr: Tree, fvs: List[Symbol]): ModuleDef = {
val obj = EmptyPackageClass.newModule(nextWrapperModuleName())
- val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), new Scope, obj.moduleClass)
+ val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), newScope, obj.moduleClass)
obj.moduleClass setInfo minfo
obj setInfo obj.moduleClass.tpe
val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName))
@@ -123,15 +123,21 @@ trait ToolBoxes extends { self: Universe =>
applyMeth.invoke(result)
}
}
-
- def showAttributed(tree: Tree): String = {
- val saved = settings.printtypes.value
+
+ def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = {
+ val saved1 = settings.printtypes.value
+ val saved2 = settings.uniqid.value
+ val saved3 = settings.Yshowsymkinds.value
try {
- settings.printtypes.value = true
- //settings.uniqid.value = true
+ settings.printtypes.value = printTypes
+ settings.uniqid.value = printIds
+ settings.uniqid.value = printKinds
tree.toString
- } finally
- compiler.settings.printtypes.value = saved
+ } finally {
+ settings.printtypes.value = saved1
+ settings.uniqid.value = saved2
+ settings.Yshowsymkinds.value = saved3
+ }
}
}
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index 7aff4e3e8e..04ff0c440d 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -608,7 +608,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
if (!deprecation.isEmpty) settings.deprecation.value = deprecation.get
if (!nobootcp.isEmpty) settings.nobootcp.value = nobootcp.get
if (!nowarn.isEmpty) settings.nowarn.value = nowarn.get
- if (!optimise.isEmpty) settings.XO.value = optimise.get
+ if (!optimise.isEmpty) settings.optimise.value = optimise.get
if (!unchecked.isEmpty) settings.unchecked.value = unchecked.get
if (!usejavacp.isEmpty) settings.usejavacp.value = usejavacp.get
diff --git a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala
index a39de64c5a..5199e273d7 100644
--- a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala
+++ b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala
@@ -13,6 +13,7 @@ import java.io.{ File, FileWriter }
import org.apache.tools.ant.Project
import org.apache.tools.ant.taskdefs.Java
import org.apache.tools.ant.util.{ GlobPatternMapper, SourceFileScanner }
+import org.apache.tools.ant.BuildException
import scala.tools.nsc.io
import scala.tools.nsc.util.ScalaClassLoader
@@ -150,7 +151,7 @@ class ScalacFork extends ScalaMatchingTask with ScalacShared with TaskArgs {
val res = execWithArgFiles(java, paths)
if (failOnError && res != 0)
- sys.error("Compilation failed because of an internal compiler error;"+
+ throw new BuildException("Compilation failed because of an internal compiler error;"+
" see the error output for details.")
}
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index e805b4e75e..797ed7e047 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -13,7 +13,7 @@ import scala.tools.util.{ Profiling, PathResolver }
import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
import reporters.{ Reporter, ConsoleReporter }
-import util.{ NoPosition, Exceptional, ClassPath, SourceFile, Statistics, StatisticsInfo, BatchSourceFile, ScriptSourceFile, ShowPickled, ScalaClassLoader, returning }
+import util.{ NoPosition, Exceptional, ClassPath, SourceFile, NoSourceFile, Statistics, StatisticsInfo, BatchSourceFile, ScriptSourceFile, ShowPickled, ScalaClassLoader, returning }
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
import settings.{ AestheticSettings }
@@ -164,6 +164,23 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
if (opt.fatalWarnings) globalError(msg)
else reporter.warning(NoPosition, msg)
+ // Getting in front of Predef's asserts to supplement with more info.
+ // This has the happy side effect of masking the one argument forms
+ // of assert and require (but for now I've reproduced them here,
+ // because there are a million to fix.)
+ @inline final def assert(assertion: Boolean, message: => Any) {
+ Predef.assert(assertion, supplementErrorMessage("" + message))
+ }
+ @inline final def assert(assertion: Boolean) {
+ assert(assertion, "")
+ }
+ @inline final def require(requirement: Boolean, message: => Any) {
+ Predef.require(requirement, supplementErrorMessage("" + message))
+ }
+ @inline final def require(requirement: Boolean) {
+ require(requirement, "")
+ }
+
// Needs to call error to make sure the compile fails.
override def abort(msg: String): Nothing = {
error(msg)
@@ -375,10 +392,13 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
}
final def applyPhase(unit: CompilationUnit) {
+ if ((unit ne null) && unit.exists)
+ lastSeenSourceFile = unit.source
+
if (opt.echoFilenames)
inform("[running phase " + name + " on " + unit + "]")
- val unit0 = currentRun.currentUnit
+ val unit0 = currentUnit
try {
currentRun.currentUnit = unit
if (!cancelled(unit)) {
@@ -387,7 +407,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
}
currentRun.advanceUnit
} finally {
- //assert(currentRun.currentUnit == unit)
+ //assert(currentUnit == unit)
currentRun.currentUnit = unit0
}
}
@@ -615,7 +635,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
object icodeChecker extends icodeCheckers.ICodeChecker()
object typer extends analyzer.Typer(
- analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, new Scope)
+ analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, newScope)
)
/** Add the internal compiler phases to the phases set.
@@ -781,9 +801,40 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
curRun = null
}
+ /** 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
+ * really want to know, this hack.
+ */
+ private var lastSeenSourceFile: SourceFile = NoSourceFile
+
/** The currently active run
*/
- def currentRun: Run = curRun
+ def currentRun: Run = curRun
+ def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit
+ def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile
+
+ /** 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
+ )
+ }
+ catch { case x: Exception => errorMessage }
/** The id of the currently active run
*/
@@ -798,10 +849,40 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** A Run is a single execution of the compiler on a sets of units
*/
class Run {
+ /** Have been running into too many init order issues with Run
+ * during erroneous conditions. Moved all these vals up to the
+ * top of the file so at least they're not trivially null.
+ */
var isDefined = false
+ /** The currently compiled unit; set from GlobalPhase */
+ var currentUnit: CompilationUnit = NoCompilationUnit
+
+ /** Counts for certain classes of warnings during this run. */
+ var deprecationWarnings: List[(Position, String)] = Nil
+ var uncheckedWarnings: List[(Position, String)] = Nil
+
+ /** A flag whether macro expansions failed */
+ var macroExpansionFailed = false
+
/** To be initialized from firstPhase. */
private var terminalPhase: Phase = NoPhase
+ private val unitbuf = new mutable.ListBuffer[CompilationUnit]
+ val compiledFiles = new mutable.HashSet[String]
+
+ /** A map from compiled top-level symbols to their source files */
+ val symSource = new mutable.HashMap[Symbol, AbstractFile]
+
+ /** A map from compiled top-level symbols to their picklers */
+ val symData = new mutable.HashMap[Symbol, PickleBuffer]
+
+ private var phasec: Int = 0 // phases completed
+ private var unitc: Int = 0 // units completed this phase
+ private var _unitbufSize = 0
+
+ def size = _unitbufSize
+ override def toString = "scalac Run for:\n " + compiledFiles.toList.sorted.mkString("\n ")
+
// Calculate where to stop based on settings -Ystop-before or -Ystop-after.
// Slightly complicated logic due to wanting -Ystop-before:parser to fail rather
// than mysteriously running to completion.
@@ -895,16 +976,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// --------------- Miscellania -------------------------------
- /** The currently compiled unit; set from GlobalPhase */
- var currentUnit: CompilationUnit = _
-
- /** Counts for certain classes of warnings during this run. */
- var deprecationWarnings: List[(Position, String)] = Nil
- var uncheckedWarnings: List[(Position, String)] = Nil
-
- /** A flag whether macro expansions failed */
- var macroExpansionFailed = false
-
/** Progress tracking. Measured in "progress units" which are 1 per
* compilation unit per phase completed.
*
@@ -936,9 +1007,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
}
def cancel() { reporter.cancelled = true }
-
- private var phasec: Int = 0 // phases completed
- private var unitc: Int = 0 // units completed this phase
+
private def currentProgress = (phasec * size) + unitc
private def totalProgress = (phaseDescriptors.size - 1) * size // -1: drops terminal phase
private def refreshProgress() = if (size > 0) progress(currentProgress, totalProgress)
@@ -977,11 +1046,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// ----------- Units and top-level classes and objects --------
- private val unitbuf = new mutable.ListBuffer[CompilationUnit]
- val compiledFiles = new mutable.HashSet[String]
-
- private var _unitbufSize = 0
- def size = _unitbufSize
/** add unit to be compiled in this run */
private def addUnit(unit: CompilationUnit) {
@@ -1005,12 +1069,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
*/
def units: Iterator[CompilationUnit] = unitbuf.iterator
- /** A map from compiled top-level symbols to their source files */
- val symSource = new mutable.HashMap[Symbol, AbstractFile]
-
- /** A map from compiled top-level symbols to their picklers */
- val symData = new mutable.HashMap[Symbol, PickleBuffer]
-
def registerPickle(sym: Symbol): Unit = {
// Convert all names to the type name: objects don't store pickled data
if (opt.showPhase && (opt.showNames exists (x => findNamedMember(x.toTypeName, sym) != NoSymbol))) {
@@ -1114,6 +1172,14 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** Compile list of units, starting with phase `fromPhase`
*/
def compileUnits(units: List[CompilationUnit], fromPhase: Phase) {
+ try compileUnitsInternal(units, fromPhase)
+ catch { case ex =>
+ globalError(supplementErrorMessage("uncaught exception during compilation: " + ex.getClass.getName))
+ throw ex
+ }
+ }
+
+ private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) {
units foreach addUnit
if (opt.profileAll) {
inform("starting CPU profiling on compilation run")
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 7b5de1f3dd..c1d6c1a4d4 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -33,17 +33,16 @@ abstract class TreeBrowsers {
val borderSize = 10
-
def create(): SwingBrowser = new SwingBrowser();
/** Pseudo tree class, so that all JTree nodes are treated uniformly */
case class ProgramTree(units: List[UnitTree]) extends Tree {
- override def toString(): String = "Program"
+ override def toString: String = "Program"
}
/** Pseudo tree class, so that all JTree nodes are treated uniformly */
case class UnitTree(unit: CompilationUnit) extends Tree {
- override def toString(): String = unit.toString()
+ override def toString: String = unit.toString
}
/**
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 88a9b5e18b..c80b07c44d 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -17,7 +17,6 @@ import scala.reflect.internal.Flags.TRAIT
trait Trees extends reflect.internal.Trees { self: Global =>
// --- additional cases --------------------------------------------------------
-
/** Only used during parsing */
case class Parens(args: List[Tree]) extends Tree
@@ -31,7 +30,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
override def isType = definition.isType
}
-
/** Either an assignment or a named argument. Only appears in argument lists,
* eliminated by typecheck (doTypedApply)
*/
@@ -40,7 +38,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
/** Array selection <qualifier> . <name> only used during erasure */
case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type)
- extends TermTree with RefTree { }
+ extends TermTree with RefTree
/** emitted by typer, eliminated by refchecks */
case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree
@@ -163,7 +161,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
traverser.traverse(qualifier)
case ReferenceToBoxed(idt) =>
traverser.traverse(idt)
- case TypeTreeWithDeferredRefCheck() => // TODO: should we traverse the wrapped tree?
+ case TypeTreeWithDeferredRefCheck() =>
// (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check)
case _ => super.xtraverse(traverser, tree)
}
@@ -225,7 +223,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
try unit.body = transform(unit.body)
catch {
case ex: Exception =>
- println("unhandled exception while transforming "+unit)
+ println(supplementErrorMessage("unhandled exception while transforming "+unit))
throw ex
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index a2a577a7ab..4478fb6128 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -468,7 +468,7 @@ trait Scanners extends ScannersCommon {
nextChar()
getOperatorRest()
} else {
- syntaxError("illegal character")
+ syntaxError("illegal character '" + ("" + '\\' + 'u' + "%04x".format(ch: Int)) + "'")
nextChar()
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index b5ec0ceffb..e310611e68 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -24,7 +24,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse
import global._
informProgress("parsing " + unit)
unit.body =
- if (unit.source.file.name.endsWith(".java")) new JavaUnitParser(unit).parse()
+ if (unit.isJava) new JavaUnitParser(unit).parse()
else if (reporter.incompleteHandled) new UnitParser(unit).parse()
else new UnitParser(unit).smartParse()
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 15b4c8c708..3d650ef753 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -179,7 +179,7 @@ abstract class GenICode extends SubComponent {
}
private def genThrow(expr: Tree, ctx: Context): (Context, TypeKind) = {
- require(expr.tpe <:< ThrowableClass.tpe)
+ require(expr.tpe <:< ThrowableClass.tpe, expr.tpe)
val thrownKind = toTypeKind(expr.tpe)
val ctx1 = genLoad(expr, ctx, thrownKind)
@@ -480,7 +480,7 @@ abstract class GenICode extends SubComponent {
*/
private def msil_genLoadZeroOfNonEnumValuetype(ctx: Context, kind: TypeKind, pos: Position, leaveAddressOnStackInstead: Boolean) {
val REFERENCE(clssym) = kind
- assert(loaders.clrTypes.isNonEnumValuetype(clssym))
+ assert(loaders.clrTypes.isNonEnumValuetype(clssym), clssym)
val local = ctx.makeLocal(pos, clssym.tpe, "tmp")
ctx.method.addLocal(local)
ctx.bb.emit(CIL_LOAD_LOCAL_ADDRESS(local), pos)
@@ -1064,7 +1064,7 @@ abstract class GenICode extends SubComponent {
var default: BasicBlock = afterCtx.bb
for (caze @ CaseDef(pat, guard, body) <- cases) {
- assert(guard == EmptyTree)
+ assert(guard == EmptyTree, guard)
val tmpCtx = ctx1.newBlock
pat match {
case Literal(value) =>
@@ -1528,7 +1528,7 @@ abstract class GenICode extends SubComponent {
if (mustUseAnyComparator) {
// when -optimise is on we call the @inline-version of equals, found in ScalaRunTime
val equalsMethod =
- if (!settings.XO.value) {
+ if (!settings.optimise.value) {
def default = platform.externalEquals
platform match {
case x: JavaPlatform =>
@@ -1550,7 +1550,7 @@ abstract class GenICode extends SubComponent {
val ctx1 = genLoad(l, ctx, ObjectReference)
val ctx2 = genLoad(r, ctx1, ObjectReference)
- ctx2.bb.emit(CALL_METHOD(equalsMethod, if (settings.XO.value) Dynamic else Static(false)))
+ ctx2.bb.emit(CALL_METHOD(equalsMethod, if (settings.optimise.value) Dynamic else Static(false)))
ctx2.bb.emit(CZJUMP(thenCtx.bb, elseCtx.bb, NE, BOOL))
ctx2.bb.close
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index 229bbceb36..f5be82a776 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -199,7 +199,7 @@ abstract class CopyPropagation {
m foreachBlock { b =>
in(b) = lattice.bottom
out(b) = lattice.bottom
- assert(out.contains(b))
+ assert(out.contains(b), out)
log("Added point: " + b)
}
m.exh foreach { e =>
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 0fea0a2d92..477cec8c8e 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -1060,6 +1060,8 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
implicit def addOnTypeError[T](x: => T): OnTypeError[T] = new OnTypeError(x)
+ // OnTypeError should still catch TypeError because of cyclic references,
+ // but DivergentImplicit shouldn't leak anymore here
class OnTypeError[T](op: => T) {
def onTypeError(alt: => T) = try {
op
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
index 494eb4d50b..b51cf1228c 100644
--- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -211,7 +211,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
var start = 0
while (true) {
val index = path.indexOf(separator, start)
- assert(index < 0 || start < index)
+ assert(index < 0 || start < index, ((path, directory, start, index)))
val name = path.substring(start, if (index < 0) length else index)
file = getFile(file, name, if (index < 0) directory else true)
if ((file eq null) || index < 0) return file
diff --git a/src/compiler/scala/tools/nsc/io/MsilFile.scala b/src/compiler/scala/tools/nsc/io/MsilFile.scala
index 69db23923d..d970d0e9c9 100644
--- a/src/compiler/scala/tools/nsc/io/MsilFile.scala
+++ b/src/compiler/scala/tools/nsc/io/MsilFile.scala
@@ -13,4 +13,6 @@ import ch.epfl.lamp.compiler.msil.{ Type => MsilType, _ }
* uniformly, as AbstractFiles.
*/
class MsilFile(val msilType: MsilType) extends VirtualFile(msilType.FullName, msilType.Namespace) {
-} \ No newline at end of file
+}
+
+object NoMsilFile extends MsilFile(null) { }
diff --git a/src/compiler/scala/tools/nsc/io/NoAbstractFile.scala b/src/compiler/scala/tools/nsc/io/NoAbstractFile.scala
new file mode 100644
index 0000000000..36cf42d7ec
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/NoAbstractFile.scala
@@ -0,0 +1,30 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package io
+
+import java.io.InputStream
+
+/** A distinguished object so you can avoid both null
+ * and Option.
+ */
+object NoAbstractFile extends AbstractFile {
+ def absolute: AbstractFile = this
+ def container: AbstractFile = this
+ def create(): Unit = ???
+ def delete(): Unit = ???
+ def file: JFile = null
+ def input: InputStream = null
+ def isDirectory: Boolean = false
+ def iterator: Iterator[AbstractFile] = Iterator.empty
+ def lastModified: Long = 0L
+ def lookupName(name: String, directory: Boolean): AbstractFile = null
+ def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile = null
+ def name: String = ""
+ def output: java.io.OutputStream = null
+ def path: String = ""
+ override def toByteArray = Array[Byte]()
+}
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index e5748b7c23..18409cfffe 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -37,7 +37,7 @@ trait Patterns extends ast.TreeDSL {
// }
private lazy val dummyMethod =
- new TermSymbol(NoSymbol, NoPosition, newTermName("matching$dummy"))
+ NoSymbol.newTermSymbol(newTermName("matching$dummy"))
// Fresh patterns
def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index 36227c1052..da913a1601 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -28,7 +28,7 @@ trait Plugins {
val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map Path.apply
val classes = Plugin.loadAllFrom(jars, dirs, settings.disable.value)
- // Lach plugin must only be instantiated once. A common pattern
+ // Each plugin must only be instantiated once. A common pattern
// is to register annotation checkers during object construction, so
// creating multiple plugin instances will leave behind stale checkers.
classes map (Plugin.instantiate(_, this))
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index 967b582f11..c76a04c6ba 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -47,20 +47,7 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
/** Prints the message with the given position indication. */
def printMessage(posIn: Position, msg: String) {
- val pos = if (posIn eq null) NoPosition
- else if (posIn.isDefined) posIn.inUltimateSource(posIn.source)
- else posIn
- pos match {
- case FakePos(fmsg) =>
- printMessage(fmsg+" "+msg)
- case NoPosition =>
- printMessage(msg)
- case _ =>
- val buf = new StringBuilder(msg)
- val file = pos.source.file
- printMessage((if (shortname) file.name else file.path)+":"+pos.line+": "+msg)
- printSourceLine(pos)
- }
+ printMessage(Position.formatMessage(posIn, msg, shortname))
}
def print(pos: Position, msg: String, severity: Severity) {
printMessage(pos, clabel(severity) + msg)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 6806ca03ba..107ffc35c6 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -140,6 +140,7 @@ trait ScalaSettings extends AbsScalaSettings
val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.")
val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs.")
val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
+ val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
val skip = PhasesSetting ("-Yskip", "Skip")
val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 4205c2ff36..942ec1fa86 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -207,7 +207,7 @@ abstract class SymbolLoaders {
protected def doComplete(root: Symbol) {
assert(root.isPackageClass, root)
- root.setInfo(new PackageClassInfoType(new Scope(), root))
+ root.setInfo(new PackageClassInfoType(newScope, root))
val sourcepaths = classpath.sourcepaths
for (classRep <- classpath.classes if platform.doLoad(classRep)) {
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 099145d3ae..ac6dca4422 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -392,7 +392,7 @@ abstract class ClassfileParser {
}
def getBytes(indices: List[Int]): Array[Byte] = {
- assert(!indices.isEmpty)
+ assert(!indices.isEmpty, indices)
var value = values(indices.head).asInstanceOf[Array[Byte]]
if (value eq null) {
val bytesBuffer = ArrayBuffer.empty[Byte]
@@ -536,8 +536,8 @@ abstract class ClassfileParser {
addEnclosingTParams(clazz)
parseInnerClasses() // also sets the isScala / isScalaRaw / hasMeta flags, see r15956
// get the class file parser to reuse scopes.
- instanceDefs = new Scope
- staticDefs = new Scope
+ instanceDefs = newScope
+ staticDefs = newScope
val classInfo = ClassInfoType(parseParents, instanceDefs, clazz)
val staticInfo = ClassInfoType(List(), staticDefs, statics)
@@ -606,7 +606,7 @@ abstract class ClassfileParser {
def parseField() {
val jflags = in.nextChar
var sflags = toScalaFieldFlags(jflags)
- if ((sflags & PRIVATE) != 0L && !global.settings.XO.value) {
+ if ((sflags & PRIVATE) != 0L && !global.settings.optimise.value) {
in.skip(4); skipAttributes()
} else {
val name = pool.getName(in.nextChar)
@@ -637,7 +637,7 @@ abstract class ClassfileParser {
def parseMethod() {
val jflags = in.nextChar.toInt
var sflags = toScalaMethodFlags(jflags)
- if (isPrivate(jflags) && !global.settings.XO.value) {
+ if (isPrivate(jflags) && !global.settings.optimise.value) {
val name = pool.getName(in.nextChar)
if (name == nme.CONSTRUCTOR)
sawPrivateConstructor = true
@@ -645,7 +645,7 @@ abstract class ClassfileParser {
} else {
if ((jflags & JAVA_ACC_BRIDGE) != 0)
sflags |= BRIDGE
- if ((sflags & PRIVATE) != 0L && global.settings.XO.value) {
+ if ((sflags & PRIVATE) != 0L && global.settings.optimise.value) {
in.skip(4); skipAttributes()
} else {
val name = pool.getName(in.nextChar)
@@ -679,7 +679,7 @@ abstract class ClassfileParser {
var index = 0
val end = sig.length
def accept(ch: Char) {
- assert(sig(index) == ch)
+ assert(sig(index) == ch, (sig(index), ch))
index += 1
}
def subName(isDelimiter: Char => Boolean): Name = {
@@ -736,7 +736,7 @@ abstract class ClassfileParser {
}
}
accept('>')
- assert(xs.length > 0)
+ assert(xs.length > 0, tp)
newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList))
} else if (classSym.isMonomorphicType) {
tp
@@ -750,7 +750,7 @@ abstract class ClassfileParser {
res
}
case tp =>
- assert(sig(index) != '<')
+ assert(sig(index) != '<', tp)
tp
}
@@ -776,7 +776,7 @@ abstract class ClassfileParser {
appliedType(definitions.ArrayClass.tpe, List(elemtp))
case '(' =>
// we need a method symbol. given in line 486 by calling getType(methodSym, ..)
- assert(sym ne null)
+ assert(sym ne null, sig)
val paramtypes = new ListBuffer[Type]()
while (sig(index) != ')') {
paramtypes += objToAny(sig2type(tparams, skiptvs))
@@ -809,7 +809,7 @@ abstract class ClassfileParser {
var tparams = classTParams
val newTParams = new ListBuffer[Symbol]()
if (sig(index) == '<') {
- assert(sym != null)
+ assert(sym != null, sig)
index += 1
val start = index
while (sig(index) != '>') {
@@ -974,18 +974,18 @@ abstract class ClassfileParser {
def parseScalaSigBytes: Option[ScalaSigBytes] = {
val tag = in.nextByte.toChar
- assert(tag == STRING_TAG)
+ assert(tag == STRING_TAG, tag)
Some(ScalaSigBytes(pool getBytes in.nextChar))
}
def parseScalaLongSigBytes: Option[ScalaSigBytes] = {
val tag = in.nextByte.toChar
- assert(tag == ARRAY_TAG)
+ assert(tag == ARRAY_TAG, tag)
val stringCount = in.nextChar
val entries =
for (i <- 0 until stringCount) yield {
val stag = in.nextByte.toChar
- assert(stag == STRING_TAG)
+ assert(stag == STRING_TAG, stag)
in.nextChar.toInt
}
Some(ScalaSigBytes(pool.getBytes(entries.toList)))
@@ -1208,7 +1208,12 @@ abstract class ClassfileParser {
atPhase(currentRun.typerPhase)(getMember(sym, innerName.toTypeName))
else
getMember(sym, innerName.toTypeName)
- assert(s ne NoSymbol, sym + "." + innerName + " linkedModule: " + sym.companionModule + sym.companionModule.info.members)
+
+ assert(s ne NoSymbol,
+ "" + ((externalName, outerName, innerName, sym.fullLocationString)) + " / " +
+ " while parsing " + ((in.file, busy)) +
+ sym + "." + innerName + " linkedModule: " + sym.companionModule + sym.companionModule.info.members
+ )
s
case None =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 3c97122c9c..7d42dabc08 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -434,7 +434,7 @@ abstract class ICodeReader extends ClassfileParser {
val padding = if ((pc + size) % 4 != 0) 4 - ((pc + size) % 4) else 0
size += padding
in.bp += padding
- assert((pc + size % 4) != 0)
+ assert((pc + size % 4) != 0, pc)
/* var byte1 = in.nextByte; size += 1;
while (byte1 == 0) { byte1 = in.nextByte; size += 1; }
val default = byte1 << 24 | in.nextByte << 16 | in.nextByte << 8 | in.nextByte;
@@ -454,7 +454,7 @@ abstract class ICodeReader extends ClassfileParser {
val padding = if ((pc + size) % 4 != 0) 4 - ((pc + size) % 4) else 0
size += padding
in.bp += padding
- assert((pc + size % 4) != 0)
+ assert((pc + size % 4) != 0, pc)
val default = pc + in.nextInt; size += 4
val npairs = in.nextInt; size += 4
var tags: List[List[Int]] = Nil
@@ -988,7 +988,7 @@ abstract class ICodeReader extends ClassfileParser {
def enterParam(idx: Int, kind: TypeKind) = {
val sym = method.symbol.newVariable(newTermName("par" + idx)).setInfo(kind.toType)
val l = new Local(sym, kind, true)
- assert(!locals.isDefinedAt(idx))
+ assert(!locals.isDefinedAt(idx), locals(idx))
locals += (idx -> List((l, kind)))
l
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
index ead431c8d7..eb8e7a14a5 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
@@ -108,7 +108,7 @@ abstract class MetaParser{
}
protected def parseClass() {
- locals = new Scope
+ locals = newScope
def parse(): Type = {
nextToken()
if (token == "[") {
@@ -130,7 +130,7 @@ abstract class MetaParser{
protected def parseMethod() {
val globals = locals
- locals = if (locals eq null) new Scope else new Scope(locals)
+ locals = if (locals eq null) newScope else newNestedScope(locals)
def parse(): Type = {
nextToken();
if (token == "[") PolyType(parseTypeParams(), parse())
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 2eddd36db0..25ae6f33d2 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -59,7 +59,7 @@ abstract class Pickler extends SubComponent {
}
}
// If there are any erroneous types in the tree, then we will crash
- // when we pickle it: so let's report an erorr instead. We know next
+ // when we pickle it: so let's report an error instead. We know next
// to nothing about what happened, but our supposition is a lot better
// than "bad type: <error>" in terms of explanatory power.
for (t <- unit.body ; if t.isErroneous) {
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 6c238f52cc..e11a5a4ad9 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -165,7 +165,7 @@ abstract class TypeParser {
clrTypes.sym2type(typMgdPtr) = clazzMgdPtr
/* clazzMgdPtr but not clazzBoxed is mapped by clrTypes.types into an msil.Type instance,
because there's no metadata-level representation for a "boxed valuetype" */
- val instanceDefsMgdPtr = new Scope
+ val instanceDefsMgdPtr = newScope
val classInfoMgdPtr = ClassInfoType(definitions.anyvalparam, instanceDefsMgdPtr, clazzMgdPtr)
clazzMgdPtr.setFlag(flags)
clazzMgdPtr.setInfo(classInfoMgdPtr)
@@ -196,8 +196,8 @@ abstract class TypeParser {
}
}
/* END CLR generics (snippet 2) */
- instanceDefs = new Scope
- staticDefs = new Scope
+ instanceDefs = newScope
+ staticDefs = newScope
val classInfoAsInMetadata = {
val ifaces: Array[MSILType] = typ.getInterfaces()
@@ -212,7 +212,7 @@ abstract class TypeParser {
}
// methods, properties, events, fields are entered in a moment
if (canBeTakenAddressOf) {
- val instanceDefsBoxed = new Scope
+ val instanceDefsBoxed = newScope
ClassInfoType(parents.toList, instanceDefsBoxed, clazzBoxed)
} else
ClassInfoType(parents.toList, instanceDefs, clazz)
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 8f5d308b8f..e01bbccf13 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -77,31 +77,57 @@ abstract class AddInterfaces extends InfoTransform {
def implClassPhase = currentRun.erasurePhase.next
/** Return the implementation class of a trait; create a new one of one does not yet exist */
- def implClass(iface: Symbol): Symbol = implClassMap.getOrElse(iface, {
- atPhase(implClassPhase) {
- val implName = nme.implClassName(iface.name)
- var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol
- if (impl != NoSymbol && settings.XO.value) {
- log("unlinking impl class " + impl)
- iface.owner.info.decls.unlink(impl)
- impl = NoSymbol
- }
- if (impl == NoSymbol) {
- impl = iface.cloneSymbolImpl(iface.owner)
- impl.name = implName
- impl.sourceFile = iface.sourceFile
- if (iface.owner.isClass)
- iface.owner.info.decls enter impl
+ def implClass(iface: Symbol): Symbol = {
+ iface.info
+
+ implClassMap.getOrElse(iface, {
+ atPhase(implClassPhase) {
+ log("%s.implClass == %s".format(iface, iface.implClass))
+ val implName = nme.implClassName(iface.name)
+ var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol
+
+ // !!! Why does forcing the impl's info here lead to a crash?
+ // See test case pos/trait-force-info.scala for a minimization.
+ // It crashes like this:
+ //
+ // [log lazyvals] trait ContextTrees.implClass == class ContextTrees$class
+ // error: java.lang.AssertionError: assertion failed: (scala.tools.nsc.typechecker.Contexts$NoContext$,scala.tools.nsc.typechecker.Contexts,NoContext$,trait Contexts in package typechecker) / while parsing (/scala/trunk/build/pack/lib/scala-compiler.jar(scala/tools/nsc/interactive/ContextTrees$class.class),Some(class ContextTrees$class))trait Contexts.NoContext$ linkedModule: <none>List()
+
+ val originalImpl = impl
+ val originalImplString = originalImpl.hasFlagsToString(-1L)
+ if (impl != NoSymbol) {
+ // Unlink a pre-existing symbol only if the implementation class is
+ // visible on the compilation classpath. In general this is true under
+ // -optimise and not otherwise, but the classpath can use arbitrary
+ // logic so the classpath must be queried.
+ if (classPath.context.isValidName(implName + ".class")) {
+ log("unlinking impl class " + impl)
+ iface.owner.info.decls.unlink(impl)
+ impl = NoSymbol
+ }
+ else log("not unlinking existing " + impl + " as the impl class is not visible on the classpath.")
+ }
+ if (impl == NoSymbol) {
+ impl = iface.cloneSymbolImpl(iface.owner)
+ impl.name = implName
+ impl.sourceFile = iface.sourceFile
+ if (iface.owner.isClass)
+ iface.owner.info.decls enter impl
+ }
+ if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile
+ impl setPos iface.pos
+ impl.flags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS
+ impl setInfo new LazyImplClassType(iface)
+ implClassMap(iface) = impl
+ debuglog(
+ "generating impl class " + impl + " " + impl.hasFlagsToString(-1L) + " in " + iface.owner + (
+ if (originalImpl == NoSymbol) "" else " (cloned from " + originalImpl.fullLocationString + " " + originalImplString + ")"
+ )
+ )
+ impl
}
- if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile
- impl setPos iface.pos
- impl.flags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS
- impl setInfo new LazyImplClassType(iface)
- implClassMap(iface) = impl
- debuglog("generating impl class " + impl + " in " + iface.owner)//debug
- impl
- }
- })
+ })
+ }
/** A lazy type to set the info of an implementation class
* The parents of an implementation class for trait iface are:
@@ -119,7 +145,7 @@ abstract class AddInterfaces extends InfoTransform {
* given the decls ifaceDecls of its interface.
*/
private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
- val decls = new Scope
+ val decls = newScope
if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol)
decls enter (
implClass.newMethod(nme.MIXIN_CONSTRUCTOR, implClass.pos)
@@ -159,7 +185,7 @@ abstract class AddInterfaces extends InfoTransform {
)
def implType(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, _) =>
- assert(phase == implClassPhase)
+ assert(phase == implClassPhase, tp)
ClassInfoType(
ObjectClass.tpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe,
implDecls(sym, decls),
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 23817545e2..d1c71faf1e 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -447,7 +447,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
val closureClass = clazz.newClass(nme.delayedInitArg.toTypeName, impl.pos, SYNTHETIC | FINAL)
val closureParents = List(AbstractFunctionClass(0).tpe, ScalaObjectClass.tpe)
- closureClass setInfoAndEnter new ClassInfoType(closureParents, new Scope, closureClass)
+ closureClass setInfoAndEnter new ClassInfoType(closureParents, newScope, closureClass)
val outerField = (
closureClass
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 71696c24e6..fe479a5375 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -742,7 +742,7 @@ abstract class Erasure extends AddInterfaces
//println("computing bridges for " + owner)//DEBUG
assert(phase == currentRun.erasurePhase)
val site = owner.thisType
- val bridgesScope = new Scope
+ val bridgesScope = newScope
val bridgeTarget = new mutable.HashMap[Symbol, Symbol]
var bridges: List[Tree] = List()
val opc = atPhase(currentRun.explicitouterPhase) {
@@ -797,7 +797,7 @@ abstract class Erasure extends AddInterfaces
// && (bridge.paramss.nonEmpty && bridge.paramss.head.nonEmpty && bridge.paramss.head.tail.isEmpty) // does the first argument list has exactly one argument -- for user-defined unapplies we can't be sure
&& !(atPhase(phase.next)(member.tpe <:< other.tpe))) { // no static guarantees (TODO: is the subtype test ever true?)
import CODE._
- val typeTest = gen.mkIsInstanceOf(REF(bridge.paramss.head.head), member.tpe.params.head.tpe, any = true, wrapInApply = true) // any = true since we're before erasure (?), wrapInapply is true since we're after uncurry
+ val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe, any = true, wrapInApply = true) // any = true since we're before erasure (?), wrapInapply is true since we're after uncurry
// println("unapp type test: "+ typeTest)
IF (typeTest) THEN bridgingCall ELSE REF(NoneModule)
} else bridgingCall
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 14f3dc16fa..7f7f7e7b65 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -427,7 +427,7 @@ abstract class ExplicitOuter extends InfoTransform
}
val t = atPos(tree.pos) {
- val context = MatrixContext(currentRun.currentUnit, transform, localTyper, currentOwner, tree.tpe)
+ val context = MatrixContext(currentUnit, transform, localTyper, currentOwner, tree.tpe)
val t_untyped = handlePattern(nselector, ncases, checkExhaustive, context)
/* if @switch annotation is present, verify the resulting tree is a Match */
@@ -506,7 +506,7 @@ abstract class ExplicitOuter extends InfoTransform
val outerVal = atPos(tree.pos)(qual match {
// it's a call between constructors of same class
case _: This =>
- assert(outerParam != NoSymbol)
+ assert(outerParam != NoSymbol, tree)
outerValue
case _ =>
gen.mkAttributedQualifier(qual.tpe.prefix match {
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index b17fd7b9b0..4fa5b52de3 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -65,7 +65,7 @@ abstract class Flatten extends InfoTransform {
case ClassInfoType(parents, decls, clazz) =>
var parents1 = parents
val decls1 = scopeTransform(clazz) {
- val decls1 = new Scope()
+ val decls1 = newScope
if (clazz.isPackageClass) {
atPhase(phase.next)(decls foreach (decls1 enter _))
} else {
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 0f11161914..712298bd89 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -9,7 +9,8 @@ package transform
import symtab._
import Flags._
import util.TreeSet
-import scala.collection.mutable.{ LinkedHashMap, ListBuffer }
+import scala.collection.{ mutable, immutable }
+import scala.collection.mutable.LinkedHashMap
abstract class LambdaLift extends InfoTransform {
import global._
@@ -64,6 +65,8 @@ abstract class LambdaLift extends InfoTransform {
/** The set of symbols that need to be renamed. */
private val renamable = newSymSet
+ private val renamableImplClasses = mutable.HashMap[Name, Symbol]() withDefaultValue NoSymbol
+
/** A flag to indicate whether new free variables have been found */
private var changedFreeVars: Boolean = _
@@ -152,7 +155,21 @@ abstract class LambdaLift extends InfoTransform {
tree match {
case ClassDef(_, _, _, _) =>
liftedDefs(tree.symbol) = Nil
- if (sym.isLocal) renamable addEntry sym
+ if (sym.isLocal) {
+ // Don't rename implementation classes independently of their interfaces. If
+ // the interface is to be renamed, then we will rename the implementation
+ // class at that time. You'd think we could call ".implClass" on the trait
+ // rather than collecting them in another map, but that seems to fail for
+ // exactly the traits being renamed here (i.e. defined in methods.)
+ //
+ // !!! - it makes no sense to have methods like "implClass" and
+ // "companionClass" which fail for an arbitrary subset of nesting
+ // arrangements, and then have separate methods which attempt to compensate
+ // for that failure. There should be exactly one method for any given
+ // entity which always gives the right answer.
+ if (sym.isImplClass) renamableImplClasses(nme.interfaceName(sym.name)) = sym
+ else renamable addEntry sym
+ }
case DefDef(_, _, _, _, _, _) =>
if (sym.isLocal) {
renamable addEntry sym
@@ -196,8 +213,8 @@ abstract class LambdaLift extends InfoTransform {
for (caller <- called.keys ; callee <- called(caller) ; fvs <- free get callee ; fv <- fvs)
markFree(fv, caller)
} while (changedFreeVars)
-
- for (sym <- renamable) {
+
+ def renameSym(sym: Symbol) {
val originalName = sym.name
val base = sym.name + nme.NAME_JOIN_STRING + (
if (sym.isAnonymousFunction && sym.owner.isMethod)
@@ -211,6 +228,25 @@ abstract class LambdaLift extends InfoTransform {
debuglog("renaming in %s: %s => %s".format(sym.owner.fullLocationString, originalName, sym.name))
}
+ /** Rename a trait's interface and implementation class in coordinated fashion.
+ */
+ def renameTrait(traitSym: Symbol, implSym: Symbol) {
+ val originalImplName = implSym.name
+ renameSym(traitSym)
+ implSym.name = nme.implClassName(traitSym.name)
+
+ debuglog("renaming impl class in step with %s: %s => %s".format(traitSym, originalImplName, implSym.name))
+ }
+
+ for (sym <- renamable) {
+ // If we renamed a trait from Foo to Foo$1, we must rename the implementation
+ // class from Foo$class to Foo$1$class. (Without special consideration it would
+ // become Foo$class$1 instead.)
+ val implClass = if (sym.isTrait) renamableImplClasses(sym.name) else NoSymbol
+ if ((implClass ne NoSymbol) && (sym.owner == implClass.owner)) renameTrait(sym, implClass)
+ else renameSym(sym)
+ }
+
atPhase(phase.next) {
for ((owner, freeValues) <- free.toList) {
val newFlags = SYNTHETIC | ( if (owner.isClass) PARAMACCESSOR | PrivateLocal else PARAM )
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index bf19cf10e9..b3b7596f9a 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -403,12 +403,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
assert(clazz.sourceModule != NoSymbol || clazz.isAnonymousClass,
clazz + " has no sourceModule: sym = " + sym + " sym.tpe = " + sym.tpe)
parents1 = List()
- decls1 = new Scope(decls.toList filter isImplementedStatically)
+ decls1 = newScopeWith(decls.toList filter isImplementedStatically: _*)
} else if (!parents.isEmpty) {
parents1 = parents.head :: (parents.tail map toInterface)
}
}
- //decls1 = atPhase(phase.next)(new Scope(decls1.toList))//debug
+ //decls1 = atPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug
if ((parents1 eq parents) && (decls1 eq decls)) tp
else ClassInfoType(parents1, decls1, clazz)
@@ -480,7 +480,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** The rootContext used for typing */
private val rootContext =
- erasure.NoContext.make(EmptyTree, RootClass, new Scope)
+ erasure.NoContext.make(EmptyTree, RootClass, newScope)
/** The typer */
private var localTyper: erasure.Typer = _
@@ -1053,7 +1053,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else accessedRef match {
case Literal(_) => accessedRef
case _ =>
- val init = Assign(accessedRef, Ident(sym.paramss.head.head))
+ val init = Assign(accessedRef, Ident(sym.firstParam))
val getter = sym.getter(clazz)
if (!needsInitFlag(getter)) init
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 70f8d37585..1200e973c5 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -74,7 +74,7 @@ abstract class OverridingPairs {
}
/** The symbols that can take part in an overriding pair */
- private val decls = new Scope
+ private val decls = newScope
// fill `decls` with overriding shadowing overridden */
{ def fillDecls(bcs: List[Symbol], deferredflag: Int) {
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index fd826fb6d8..4a104857db 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -502,7 +502,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
typeEnv(sClass) = env
this.specializedClass((clazz, env0)) = sClass
- val decls1 = new Scope // declarations of the newly specialized class 'sClass'
+ val decls1 = newScope // declarations of the newly specialized class 'sClass'
var oldClassTParams: List[Symbol] = Nil // original unspecialized type parameters
var newClassTParams: List[Symbol] = Nil // unspecialized type parameters of 'specializedClass' (cloned)
@@ -1089,7 +1089,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (tparams.nonEmpty) " (poly)" else "",
clazz, parents1, phase)
)
- val newScope = new Scope(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz))
+ val newScope = newScopeWith(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz): _*)
// If tparams.isEmpty, this is just the ClassInfoType.
polyType(tparams, ClassInfoType(parents1, newScope, clazz))
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 56d9658377..ab4a2141a9 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -259,7 +259,7 @@ abstract class UnCurry extends InfoTransform
else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe)
- anonClass setInfo ClassInfoType(parents, new Scope, anonClass)
+ anonClass setInfo ClassInfoType(parents, newScope, anonClass)
val applyMethod = anonClass.newMethod(nme.apply, fun.pos, FINAL)
applyMethod setInfoAndEnter MethodType(applyMethod newSyntheticValueParams formals, restpe)
anonClass addAnnotation serialVersionUIDAnnotation
@@ -422,7 +422,7 @@ abstract class UnCurry extends InfoTransform
if (tp.typeSymbol.isBottomClass) getManifest(AnyClass.tpe)
else if (!manifestOpt.tree.isEmpty) manifestOpt.tree
else if (tp.bounds.hi ne tp) getManifest(tp.bounds.hi)
- else localTyper.getManifestTree(tree.pos, tp, false)
+ else localTyper.getManifestTree(tree, tp, false)
}
atPhase(phase.next) {
localTyper.typedPos(pos) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 16d55c26ca..18c7635b1e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -23,6 +23,7 @@ trait Analyzer extends AnyRef
with Macros
with NamesDefaults
with TypeDiagnostics
+ with ContextErrors
{
val global : Global
import global._
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
new file mode 100644
index 0000000000..6ee09d064f
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -0,0 +1,1056 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package typechecker
+
+import scala.collection.{ mutable, immutable }
+import scala.tools.util.StringOps.{ countElementsAsString, countAsString }
+import symtab.Flags.{ PRIVATE, PROTECTED }
+import scala.tools.util.EditDistance.similarString
+
+trait ContextErrors {
+ self: Analyzer =>
+
+ import global._
+
+ object ErrorKinds extends Enumeration {
+ type ErrorKind = Value
+ val Normal, Access, Ambiguous, Divergent = Value
+ }
+
+ import ErrorKinds.ErrorKind
+
+ trait AbsTypeError extends Throwable {
+ def errPos: Position
+ def errMsg: String
+ def kind: ErrorKind
+ }
+
+ case class NormalTypeError(underlyingTree: Tree, errMsg: String, kind: ErrorKind = ErrorKinds.Normal)
+ extends AbsTypeError {
+
+ def errPos:Position = underlyingTree.pos
+ override def toString() = "[Type error at:" + underlyingTree.pos + "] " + errMsg
+ }
+
+ case class SymbolTypeError(underlyingSym: Symbol, errMsg: String, kind: ErrorKind = ErrorKinds.Normal)
+ extends AbsTypeError {
+
+ def errPos = underlyingSym.pos
+ }
+
+ case class TypeErrorWrapper(ex: TypeError, kind: ErrorKind = ErrorKinds.Normal)
+ extends AbsTypeError {
+ def errMsg = ex.msg
+ def errPos = ex.pos
+ }
+
+ case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError, kind: ErrorKind = ErrorKinds.Normal)
+ extends AbsTypeError {
+ def errMsg = ex.msg
+ def errPos = tree.pos
+ }
+
+ case class AmbiguousTypeError(underlyingTree: Tree, errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Ambiguous) extends AbsTypeError
+
+ case class PosAndMsgTypeError(errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError
+
+ object ErrorUtils {
+ def issueNormalTypeError(tree: Tree, msg: String)(implicit context: Context) {
+ issueTypeError(NormalTypeError(tree, msg))
+ }
+
+ def issueSymbolTypeError(sym: Symbol, msg: String)(implicit context: Context) {
+ issueTypeError(SymbolTypeError(sym, msg))
+ }
+
+ def issueDivergentImplicitsError(tree: Tree, msg: String)(implicit context: Context) {
+ issueTypeError(NormalTypeError(tree, msg, ErrorKinds.Divergent))
+ }
+
+ def issueAmbiguousTypeError(pre: Type, sym1: Symbol, sym2: Symbol, err: AmbiguousTypeError)(implicit context: Context) {
+ context.issueAmbiguousError(pre, sym1, sym2, err)
+ }
+
+ def issueTypeError(err: AbsTypeError)(implicit context: Context) { context.issue(err) }
+
+ def typeErrorMsg(found: Type, req: Type, possiblyMissingArgs: Boolean) = {
+ def missingArgsMsg = if (possiblyMissingArgs) "\n possible cause: missing arguments for method or constructor" else ""
+ "type mismatch" + foundReqMsg(found, req) + missingArgsMsg
+ }
+ }
+
+ import ErrorUtils._
+
+ trait TyperContextErrors {
+ self: Typer =>
+
+ import infer.setError
+
+ object TyperErrorGen {
+ implicit val context0: Context = infer.getContext
+
+ def UnstableTreeError(tree: Tree) = {
+ def addendum = {
+ "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile."
+ }
+ issueNormalTypeError(tree,
+ "stable identifier required, but "+tree+" found." + (
+ if (isStableExceptVolatile(tree)) addendum else ""))
+ setError(tree)
+ }
+
+ def NoImplicitFoundError(tree: Tree, param: Symbol) = {
+ def errMsg = {
+ val paramName = param.name
+ val paramTp = param.tpe
+ paramTp.typeSymbol match {
+ case ImplicitNotFoundMsg(msg) => msg.format(paramName, paramTp)
+ case _ =>
+ "could not find implicit value for "+
+ (if (paramName startsWith nme.EVIDENCE_PARAM_PREFIX) "evidence parameter of type "
+ else "parameter "+paramName+": ")+paramTp
+ }
+ }
+ issueNormalTypeError(tree, errMsg)
+ }
+
+ def AdaptTypeError(tree: Tree, found: Type, req: Type) = {
+ // If the expected type is a refinement type, and the found type is a refinement or an anon
+ // class, we can greatly improve the error message by retyping the tree to recover the actual
+ // members present, then display along with the expected members. This is done here because
+ // this is the last point where we still have access to the original tree, rather than just
+ // the found/req types.
+ val foundType: Type = req.normalize match {
+ case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass =>
+ val retyped = typed (tree.duplicate setType null)
+ val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
+
+ if (foundDecls.isEmpty) found
+ else {
+ // The members arrive marked private, presumably because there was no
+ // expected type and so they're considered members of an anon class.
+ foundDecls foreach (_ resetFlag (PRIVATE | PROTECTED))
+ // TODO: if any of the found parents match up with required parents after normalization,
+ // print the error so that they match. The major beneficiary there would be
+ // java.lang.Object vs. AnyRef.
+ refinedType(found.parents, found.typeSymbol.owner, foundDecls, tree.pos)
+ }
+ case _ =>
+ found
+ }
+ assert(!found.isErroneous && !req.isErroneous, (found, req))
+
+ issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req))) )
+ if (settings.explaintypes.value)
+ explainTypes(found, req)
+ }
+
+ def WithFilterError(tree: Tree, ex: AbsTypeError) = {
+ issueTypeError(ex)
+ setError(tree)
+ }
+
+ def ParentTypesError(templ: Template, ex: TypeError) = {
+ templ.tpe = null
+ issueNormalTypeError(templ, ex.getMessage())
+ }
+
+ // additional parentTypes errors
+ def ConstrArgsInTraitParentTpeError(arg: Tree, parent: Symbol) =
+ issueNormalTypeError(arg, parent + " is a trait; does not take constructor arguments")
+
+ def MissingTypeArgumentsParentTpeError(supertpt: Tree) =
+ issueNormalTypeError(supertpt, "missing type arguments")
+
+ // typedIdent
+ def AmbiguousIdentError(tree: Tree, name: Name, msg: String) =
+ NormalTypeError(tree, "reference to " + name + " is ambiguous;\n" + msg)
+
+ def SymbolNotFoundError(tree: Tree, name: Name, owner: Symbol, startingIdentCx: Context) = {
+ /*** Disabled pending investigation of performance impact.
+
+ // This laborious determination arrived at to keep the tests working.
+ val calcSimilar = (
+ name.length > 2 && (
+ startingIdentCx.reportErrors
+ || startingIdentCx.enclClassOrMethod.reportErrors
+ )
+ )
+ // avoid calculating if we're in "silent" mode.
+ // name length check to limit unhelpful suggestions for e.g. "x" and "b1"
+ val similar = {
+ if (!calcSimilar) ""
+ else {
+ val allowed = (
+ startingIdentCx.enclosingContextChain
+ flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols))
+ filter (sym => sym.isTerm == name.isTermName)
+ filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName)
+ )
+ val allowedStrings = (
+ allowed.map("" + _.name).distinct.sorted
+ filterNot (s => (s contains '$') || (s contains ' '))
+ )
+ similarString("" + name, allowedStrings)
+ }
+ }
+ */
+ val similar = ""
+ NormalTypeError(tree, "not found: "+decodeWithKind(name, owner) + similar)
+ }
+
+ // typedAppliedTypeTree
+ def AppliedTypeNoParametersError(tree: Tree, errTpe: Type) = {
+ issueNormalTypeError(tree, errTpe + " does not take type parameters")
+ setError(tree)
+ }
+
+ def AppliedTypeWrongNumberOfArgsError(tree: Tree, tpt: Tree, tparams: List[Symbol]) = {
+ val tptSafeString: String = try {
+ tpt.tpe.toString()
+ } catch {
+ case _: CyclicReference =>
+ tpt.toString()
+ }
+ val msg = "wrong number of type arguments for "+tptSafeString+", should be "+tparams.length
+ issueNormalTypeError(tree, msg)
+ setError(tree)
+ }
+
+ // typedTypeDef
+ def LowerBoundError(tree: TypeDef, lowB: Type, highB: Type) =
+ issueNormalTypeError(tree, "lower bound "+lowB+" does not conform to upper bound "+highB)
+
+ def HiddenSymbolWithError[T <: Tree](tree: T): T =
+ setError(tree)
+
+ def SymbolEscapesScopeError[T <: Tree](tree: T, badSymbol: Symbol): T = {
+ val modifierString = if (badSymbol.isPrivate) "private " else ""
+ issueNormalTypeError(tree, modifierString + badSymbol + " escapes its defining scope as part of type "+tree.tpe)
+ setError(tree)
+ }
+
+ // typedDefDef
+ def StarParamNotLastError(param: Tree) =
+ issueNormalTypeError(param, "*-parameter must come last")
+
+ def StarWithDefaultError(meth: Symbol) =
+ issueSymbolTypeError(meth, "a parameter section with a `*'-parameter is not allowed to have default arguments")
+
+ def InvalidConstructorDefError(ddef: Tree) =
+ issueNormalTypeError(ddef, "constructor definition not allowed here")
+
+ def DeprecatedParamNameError(param: Symbol, name: Name) =
+ issueSymbolTypeError(param, "deprecated parameter name "+ name +" has to be distinct from any other parameter name (deprecated or not).")
+
+ // computeParamAliases
+ def SuperConstrReferenceError(tree: Tree) =
+ NormalTypeError(tree, "super constructor cannot be passed a self reference unless parameter is declared by-name")
+
+ def SuperConstrArgsThisReferenceError(tree: Tree) =
+ NormalTypeError(tree, "super constructor arguments cannot reference unconstructed `this`")
+
+ // typedValDef
+ def VolatileValueError(vdef: Tree) =
+ issueNormalTypeError(vdef, "values cannot be volatile")
+
+ def FinalVolatileVarError(vdef: Tree) =
+ issueNormalTypeError(vdef, "final vars cannot be volatile")
+
+ def LocalVarUninitializedError(vdef: Tree) =
+ issueNormalTypeError(vdef, "local variables must be initialized")
+
+ //typedAssign
+ def AssignmentError(tree: Tree, varSym: Symbol) = {
+ issueNormalTypeError(tree,
+ if (varSym != null && varSym.isValue) "reassignment to val"
+ else "assignment to non variable")
+ setError(tree)
+ }
+
+ def UnexpectedTreeAssignmentConversionError(tree: Tree) = {
+ issueNormalTypeError(tree, "Unexpected tree during assignment conversion.")
+ setError(tree)
+ }
+
+ def MultiDimensionalArrayError(tree: Tree) = {
+ issueNormalTypeError(tree, "cannot create a generic multi-dimensional array of more than "+ definitions.MaxArrayDims+" dimensions")
+ setError(tree)
+ }
+
+ //typedSuper
+ def MixinMissingParentClassNameError(tree: Tree, mix: Name, clazz: Symbol) =
+ issueNormalTypeError(tree, mix+" does not name a parent class of "+clazz)
+
+ def AmbiguousParentClassError(tree: Tree) =
+ issueNormalTypeError(tree, "ambiguous parent class qualifier")
+
+ //typedSelect
+ def NotAMemberError(sel: Tree, qual: Tree, name: Name) = {
+ def errMsg = {
+ val owner = qual.tpe.typeSymbol
+ val target = qual.tpe.widen
+ def targetKindString = if (owner.isTypeParameterOrSkolem) "type parameter " else ""
+ def nameString = decodeWithKind(name, owner)
+ /** Illuminating some common situations and errors a bit further. */
+ def addendum = {
+ val companion = {
+ if (name.isTermName && owner.isPackageClass) {
+ target.member(name.toTypeName) match {
+ case NoSymbol => ""
+ case sym => "\nNote: %s exists, but it has no companion object.".format(sym)
+ }
+ }
+ else ""
+ }
+ val semicolon = (
+ if (linePrecedes(qual, sel))
+ "\npossible cause: maybe a semicolon is missing before `"+nameString+"'?"
+ else
+ ""
+ )
+ companion + semicolon
+ }
+ withAddendum(qual.pos)(
+ if (name == nme.CONSTRUCTOR) target + " does not have a constructor"
+ else nameString + " is not a member of " + targetKindString + target + addendum
+ )
+ }
+ issueNormalTypeError(sel, errMsg)
+ // the error has to be set for the copied tree, otherwise
+ // the error remains persistent acros multiple compilations
+ // and causes problems
+ //setError(sel)
+ }
+
+ //typedNew
+ def IsAbstractError(tree: Tree, sym: Symbol) = {
+ issueNormalTypeError(tree, sym + " is abstract; cannot be instantiated")
+ setError(tree)
+ }
+
+ def DoesNotConformToSelfTypeError(tree: Tree, sym: Symbol, tpe0: Type) = {
+ issueNormalTypeError(tree, sym + " cannot be instantiated because it does not conform to its self-type " + tpe0)
+ setError(tree)
+ }
+
+ //typedEta
+ def UnderscoreEtaError(tree: Tree) = {
+ issueNormalTypeError(tree, "_ must follow method; cannot follow " + tree.tpe)
+ setError(tree)
+ }
+
+ //typedReturn
+ def ReturnOutsideOfDefError(tree: Tree) = {
+ issueNormalTypeError(tree, "return outside method definition")
+ setError(tree)
+ }
+
+ def ReturnWithoutTypeError(tree: Tree, owner: Symbol) = {
+ issueNormalTypeError(tree, owner + " has return statement; needs result type")
+ setError(tree)
+ }
+
+ //typedBind
+ def VariableInPatternAlternativeError(tree: Tree) = {
+ issueNormalTypeError(tree, "illegal variable in pattern alternative")
+ //setError(tree)
+ }
+
+ //typedCase
+ def StarPositionInPatternError(tree: Tree) =
+ issueNormalTypeError(tree, "_* may only come last")
+
+ //typedFunction
+ def MaxFunctionArityError(fun: Tree) = {
+ issueNormalTypeError(fun, "implementation restricts functions to " + definitions.MaxFunctionArity + " parameters")
+ setError(fun)
+ }
+
+ def WrongNumberOfParametersError(tree: Tree, argpts: List[Type]) = {
+ issueNormalTypeError(tree, "wrong number of parameters; expected = " + argpts.length)
+ setError(tree)
+ }
+
+ def MissingParameterTypeError(fun: Tree, vparam: ValDef, pt: Type) = {
+ def anonMessage = (
+ "\nThe argument types of an anonymous function must be fully known. (SLS 8.5)" +
+ "\nExpected type was: " + pt.toLongString
+ )
+
+ val suffix =
+ if (!vparam.mods.isSynthetic) ""
+ else " for expanded function" + (fun match {
+ case Function(_, Match(_, _)) => anonMessage
+ case _ => " " + fun
+ })
+
+ issueNormalTypeError(vparam, "missing parameter type" + suffix)
+ }
+
+ def ConstructorsOrderError(tree: Tree) = {
+ issueNormalTypeError(tree, "called constructor's definition must precede calling constructor's definition")
+ setError(tree)
+ }
+
+ def OnlyDeclarationsError(tree: Tree) = {
+ issueNormalTypeError(tree, "only declarations allowed here")
+ setError(tree)
+ }
+
+ // typedAnnotation
+ def AnnotationNotAConstantError(tree: Tree) =
+ NormalTypeError(tree, "annotation argument needs to be a constant; found: " + tree)
+
+ def AnnotationArgNullError(tree: Tree) =
+ NormalTypeError(tree, "annotation argument cannot be null")
+
+ def ArrayConstantsError(tree: Tree) =
+ NormalTypeError(tree, "Array constants have to be specified using the `Array(...)' factory method")
+
+ def ArrayConstantsTypeMismatchError(tree: Tree, pt: Type) =
+ NormalTypeError(tree, "found array constant, expected argument of type " + pt)
+
+ def UnexpectedTreeAnnotation(tree: Tree) =
+ NormalTypeError(tree, "unexpected tree in annotation: "+ tree)
+
+ def AnnotationTypeMismatchError(tree: Tree, expected: Type, found: Type) =
+ NormalTypeError(tree, "expected annotation of type " + expected + ", found " + found)
+
+ def MultipleArgumentListForAnnotationError(tree: Tree) =
+ NormalTypeError(tree, "multiple argument lists on classfile annotation")
+
+ def UnknownAnnotationNameError(tree: Tree, name: Name) =
+ NormalTypeError(tree, "unknown annotation argument name: " + name)
+
+ def DuplicateValueAnnotationError(tree: Tree, name: Name) =
+ NormalTypeError(tree, "duplicate value for annotation argument " + name)
+
+ def ClassfileAnnotationsAsNamedArgsError(tree: Tree) =
+ NormalTypeError(tree, "classfile annotation arguments have to be supplied as named arguments")
+
+ def AnnotationMissingArgError(tree: Tree, annType: Type, sym: Symbol) =
+ NormalTypeError(tree, "annotation " + annType.typeSymbol.fullName + " is missing argument " + sym.name)
+
+ def NestedAnnotationError(tree: Tree, annType: Type) =
+ NormalTypeError(tree, "nested classfile annotations must be defined in java; found: "+ annType)
+
+ def UnexpectedTreeAnnotationError(tree: Tree, unexpected: Tree) =
+ NormalTypeError(tree, "unexpected tree after typing annotation: "+ unexpected)
+
+ // TODO no test case
+ //typedExistentialTypeTree
+ def AbstractionFromVolatileTypeError(vd: ValDef) =
+ issueNormalTypeError(vd, "illegal abstraction from value with volatile type "+vd.symbol.tpe)
+
+ def TypedApplyWrongNumberOfTpeParametersError(tree: Tree, fun: Tree) = {
+ issueNormalTypeError(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun))
+ setError(tree)
+ }
+
+ def TypedApplyDoesNotTakeTpeParametersError(tree: Tree, fun: Tree) = {
+ issueNormalTypeError(tree, treeSymTypeMsg(fun)+" does not take type parameters.")
+ setError(tree)
+ }
+
+ // doTypeApply
+ //tryNamesDefaults
+ def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
+
+ def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
+
+ // can it still happen? see test case neg/t960.scala
+ // TODO no test case
+ def OverloadedUnapplyError(tree: Tree) =
+ issueNormalTypeError(tree, "cannot resolve overloaded unapply")
+
+ def UnapplyWithSingleArgError(tree: Tree) =
+ issueNormalTypeError(tree, "an unapply method must accept a single argument.")
+
+ def MultipleVarargError(tree: Tree) =
+ NormalTypeError(tree, "when using named arguments, the vararg parameter has to be specified exactly once")
+
+ def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) =
+ NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments")
+
+ def NotEnoughArgsError(tree: Tree, fun0: Tree, missing0: List[Symbol]) = {
+ def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]) = {
+ val suffix = {
+ if (missing.isEmpty) ""
+ else {
+ val keep = missing take 3 map (_.name)
+ ".\nUnspecified value parameter%s %s".format(
+ if (missing.tail.isEmpty) "" else "s",
+ if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ")
+ else keep.mkString("", ", ", ".")
+ )
+ }
+ }
+
+ "not enough arguments for " + treeSymTypeMsg(fun) + suffix
+ }
+ NormalTypeError(tree, notEnoughArgumentsMsg(fun0, missing0))
+ }
+
+ //doTypedApply - patternMode
+ // TODO: missing test case
+ def TooManyArgsPatternError(fun: Tree) =
+ NormalTypeError(fun, "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity)
+
+ def WrongNumberArgsPatternError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+
+ def ApplyWithoutArgsError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, fun.tpe+" does not take parameters")
+
+ //checkClassType
+ def TypeNotAStablePrefixError(tpt: Tree, pre: Type) = {
+ issueNormalTypeError(tpt, "type "+pre+" is not a stable prefix")
+ setError(tpt)
+ }
+
+ def ClassTypeRequiredError(tree: Tree, found: AnyRef) = {
+ issueNormalTypeError(tree, "class type required but "+found+" found")
+ setError(tree)
+ }
+
+ // validateParentClasses
+ def ParentSuperSubclassError(parent: Tree, superclazz: Symbol,
+ parentSym: Symbol, mixin: Symbol) =
+ NormalTypeError(parent, "illegal inheritance; super"+superclazz+
+ "\n is not a subclass of the super"+parentSym+
+ "\n of the mixin " + mixin)
+
+ def ParentNotATraitMixinError(parent: Tree, mixin: Symbol) =
+ NormalTypeError(parent, mixin+" needs to be a trait to be mixed in")
+
+ def ParentFinalInheritanceError(parent: Tree, mixin: Symbol) =
+ NormalTypeError(parent, "illegal inheritance from final "+mixin)
+
+ def ParentSealedInheritanceError(parent: Tree, psym: Symbol) =
+ NormalTypeError(parent, "illegal inheritance from sealed " + psym + ": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath)
+
+ def ParentSelfTypeConformanceError(parent: Tree, selfType: Type) =
+ NormalTypeError(parent,
+ "illegal inheritance;\n self-type "+selfType+" does not conform to "+
+ parent +"'s selftype "+parent.tpe.typeOfThis)
+
+ // TODO: missing test case
+ def ParentInheritedTwiceError(parent: Tree, parentSym: Symbol) =
+ NormalTypeError(parent, parentSym+" is inherited twice")
+
+ //adapt
+ def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = {
+ issueNormalTypeError(tree,
+ "missing arguments for " + meth.fullLocationString + (
+ if (meth.isConstructor) ""
+ else ";\nfollow this method with `_' if you want to treat it as a partially applied function"
+ ))
+ setError(tree)
+ }
+
+ def MissingTypeParametersError(tree: Tree) = {
+ issueNormalTypeError(tree, tree.symbol+" takes type parameters")
+ setError(tree)
+ }
+
+ def KindArityMismatchError(tree: Tree, pt: Type) = {
+ issueNormalTypeError(tree,
+ tree.tpe+" takes "+countElementsAsString(tree.tpe.typeParams.length, "type parameter")+
+ ", expected: "+countAsString(pt.typeParams.length))
+ setError(tree)
+ }
+
+ def CaseClassConstructorError(tree: Tree) = {
+ issueNormalTypeError(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method")
+ setError(tree)
+ }
+
+ //TODO Needs test case
+ def ConstructorPrefixError(tree: Tree, restpe: Type) = {
+ issueNormalTypeError(tree, restpe.prefix+" is not a legal prefix for a constructor")
+ setError(tree)
+ }
+
+ // SelectFromTypeTree
+ def TypeSelectionFromVolatileTypeError(tree: Tree, qual: Tree) = {
+ issueNormalTypeError(tree, "illegal type selection from volatile type "+qual.tpe)
+ setError(tree)
+ }
+
+ // packedType
+ def InferTypeWithVolatileTypeSelectionError(tree: Tree, pre: Type) =
+ issueNormalTypeError(tree, "Inferred type "+tree.tpe+" contains type selection from volatile type "+pre)
+
+ def AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) =
+ issueNormalTypeError(tree, "can't existentially abstract over parameterized type " + tp)
+
+ //manifestTreee
+ def MissingManifestError(tree: Tree, full: Boolean, tp: Type) = {
+ issueNormalTypeError(tree, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp)
+ setError(tree)
+ }
+
+ // TODO needs test case
+ // cases where we do not necessarily return trees
+ def DependentMethodTpeConversionToFunctionError(tree: Tree, tp: Type) =
+ issueNormalTypeError(tree, "method with dependent type "+tp+" cannot be converted to function value")
+
+ //checkStarPatOK
+ def StarPatternWithVarargParametersError(tree: Tree) =
+ issueNormalTypeError(tree, "star patterns must correspond with varargs parameters")
+
+ // TODO missing test case
+ def FinitaryError(tparam: Symbol) =
+ issueSymbolTypeError(tparam, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive")
+
+ // TODO missing test case for a second case
+ def QualifyingClassError(tree: Tree, qual: Name) = {
+ issueNormalTypeError(tree,
+ if (qual.isEmpty) tree + " can be used only in a class, object, or template"
+ else qual + " is not an enclosing class")
+ setError(tree)
+ }
+
+ // def stabilize
+ def NotAValueError(tree: Tree, sym: Symbol) = {
+ issueNormalTypeError(tree, sym.kindString + " " + sym.fullName + " is not a value")
+ setError(tree)
+ }
+
+ // checkNoDoubleDefs...
+ def DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) =
+ issueSymbolTypeError(sym0, sym1+" is defined twice"+
+ {if(!settings.debug.value) "" else " in "+context0.unit}+
+ {if (sym0.isMacro && sym1.isMacro) " \n(note that macros cannot be overloaded)" else ""})
+
+ // cyclic errors
+ def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) =
+ issueTypeError(PosAndMsgTypeError(errPos, "cyclic aliasing or subtyping involving "+sym0))
+
+ def CyclicReferenceError(errPos: Position, lockedSym: Symbol) =
+ issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym))
+
+ def MacroExpandError(tree: Tree, t: Any) = {
+ issueNormalTypeError(tree, "macros must return a compiler-specific tree; returned class is: " + t.getClass)
+ setError(tree)
+ }
+ }
+ }
+
+ trait InferencerContextErrors {
+ self: Inferencer =>
+
+ private def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = {
+ def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")")
+
+ def resType = if (pt isWildcard) "" else " with expected result type " + pt
+ def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt
+ def locals = alternatives(tree) flatMap (_.typeParams)
+
+ withDisambiguation(locals, allTypes: _*) {
+ treeSymTypeMsg(tree) + msg + asParams(argtpes) + resType
+ }
+ }
+
+ object InferErrorGen {
+
+ implicit val context0 = getContext
+
+ object PolyAlternativeErrorKind extends Enumeration {
+ type ErrorType = Value
+ val WrongNumber, NoParams, ArgsDoNotConform = Value
+ }
+
+ private def ambiguousErrorMsgPos(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) =
+ if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) {
+ val methodName = nme.defaultGetterToMethod(sym1.name)
+ (sym1.enclClass.pos,
+ "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName +
+ " define default arguments")
+ } else {
+ (pos,
+ ("ambiguous reference to overloaded definition,\n" +
+ "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) +
+ "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) +
+ "\nmatch " + rest)
+ )
+ }
+
+ def AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String) = {
+ def errMsg = {
+ val location = if (sym.isClassConstructor) owner0 else pre.widen
+
+ underlying(sym).fullLocationString + " cannot be accessed in " +
+ location + explanation
+ }
+ NormalTypeError(tree, errMsg, ErrorKinds.Access)
+ }
+
+ def NoMethodInstanceError(fn: Tree, args: List[Tree], msg: String) =
+ issueNormalTypeError(fn,
+ "no type parameters for " +
+ applyErrorMsg(fn, " exist so that it can be applied to arguments ", args map (_.tpe.widen), WildcardType) +
+ "\n --- because ---\n" + msg)
+
+ // TODO: no test case
+ def NoConstructorInstanceError(tree: Tree, restpe: Type, pt: Type, msg: String) = {
+ issueNormalTypeError(tree,
+ "constructor of type " + restpe +
+ " cannot be uniquely instantiated to expected type " + pt +
+ "\n --- because ---\n" + msg)
+ setError(tree)
+ }
+
+ def ConstrInstantiationError(tree: Tree, restpe: Type, pt: Type) = {
+ issueNormalTypeError(tree,
+ "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt))
+ setError(tree)
+ }
+
+ def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) =
+ issueNormalTypeError(tree,
+ applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+
+ def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol,
+ firstCompeting: Symbol, argtpes: List[Type], pt: Type) = {
+ val msg0 =
+ "argument types " + argtpes.mkString("(", ",", ")") +
+ (if (pt == WildcardType) "" else " and expected result type " + pt)
+ val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, msg0)
+ issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg))
+ }
+
+ def NoBestExprAlternativeError(tree: Tree, pt: Type) =
+ issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(tree.symbol.tpe, pt, isPossiblyMissingArgs(tree.symbol.tpe, pt))))
+
+ def AmbiguousExprAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, pt: Type) = {
+ val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, "expected type " + pt)
+ setError(tree)
+ issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg))
+ }
+
+ // checkBounds
+ def KindBoundErrors(tree: Tree, prefix: String, targs: List[Type],
+ tparams: List[Symbol], kindErrors: List[String]) = {
+ issueNormalTypeError(tree,
+ prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
+ " do not conform to the expected kinds of the type parameters "+
+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
+ kindErrors.toList.mkString("\n", ", ", ""))
+ }
+
+ def NotWithinBounds(tree: Tree, prefix: String, targs: List[Type],
+ tparams: List[Symbol], kindErrors: List[String]) = {
+ if (settings.explaintypes.value) {
+ val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi))
+ ()
+ }
+
+ issueNormalTypeError(tree,
+ prefix + "type arguments " + targs.mkString("[", ",", "]") +
+ " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
+ (tparams map (_.defString)).mkString("[", ",", "]"))
+ }
+
+ //substExpr
+ def PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) =
+ issueNormalTypeError(tree,
+ "polymorphic expression cannot be instantiated to expected type" +
+ foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt))
+
+ //checkCheckable
+ def TypePatternOrIsInstanceTestError(tree: Tree, tp: Type) =
+ issueNormalTypeError(tree, "type "+tp+" cannot be used in a type pattern or isInstanceOf test")
+
+ def PatternTypeIncompatibleWithPtError1(tree: Tree, pattp: Type, pt: Type) =
+ issueNormalTypeError(tree, "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt))
+
+ def IncompatibleScrutineeTypeError(tree: Tree, pattp: Type, pt: Type) =
+ issueNormalTypeError(tree, "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt))
+
+ def PatternTypeIncompatibleWithPtError2(pat: Tree, pt1: Type, pt: Type) = {
+ def errMsg = {
+ val sym = pat.tpe.typeSymbol
+ val clazz = sym.companionClass
+ val addendum = (
+ if (sym.isModuleClass && clazz.isCaseClass && (clazz isSubClass pt1.typeSymbol)) {
+ // TODO: move these somewhere reusable.
+ val typeString = clazz.typeParams match {
+ case Nil => "" + clazz.name
+ case xs => xs map (_ => "_") mkString (clazz.name + "[", ",", "]")
+ }
+ val caseString = (
+ clazz.caseFieldAccessors
+ map (_ => "_") // could use the actual param names here
+ mkString (clazz.name + "(", ",", ")")
+ )
+ (
+ "\nNote: if you intended to match against the class, try `case _: " +
+ typeString + "` or `case " + caseString + "`"
+ )
+ }
+ else ""
+ )
+ "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt) + addendum
+ }
+ issueNormalTypeError(pat, errMsg)
+ }
+
+ def PolyAlternativeError(tree: Tree, argtypes: List[Type], sym: Symbol, err: PolyAlternativeErrorKind.ErrorType) = {
+ import PolyAlternativeErrorKind._
+ val msg =
+ err match {
+ case WrongNumber =>
+ "wrong number of type parameters for " + treeSymTypeMsg(tree)
+ case NoParams =>
+ treeSymTypeMsg(tree) + " does not take type parameters"
+ case ArgsDoNotConform =>
+ "type arguments " + argtypes.mkString("[", ",", "]") +
+ " conform to the bounds of none of the overloaded alternatives of\n "+sym+
+ ": "+sym.info
+ }
+ issueNormalTypeError(tree, msg)
+ ()
+ }
+ }
+ }
+
+ trait NamerContextErrors {
+ self: Namer =>
+
+ object NamerErrorGen {
+
+ implicit val context0 = context
+
+ object SymValidateErrors extends Enumeration {
+ val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject,
+ OverrideClass, SealedNonClass, AbstractNonClass,
+ OverrideConstr, AbstractOverride, LazyAndEarlyInit,
+ ByNameParameter, AbstractVar = Value
+ }
+
+ object DuplicatesErrorKinds extends Enumeration {
+ val RenamedTwice, AppearsTwice = Value
+ }
+
+ import SymValidateErrors._
+ import DuplicatesErrorKinds._
+ import symtab.Flags
+
+ def TypeSigError(tree: Tree, ex: TypeError) = {
+ ex match {
+ case CyclicReference(sym, info: TypeCompleter) =>
+ issueNormalTypeError(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
+ case _ =>
+ context0.issue(TypeErrorWithUnderlyingTree(tree, ex))
+ }
+ }
+
+ def GetterDefinedTwiceError(getter: Symbol) =
+ issueSymbolTypeError(getter, getter+" is defined twice")
+
+ def ValOrValWithSetterSuffixError(tree: Tree) =
+ issueNormalTypeError(tree, "Names of vals or vars may not end in `_='")
+
+ def PrivateThisCaseClassParameterError(tree: Tree) =
+ issueNormalTypeError(tree, "private[this] not allowed for case class parameters")
+
+ def BeanPropertyAnnotationLimitationError(tree: Tree) =
+ issueNormalTypeError(tree, "implementation limitation: the BeanProperty annotation cannot be used in a type alias or renamed import")
+
+ def BeanPropertyAnnotationFieldWithoutLetterError(tree: Tree) =
+ issueNormalTypeError(tree, "`BeanProperty' annotation can be applied only to fields that start with a letter")
+
+ def BeanPropertyAnnotationPrivateFieldError(tree: Tree) =
+ issueNormalTypeError(tree, "`BeanProperty' annotation can be applied only to non-private fields")
+
+ def DoubleDefError(currentSym: Symbol, prevSym: Symbol) = {
+ val s1 = if (prevSym.isModule) "case class companion " else ""
+ val s2 = if (prevSym.isSynthetic) "(compiler-generated) " + s1 else ""
+ val s3 = if (prevSym.isCase) "case class " + prevSym.name else "" + prevSym
+
+ issueSymbolTypeError(currentSym, prevSym.name + " is already defined as " + s2 + s3)
+ }
+
+ def MaxParametersCaseClassError(tree: Tree) =
+ issueNormalTypeError(tree, "Implementation restriction: case classes cannot have more than " + definitions.MaxFunctionArity + " parameters.")
+
+ def InheritsItselfError(tree: Tree) =
+ issueNormalTypeError(tree, tree.tpe.typeSymbol+" inherits itself")
+
+ def MissingParameterOrValTypeError(vparam: Tree) =
+ issueNormalTypeError(vparam, "missing parameter type")
+
+ def RootImportError(tree: Tree) =
+ issueNormalTypeError(tree, "_root_ cannot be imported")
+
+ def SymbolValidationError(sym: Symbol, errKind: SymValidateErrors.Value) {
+ val msg = errKind match {
+ case ImplicitConstr =>
+ "`implicit' modifier not allowed for constructors"
+
+ case ImplicitNotTerm =>
+ "`implicit' modifier can be used only for values, variables and methods"
+
+ case ImplicitTopObject =>
+ "`implicit' modifier cannot be used for top-level objects"
+
+ case OverrideClass =>
+ "`override' modifier not allowed for classes"
+
+ case SealedNonClass =>
+ "`sealed' modifier can be used only for classes"
+
+ case AbstractNonClass =>
+ "`abstract' modifier can be used only for classes; it should be omitted for abstract members"
+
+ case OverrideConstr =>
+ "`override' modifier not allowed for constructors"
+
+ case AbstractOverride =>
+ "`abstract override' modifier only allowed for members of traits"
+
+ case LazyAndEarlyInit =>
+ "`lazy' definitions may not be initialized early"
+
+ case ByNameParameter =>
+ "pass-by-name arguments not allowed for case class parameters"
+
+ case AbstractVar =>
+ "only classes can have declared but undefined members" + abstractVarMessage(sym)
+
+ }
+ issueSymbolTypeError(sym, msg)
+ }
+
+
+ def AbstractMemberWithModiferError(sym: Symbol, flag: Int) =
+ issueSymbolTypeError(sym, "abstract member may not have " + Flags.flagsToString(flag) + " modifier")
+
+ def IllegalModifierCombination(sym: Symbol, flag1: Int, flag2: Int) =
+ issueSymbolTypeError(sym, "illegal combination of modifiers: %s and %s for: %s".format(
+ Flags.flagsToString(flag1), Flags.flagsToString(flag2), sym))
+
+ def IllegalDependentMethTpeError(sym: Symbol)(context: Context) = {
+ val errorAddendum =
+ ": parameter appears in the type of another parameter in the same section or an earlier one"
+ issueSymbolTypeError(sym, "illegal dependent method type" + errorAddendum)(context)
+ }
+
+ def DuplicatesError(tree: Tree, name: Name, kind: DuplicatesErrorKinds.Value) = {
+ val msg = kind match {
+ case RenamedTwice =>
+ "is renamed twice"
+ case AppearsTwice =>
+ "appears twice as a target of a renaming"
+ }
+
+ issueNormalTypeError(tree, name.decode + " " + msg)
+ }
+ }
+ }
+
+ trait ImplicitsContextErrors {
+ self: ImplicitSearch =>
+
+ import definitions._
+
+ def AmbiguousImplicitError(info1: ImplicitInfo, info2: ImplicitInfo,
+ pre1: String, pre2: String, trailer: String)
+ (isView: Boolean, pt: Type, tree: Tree)(implicit context0: Context) = {
+ if (!info1.tpe.isErroneous && !info2.tpe.isErroneous) {
+ val coreMsg =
+ pre1+" "+info1.sym.fullLocationString+" of type "+info1.tpe+"\n "+
+ pre2+" "+info2.sym.fullLocationString+" of type "+info2.tpe+"\n "+
+ trailer
+ val errMsg =
+ if (isView) {
+ val found = pt.typeArgs(0)
+ val req = pt.typeArgs(1)
+ def defaultExplanation =
+ "Note that implicit conversions are not applicable because they are ambiguous:\n "+
+ coreMsg+"are possible conversion functions from "+ found+" to "+req
+
+ def explanation = {
+ val sym = found.typeSymbol
+ // Explain some common situations a bit more clearly.
+ if (AnyRefClass.tpe <:< req) {
+ if (sym == AnyClass || sym == UnitClass) {
+ "Note: " + sym.name + " is not implicitly converted to AnyRef. You can safely\n" +
+ "pattern match `x: AnyRef` or cast `x.asInstanceOf[AnyRef]` to do so."
+ }
+ else boxedClass get sym match {
+ case Some(boxed) =>
+ "Note: an implicit exists from " + sym.fullName + " => " + boxed.fullName + ", but\n" +
+ "methods inherited from Object are rendered ambiguous. This is to avoid\n" +
+ "a blanket implicit which would convert any " + sym.fullName + " to any AnyRef.\n" +
+ "You may wish to use a type ascription: `x: " + boxed.fullName + "`."
+ case _ =>
+ defaultExplanation
+ }
+ }
+ else defaultExplanation
+ }
+
+ typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req)) + "\n" + explanation
+ } else {
+ "ambiguous implicit values:\n "+coreMsg + "match expected type "+pt
+ }
+ context.issueAmbiguousError(AmbiguousTypeError(tree, tree.pos, errMsg))
+ }
+ }
+
+ def DivergingImplicitExpansionError(tree: Tree, pt: Type, sym: Symbol)(implicit context0: Context) =
+ issueDivergentImplicitsError(tree,
+ "diverging implicit expansion for type "+pt+"\nstarting with "+
+ sym.fullLocationString)
+ }
+
+ object NamesDefaultsErrorsGen {
+ import typer.infer.setError
+
+ def NameClashError(sym: Symbol, arg: Tree)(implicit context: Context) = {
+ setError(arg) // to distinguish it from ambiguous reference error
+
+ def errMsg =
+ "%s definition needs %s because '%s' is used as a named argument in its body.".format(
+ "variable", // "method"
+ "type", // "result type"
+ sym.name)
+ issueSymbolTypeError(sym, errMsg)
+ }
+
+ def AmbiguousReferenceInNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = {
+ if (!arg.isErroneous) { // check if name clash wasn't reported already
+ issueNormalTypeError(arg,
+ "reference to "+ name +" is ambiguous; it is both a method parameter "+
+ "and a variable in scope.")
+ setError(arg)
+ } else arg
+ }
+
+ def UnknownParameterNameNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = {
+ issueNormalTypeError(arg, "unknown parameter name: " + name)
+ setError(arg)
+ }
+
+ def DoubleParamNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = {
+ issueNormalTypeError(arg, "parameter specified twice: "+ name)
+ setError(arg)
+ }
+
+ def PositionalAfterNamedNamesDefaultError(arg: Tree)(implicit context: Context) = {
+ issueNormalTypeError(arg, "positional after named argument.")
+ setError(arg)
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index faff4ccab2..740acbd10f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -7,7 +7,7 @@ package scala.tools.nsc
package typechecker
import symtab.Flags._
-import scala.collection.mutable.ListBuffer
+import scala.collection.mutable.{LinkedHashSet, Set}
import annotation.tailrec
/**
@@ -66,8 +66,7 @@ trait Contexts { self: Analyzer =>
sc.depth += 1
}
val c = sc.make(unit, tree, sc.owner, sc.scope, sc.imports)
- c.reportAmbiguousErrors = !erasedTypes
- c.reportGeneralErrors = !erasedTypes
+ if (erasedTypes) c.setThrowErrors() else c.setReportErrors()
c.implicitsEnabled = !erasedTypes
c
}
@@ -83,7 +82,17 @@ trait Contexts { self: Analyzer =>
}
}
+ private object Errors {
+ final val ReportErrors = 1 << 0
+ final val BufferErrors = 1 << 1
+ final val AmbiguousErrors = 1 << 2
+ final val notThrowMask = ReportErrors | BufferErrors
+ final val AllMask = ReportErrors | BufferErrors | AmbiguousErrors
+ }
+
class Context private[typechecker] {
+ import Errors._
+
var unit: CompilationUnit = NoCompilationUnit
var tree: Tree = _ // Tree associated with this context
var owner: Symbol = NoSymbol // The current owner
@@ -109,8 +118,6 @@ trait Contexts { self: Analyzer =>
// (the call to the super or self constructor in the first line of a constructor)
// in this context the object's fields should not be in scope
- var reportAmbiguousErrors = false
- var reportGeneralErrors = false
var diagnostic: List[String] = Nil // these messages are printed when issuing an error
var implicitsEnabled = false
var checking = false
@@ -138,12 +145,41 @@ trait Contexts { self: Analyzer =>
tparams
}
- def withoutReportingErrors[T](op: => T): T = {
- val saved = reportGeneralErrors
- reportGeneralErrors = false
- try op
- finally reportGeneralErrors = saved
+ private[this] var mode = 0
+ private[this] val buffer = LinkedHashSet[AbsTypeError]()
+
+ def errBuffer = buffer
+ def hasErrors = buffer.nonEmpty
+
+ def state: Int = mode
+ def restoreState(state0: Int) = mode = state0
+
+ def reportErrors = (state & ReportErrors) != 0
+ def bufferErrors = (state & BufferErrors) != 0
+ def ambiguousErrors = (state & AmbiguousErrors) != 0
+ def throwErrors = (state & notThrowMask) == 0
+
+ def setReportErrors() = mode = (ReportErrors | AmbiguousErrors)
+ def setBufferErrors() = {
+ assert(bufferErrors || !hasErrors, "When entering the buffer state, context has to be clean. Current buffer: " + buffer)
+ mode = BufferErrors
+ }
+ def setThrowErrors() = mode &= (~AllMask)
+ def setAmbiguousErrors(report: Boolean) = if (report) mode |= AmbiguousErrors else mode &= notThrowMask
+
+ def updateBuffer(errors: Set[AbsTypeError]) = buffer ++= errors
+ def condBufferFlush(removeP: AbsTypeError => Boolean) {
+ val elems = buffer.filter(removeP)
+ buffer --= elems
}
+ def flushBuffer() { buffer.clear() }
+ def flushAndReturnBuffer(): Set[AbsTypeError] = {
+ val current = buffer.clone()
+ buffer.clear()
+ current
+ }
+
+ def logError(err: AbsTypeError) = buffer += err
def withImplicitsDisabled[T](op: => T): T = {
val saved = implicitsEnabled
@@ -183,8 +219,7 @@ trait Contexts { self: Analyzer =>
c.depth = if (scope == this.scope) this.depth else this.depth + 1
c.imports = imports
c.inSelfSuperCall = inSelfSuperCall
- c.reportAmbiguousErrors = this.reportAmbiguousErrors
- c.reportGeneralErrors = this.reportGeneralErrors
+ c.restoreState(this.state)
c.diagnostic = this.diagnostic
c.typingIndentLevel = typingIndentLevel
c.implicitsEnabled = this.implicitsEnabled
@@ -196,10 +231,10 @@ trait Contexts { self: Analyzer =>
c
}
+ // TODO: remove? Doesn't seem to be used
def make(unit: CompilationUnit): Context = {
val c = make(unit, EmptyTree, owner, scope, imports)
- c.reportAmbiguousErrors = true
- c.reportGeneralErrors = true
+ c.setReportErrors()
c.implicitsEnabled = true
c
}
@@ -218,7 +253,7 @@ trait Contexts { self: Analyzer =>
make(unit, tree, owner, scope, imports)
def makeNewScope(tree: Tree, owner: Symbol): Context =
- make(tree, owner, new Scope(scope))
+ make(tree, owner, newNestedScope(scope))
// IDE stuff: distinguish between scopes created for typing and scopes created for naming.
def make(tree: Tree, owner: Symbol): Context =
@@ -229,8 +264,8 @@ trait Contexts { self: Analyzer =>
def makeSilent(reportAmbiguousErrors: Boolean, newtree: Tree = tree): Context = {
val c = make(newtree)
- c.reportGeneralErrors = false
- c.reportAmbiguousErrors = reportAmbiguousErrors
+ c.setBufferErrors()
+ c.setAmbiguousErrors(reportAmbiguousErrors)
c
}
@@ -242,13 +277,11 @@ trait Contexts { self: Analyzer =>
def makeConstructorContext = {
var baseContext = enclClass.outer
- //todo: find out why we need next line
while (baseContext.tree.isInstanceOf[Template])
baseContext = baseContext.outer
val argContext = baseContext.makeNewScope(tree, owner)
argContext.inSelfSuperCall = true
- argContext.reportGeneralErrors = this.reportGeneralErrors
- argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
+ argContext.restoreState(this.state)
def enterElems(c: Context) {
def enterLocalElems(e: ScopeEntry) {
if (e != null && e.owner == c.scope) {
@@ -275,41 +308,41 @@ trait Contexts { self: Analyzer =>
private def unitError(pos: Position, msg: String) =
unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
+ def issue(err: AbsTypeError) {
+ if (reportErrors) unitError(err.errPos, addDiagString(err.errMsg))
+ else if (bufferErrors) { buffer += err }
+ else throw new TypeError(err.errPos, err.errMsg)
+ }
+
+ def issueAmbiguousError(pre: Type, sym1: Symbol, sym2: Symbol, err: AbsTypeError) {
+ if (ambiguousErrors) {
+ if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous)
+ unitError(err.errPos, err.errMsg)
+ } else if (bufferErrors) { buffer += err }
+ else throw new TypeError(err.errPos, err.errMsg)
+ }
+
+ def issueAmbiguousError(err: AbsTypeError) {
+ if (ambiguousErrors)
+ unitError(err.errPos, addDiagString(err.errMsg))
+ else if (bufferErrors) { buffer += err }
+ else throw new TypeError(err.errPos, err.errMsg)
+ }
+
+ // TODO remove
def error(pos: Position, err: Throwable) =
- if (reportGeneralErrors) unitError(pos, addDiagString(err.getMessage()))
+ if (reportErrors) unitError(pos, addDiagString(err.getMessage()))
else throw err
def error(pos: Position, msg: String) = {
val msg1 = addDiagString(msg)
- if (reportGeneralErrors) unitError(pos, msg1)
+ if (reportErrors) unitError(pos, msg1)
else throw new TypeError(pos, msg1)
}
- def warning(pos: Position, msg: String) = {
- if (reportGeneralErrors) unit.warning(pos, msg)
- }
-
- def ambiguousError(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) {
- val (reportPos, msg) = (
- if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) {
- val methodName = nme.defaultGetterToMethod(sym1.name)
- (sym1.enclClass.pos,
- "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName +
- " define default arguments")
- }
- else {
- (pos,
- ("ambiguous reference to overloaded definition,\n" +
- "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) +
- "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) +
- "\nmatch " + rest)
- )
- }
- )
- if (reportAmbiguousErrors) {
- if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous)
- unit.error(reportPos, msg)
- } else throw new TypeError(pos, msg)
+ def warning(pos: Position, msg: String): Unit = warning(pos, msg, false)
+ def warning(pos: Position, msg: String, force: Boolean) {
+ if (reportErrors || force) unit.warning(pos, msg)
}
def isLocal(): Boolean = tree match {
@@ -343,8 +376,8 @@ trait Contexts { self: Analyzer =>
def enclosingContextChain: List[Context] = this :: outer.enclosingContextChain
- override def toString = "Context(%s@%s unit=%s scope=%s)".format(
- owner.fullName, tree.shortClass, unit, scope.##
+ override def toString = "Context(%s@%s unit=%s scope=%s errors=%b)".format(
+ owner.fullName, tree.shortClass, unit, scope.##, hasErrors
)
/** Is `sub` a subclass of `base` or a companion object of such a subclass?
*/
@@ -552,7 +585,7 @@ trait Contexts { self: Analyzer =>
debuglog("collect local implicits " + scope.toList)//DEBUG
collectImplicits(scope.toList, NoPrefix)
} else if (imports != nextOuter.imports) {
- assert(imports.tail == nextOuter.imports)
+ assert(imports.tail == nextOuter.imports, (imports, nextOuter.imports))
collectImplicitImports(imports.head)
} else if (owner.isPackageClass) {
// the corresponding package object may contain implicit members.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 53e88b33c8..eaf1b1ffbc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -31,20 +31,26 @@ trait Implicits {
import typeDebug.{ ptTree, ptBlock, ptLine }
import global.typer.{ printTyping, deindentTyping, indentTyping, printInference }
+ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult =
+ inferImplicit(tree, pt, reportAmbiguous, isView, context, true)
+
/** Search for an implicit value. See the comment on `result` at the end of class `ImplicitSearch`
* for more info how the search is conducted.
- * @param tree The tree for which the implicit needs to be inserted.
- * (the inference might instantiate some of the undetermined
- * type parameters of that tree.
- * @param pt The expected type of the implicit.
- * @param reportAmbiguous Should ambiguous implicit errors be reported?
- * False iff we search for a view to find out
- * whether one type is coercible to another.
- * @param isView We are looking for a view
- * @param context The current context
- * @return A search result
+ * @param tree The tree for which the implicit needs to be inserted.
+ * (the inference might instantiate some of the undetermined
+ * type parameters of that tree.
+ * @param pt The expected type of the implicit.
+ * @param reportAmbiguous Should ambiguous implicit errors be reported?
+ * False iff we search for a view to find out
+ * whether one type is coercible to another.
+ * @param isView We are looking for a view
+ * @param context The current context
+ * @param saveAmbiguousDivergent False if any divergent/ambiguous errors should be ignored after
+ * implicits search,
+ * true if they should be reported (used in further typechecking).
+ * @return A search result
*/
- def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = {
+ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean): SearchResult = {
printInference("[infer %s] %s with pt=%s in %s".format(
if (isView) "view" else "implicit",
tree, pt, context.owner.enclClass)
@@ -64,8 +70,10 @@ trait Implicits {
val start = startTimer(implicitNanos)
if (printInfers && !tree.isEmpty && !context.undetparams.isEmpty)
printTyping("typing implicit: %s %s".format(tree, context.undetparamsString))
-
- val result = new ImplicitSearch(tree, pt, isView, context.makeImplicit(reportAmbiguous)).bestImplicit
+ val implicitSearchContext = context.makeImplicit(reportAmbiguous)
+ val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext).bestImplicit
+ if (saveAmbiguousDivergent && implicitSearchContext.hasErrors)
+ context.updateBuffer(implicitSearchContext.errBuffer.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent))
printInference("[infer implicit] inferred " + result)
context.undetparams = context.undetparams filterNot result.subst.from.contains
@@ -94,21 +102,13 @@ trait Implicits {
private val ManifestSymbols = Set(PartialManifestClass, FullManifestClass, OptManifestClass)
- /** Map all type params in given list to WildcardType
- * @param tparams The list of type parameters to map
- * @param tp The type in which to do the mapping
- */
- private def tparamsToWildcards(tparams: List[Symbol], tp: Type) =
- if (tparams.isEmpty) tp
- else tp.instantiateTypeParams(tparams, tparams map (_ => WildcardType))
-
/* Map a polytype to one in which all type parameters and argument-dependent types are replaced by wildcards.
* Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate DebruijnIndex types
* when checking whether `b` is a valid implicit, as we haven't even searched a value for the implicit arg `x`,
* so we have to approximate (otherwise it is excluded a priori).
*/
private def depoly(tp: Type): Type = tp match {
- case PolyType(tparams, restpe) => tparamsToWildcards(tparams, ApproximateDependentMap(restpe))
+ case PolyType(tparams, restpe) => deriveTypeWithWildcards(tparams)(ApproximateDependentMap(restpe))
case _ => ApproximateDependentMap(tp)
}
@@ -213,7 +213,7 @@ trait Implicits {
/** An extractor for types of the form ? { name: (? >: argtpe <: Any*)restp }
*/
object HasMethodMatching {
- val dummyMethod = new TermSymbol(NoSymbol, NoPosition, newTermName("typer$dummy"))
+ val dummyMethod = NoSymbol.newTermSymbol(newTermName("typer$dummy"))
def templateArgType(argtpe: Type) = new BoundedWildcardType(TypeBounds.lower(argtpe))
def apply(name: Name, argtpes: List[Type], restpe: Type): Type = {
@@ -252,7 +252,8 @@ trait Implicits {
* @param isView We are looking for a view
* @param context0 The context used for the implicit search
*/
- class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context) extends Typer(context0) {
+ class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context)
+ extends Typer(context0) with ImplicitsContextErrors {
printTyping(
ptBlock("new ImplicitSearch",
"tree" -> tree,
@@ -335,50 +336,6 @@ trait Implicits {
incCounter(implicitSearchCount)
- /** Issues an error signalling ambiguous implicits */
- private def ambiguousImplicitError(info1: ImplicitInfo, info2: ImplicitInfo,
- pre1: String, pre2: String, trailer: String) =
- if (!info1.tpe.isErroneous && !info2.tpe.isErroneous) {
- val coreMsg =
- pre1+" "+info1.sym.fullLocationString+" of type "+info1.tpe+"\n "+
- pre2+" "+info2.sym.fullLocationString+" of type "+info2.tpe+"\n "+
- trailer
- error(tree.pos,
- if (isView) {
- val found = pt.typeArgs(0)
- val req = pt.typeArgs(1)
- def defaultExplanation =
- "Note that implicit conversions are not applicable because they are ambiguous:\n "+
- coreMsg+"are possible conversion functions from "+ found+" to "+req
-
- def explanation = {
- val sym = found.typeSymbol
- // Explain some common situations a bit more clearly.
- if (AnyRefClass.tpe <:< req) {
- if (sym == AnyClass || sym == UnitClass) {
- "Note: " + sym.name + " is not implicitly converted to AnyRef. You can safely\n" +
- "pattern match `x: AnyRef` or cast `x.asInstanceOf[AnyRef]` to do so."
- }
- else boxedClass get sym match {
- case Some(boxed) =>
- "Note: an implicit exists from " + sym.fullName + " => " + boxed.fullName + ", but\n" +
- "methods inherited from Object are rendered ambiguous. This is to avoid\n" +
- "a blanket implicit which would convert any " + sym.fullName + " to any AnyRef.\n" +
- "You may wish to use a type ascription: `x: " + boxed.fullName + "`."
- case _ =>
- defaultExplanation
- }
- }
- else defaultExplanation
- }
-
- typeErrorMsg(found, req) + "\n" + explanation
- }
- else {
- "ambiguous implicit values:\n "+coreMsg + "match expected type "+pt
- })
- }
-
/** The type parameters to instantiate */
val undetParams = if (isView) List() else context.outer.undetparams
@@ -408,9 +365,7 @@ trait Implicits {
// println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG
if (context.openImplicits.tail.isEmpty) {
if (!(pt.isErroneous))
- context.unit.error(
- tree.pos, "diverging implicit expansion for type "+pt+"\nstarting with "+
- info.sym.fullLocationString)
+ DivergingImplicitExpansionError(tree, pt, info.sym)(context)
SearchFailure
} else {
throw DivergentImplicit
@@ -586,6 +541,9 @@ trait Implicits {
else
typed1(itree, EXPRmode, wildPt)
+ if (context.hasErrors)
+ return fail("typed implicit %s has errors".format(info.sym.fullLocationString))
+
incCounter(typedImplicits)
printTyping("typed implicit %s:%s, pt=%s".format(itree1, itree1.tpe, wildPt))
@@ -605,8 +563,8 @@ trait Implicits {
}
}
- if (itree2.tpe.isError)
- SearchFailure
+ if (context.hasErrors)
+ fail("hasMatchingSymbol reported threw error(s)")
else if (!hasMatchingSymbol(itree1))
fail("candidate implicit %s is shadowed by other implicit %s".format(
info.sym.fullLocationString, itree1.symbol.fullLocationString))
@@ -628,7 +586,9 @@ trait Implicits {
false, lubDepth(List(itree2.tpe, pt)))
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
- checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
+ checkBounds(itree2, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
+ if (context.hasErrors)
+ return fail("type parameters weren't correctly instantiated outside of the implicit tree")
// filter out failures from type inference, don't want to remove them from undetParams!
// we must be conservative in leaving type params in undetparams
@@ -654,21 +614,29 @@ trait Implicits {
// re-typecheck)
// TODO: the return tree is ignored. This seems to make
// no difference, but it's bad practice regardless.
- itree2 match {
+
+
+ val checked = itree2 match {
case TypeApply(fun, args) => typedTypeApply(itree2, EXPRmode, fun, args)
case Apply(TypeApply(fun, args), _) => typedTypeApply(itree2, EXPRmode, fun, args) // t2421c
case t => t
}
- val result = new SearchResult(itree2, subst)
- incCounter(foundImplicits)
- printInference("[success] found %s for pt %s".format(result, ptInstantiated))
- result
+
+ if (context.hasErrors)
+ fail("typing TypeApply reported errors for the implicit tree")
+ else {
+ val result = new SearchResult(checked, subst)
+ incCounter(foundImplicits)
+ printInference("[success] found %s for pt %s".format(result, ptInstantiated))
+ result
+ }
}
else fail("incompatible: %s does not match expected type %s".format(itree2.tpe, ptInstantiated))
}
}
catch {
- case ex: TypeError => fail(ex.getMessage())
+ case ex: TypeError =>
+ fail(ex.getMessage())
}
}
@@ -802,7 +770,11 @@ trait Implicits {
catch divergenceHandler
tryImplicitInfo(i) match {
- case SearchFailure => rankImplicits(is, acc)
+ case SearchFailure =>
+ // We don't want errors that occur during checking implicit info
+ // to influence the check of further infos.
+ context.condBufferFlush(_.kind != ErrorKinds.Divergent)
+ rankImplicits(is, acc)
case newBest =>
best = newBest
val newPending = undoLog undo {
@@ -837,7 +809,8 @@ trait Implicits {
case chosen :: rest =>
rest find (alt => !improves(chosen, alt)) match {
case Some(competing) =>
- ambiguousImplicitError(chosen, competing, "both", "and", "")
+ AmbiguousImplicitError(chosen, competing, "both", "and", "")(isView, pt, tree)(context)
+ return SearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala
case _ =>
if (isView) chosen.useCountView += 1
else chosen.useCountArg += 1
@@ -1238,12 +1211,14 @@ trait Implicits {
incCounter(inscopeImplicitHits)
}
if (result == SearchFailure) {
+ val previousErrs = context.flushAndReturnBuffer()
val failstart = startTimer(oftypeFailNanos)
val succstart = startTimer(oftypeSucceedNanos)
result = implicitManifestOrOfExpectedType(pt)
if (result == SearchFailure) {
+ context.updateBuffer(previousErrs)
stopTimer(oftypeFailNanos, failstart)
} else {
stopTimer(oftypeSucceedNanos, succstart)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index b1612f24ef..eac657da19 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -191,12 +191,14 @@ trait Infer {
private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)
/** The context-dependent inferencer part */
- class Inferencer(context: Context) {
+ class Inferencer(context: Context) extends InferencerContextErrors {
+ import InferErrorGen._
+
/* -- Error Messages --------------------------------------------------- */
def setError[T <: Tree](tree: T): T = {
def name = newTermName("<error: " + tree.symbol + ">")
- def errorClass = if (context.reportGeneralErrors) context.owner.newErrorClass(name.toTypeName) else stdErrorClass
- def errorValue = if (context.reportGeneralErrors) context.owner.newErrorValue(name) else stdErrorValue
+ def errorClass = if (context.reportErrors) context.owner.newErrorClass(name.toTypeName) else stdErrorClass
+ def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue
def errorSym = if (tree.isType) errorClass else errorValue
if (tree.hasSymbol)
@@ -205,59 +207,12 @@ trait Infer {
tree setType ErrorType
}
- def error(pos: Position, msg: String) {
- context.error(pos, msg)
- }
-
- def errorTree(tree: Tree, msg: String): Tree = {
- if (!tree.isErroneous) error(tree.pos, msg)
- setError(tree)
- }
-
- def typeError(pos: Position, found: Type, req: Type) {
- if (!found.isErroneous && !req.isErroneous) {
- error(pos, withAddendum(pos)(typeErrorMsg(found, req)))
-
- if (settings.explaintypes.value)
- explainTypes(found, req)
- }
- }
-
- def typeErrorMsg(found: Type, req: Type) = {
- def isPossiblyMissingArgs = (found.resultApprox ne found) && isWeaklyCompatible(found.resultApprox, req)
- def missingArgsMsg = if (isPossiblyMissingArgs) "\n possible cause: missing arguments for method or constructor" else ""
-
- "type mismatch" + foundReqMsg(found, req) + missingArgsMsg
- }
-
- def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = {
- // If the expected type is a refinement type, and the found type is a refinement or an anon
- // class, we can greatly improve the error message by retyping the tree to recover the actual
- // members present, then display along with the expected members. This is done here because
- // this is the last point where we still have access to the original tree, rather than just
- // the found/req types.
- val foundType: Type = req.normalize match {
- case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass =>
- val retyped = typer typed (tree.duplicate setType null)
- val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
-
- if (foundDecls.isEmpty) found
- else {
- // The members arrive marked private, presumably because there was no
- // expected type and so they're considered members of an anon class.
- foundDecls foreach (_ resetFlag (PRIVATE | PROTECTED))
- // TODO: if any of the found parents match up with required parents after normalization,
- // print the error so that they match. The major beneficiary there would be
- // java.lang.Object vs. AnyRef.
- refinedType(found.parents, found.typeSymbol.owner, foundDecls, tree.pos)
- }
- case _ =>
- found
- }
- typeError(tree.pos, foundType, req)
- setError(tree)
- }
+ def getContext = context
+ def issue(err: AbsTypeError): Unit = context.issue(err)
+
+ def isPossiblyMissingArgs(found: Type, req: Type) = (found.resultApprox ne found) && isWeaklyCompatible(found.resultApprox, req)
+
def explainTypes(tp1: Type, tp2: Type) =
withDisambiguation(List(), tp1, tp2)(global.explainTypes(tp1, tp2))
@@ -279,7 +234,6 @@ trait Infer {
var sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
// Console.println("check acc " + (sym, sym1) + ":" + (sym.tpe, sym1.tpe) + " from " + pre);//DEBUG
-
if (sym1 == NoSymbol && sym.isJavaDefined && context.unit.isJava) // don't try to second guess Java; see #4402
sym1 = sym
@@ -289,7 +243,7 @@ trait Infer {
Console.println(tree)
Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
}
- new AccessError(tree, sym, pre,
+ ErrorUtils.issueTypeError(AccessError(tree, sym, pre, context.enclClass.owner,
if (settings.check.isDefault)
analyzer.lastAccessCheckDetails
else
@@ -303,7 +257,8 @@ trait Infer {
"context.owner" -> context.owner,
"context.outer.enclClass.owner" -> context.outer.enclClass.owner
)
- )
+ ))(context)
+ setError(tree)
}
else {
if (sym1.isTerm)
@@ -316,10 +271,11 @@ trait Infer {
if (settings.debug.value) ex.printStackTrace
val sym2 = underlyingSymbol(sym1)
val itype = pre.memberType(sym2)
- new AccessError(tree, sym, pre,
- "\n because its instance type "+itype+
- (if ("malformed type: "+itype.toString==ex.msg) " is malformed"
- else " contains a "+ex.msg)).emit()
+ ErrorUtils.issueTypeError(
+ AccessError(tree, sym, pre, context.enclClass.owner,
+ "\n because its instance type "+itype+
+ (if ("malformed type: "+itype.toString==ex.msg) " is malformed"
+ else " contains a "+ex.msg)))(context)
ErrorType
}
}
@@ -762,25 +718,20 @@ trait Infer {
false
}
- /** Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
+ /**
+ * Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
+ * The chance of TypeErrors should be reduced through context errors
*/
private[typechecker] def isApplicableSafe(undetparams: List[Symbol], ftpe: Type,
argtpes0: List[Type], pt: Type): Boolean = {
- val reportAmbiguousErrors = context.reportAmbiguousErrors
- context.reportAmbiguousErrors = false
- try {
- isApplicable(undetparams, ftpe, argtpes0, pt)
- } catch {
- case ex: TypeError =>
- try {
- isApplicable(undetparams, ftpe, argtpes0, WildcardType)
- } catch {
- case ex: TypeError =>
- false
- }
- } finally {
- context.reportAmbiguousErrors = reportAmbiguousErrors
- }
+ val silentContext = context.makeSilent(false)
+ val typer0 = newTyper(silentContext)
+ val res1 = typer0.infer.isApplicable(undetparams, ftpe, argtpes0, pt)
+ if (pt != WildcardType && silentContext.hasErrors) {
+ silentContext.flushBuffer()
+ val res2 = typer0.infer.isApplicable(undetparams, ftpe, argtpes0, WildcardType)
+ if (silentContext.hasErrors) false else res2
+ } else res1
}
/** Is type <code>ftpe1</code> strictly more specific than type <code>ftpe2</code>
@@ -942,38 +893,22 @@ trait Infer {
*/
/** error if arguments not within bounds. */
- def checkBounds(pos: Position, pre: Type, owner: Symbol,
- tparams: List[Symbol], targs: List[Type], prefix: String) = {
+ def checkBounds(tree: Tree, pre: Type, owner: Symbol,
+ tparams: List[Symbol], targs: List[Type], prefix: String): Boolean = {
//@M validate variances & bounds of targs wrt variances & bounds of tparams
//@M TODO: better place to check this?
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
- if (!kindErrors.isEmpty) {
- if (targs contains WildcardType) ()
- else error(pos,
- prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
- " do not conform to the expected kinds of the type parameters "+
- tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
- kindErrors.toList.mkString("\n", ", ", ""))
- }
- else if (!isWithinBounds(pre, owner, tparams, targs)) {
+ if(!kindErrors.isEmpty) {
+ if (targs contains WildcardType) true
+ else { KindBoundErrors(tree, prefix, targs, tparams, kindErrors); false }
+ } else if (!isWithinBounds(pre, owner, tparams, targs)) {
if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
- //val bounds = instantiatedBounds(pre, owner, tparams, targs)//DEBUG
- //println("bounds = "+bounds+", targs = "+targs+", targclasses = "+(targs map (_.getClass))+", parents = "+(targs map (_.parents)))
- //println(List.map2(bounds, targs)((bound, targ) => bound containsType targ))
- error(pos,
- prefix + "type arguments " + targs.mkString("[", ",", "]") +
- " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
- (tparams map (_.defString)).mkString("[", ",", "]"))
- if (settings.explaintypes.value) {
- val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
- (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
- (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi))
- ()
- }
- }
- }
+ NotWithinBounds(tree, prefix, targs, tparams, kindErrors)
+ false
+ } else true
+ } else true
}
def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = {
@@ -1055,8 +990,7 @@ trait Infer {
targs: List[Type], pt: Type) {
if (targs eq null) {
if (!tree.tpe.isErroneous && !pt.isErroneous)
- error(tree.pos, "polymorphic expression cannot be instantiated to expected type" +
- foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt))
+ PolymorphicExpressionInstantiationError(tree, undetparams, pt)
} else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
}
@@ -1092,43 +1026,28 @@ trait Infer {
(okparams map (_.name), okargs).zipped.map(_ + "=" + _).mkString("solved: ", ", ", "")
))
- checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")
- val treeSubst = new TreeTypeSubstituter(okparams, okargs)
- treeSubst traverseTrees fn :: args
+ if (checkBounds(fn, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")) {
+ val treeSubst = new TreeTypeSubstituter(okparams, okargs)
+ treeSubst traverseTrees fn :: args
- leftUndet match {
- case Nil => Nil
- case xs =>
- // #3890
- val xs1 = treeSubst.typeMap mapOver xs
- if (xs ne xs1)
- new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
+ leftUndet match {
+ case Nil => Nil
+ case xs =>
+ // #3890
+ val xs1 = treeSubst.typeMap mapOver xs
+ if (xs ne xs1)
+ new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
- xs1
- }
+ xs1
+ }
+ } else Nil
}
catch ifNoInstance { msg =>
- errorTree(fn, "no type parameters for " +
- applyErrorMsg(fn, " exist so that it can be applied to arguments ", args map (_.tpe.widen), WildcardType) +
- "\n --- because ---\n" + msg
- )
- Nil
+ NoMethodInstanceError(fn, args, msg); List()
}
}
- /** Type with all top-level occurrences of abstract types replaced by their bounds */
- def widen(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala )
- case TypeRef(_, sym, _) if sym.isAbstractType =>
- widen(tp.bounds.hi)
- case TypeRef(_, sym, _) if sym.isAliasType =>
- widen(tp.normalize)
- case rtp @ RefinedType(parents, decls) =>
- copyRefinedType(rtp, parents mapConserve widen, decls)
- case AnnotatedType(_, underlying, _) =>
- widen(underlying)
- case _ =>
- tp
- }
+ def widen(tp: Type): Type = abstractTypesToBounds(tp)
/** Substitute free type variables <code>undetparams</code> of type constructor
* <code>tree</code> in pattern, given prototype <code>pt</code>.
@@ -1149,20 +1068,16 @@ trait Infer {
try {
val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe),
true, lubDepth(List(restpe, pt)))
-// checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
+// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- } catch {
- case ex: NoInstance =>
- errorTree(tree, "constructor of type " + restpe +
- " cannot be uniquely instantiated to expected type " + pt +
- "\n --- because ---\n" + ex.getMessage())
+ } catch ifNoInstance{ msg =>
+ NoConstructorInstanceError(tree, restpe, pt, msg)
}
def instError = {
if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
if (settings.explaintypes.value) explainTypes(restpe.instantiateTypeParams(undetparams, tvars), pt)
- errorTree(tree, "constructor cannot be instantiated to expected type" +
- foundReqMsg(restpe, pt))
+ ConstrInstantiationError(tree, restpe, pt)
}
if (restpe.instantiateTypeParams(undetparams, tvars) <:< pt) {
computeArgs
@@ -1232,9 +1147,9 @@ trait Infer {
}
}
- def checkCheckable(pos: Position, tp: Type, kind: String) {
+ def checkCheckable(tree: Tree, tp: Type, kind: String) {
def patternWarning(tp0: Type, prefix: String) = {
- context.unit.uncheckedWarning(pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure")
+ context.unit.uncheckedWarning(tree.pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure")
}
def check(tp: Type, bound: List[Symbol]) {
def isLocalBinding(sym: Symbol) =
@@ -1253,7 +1168,7 @@ trait Infer {
} else if (sym.isAliasType) {
check(tp.normalize, bound)
} else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) {
- error(pos, "type "+tp+" cannot be used in a type pattern or isInstanceOf test")
+ TypePatternOrIsInstanceTestError(tree, tp)
} else {
for (arg <- args) {
if (sym == ArrayClass) check(arg, bound)
@@ -1277,11 +1192,12 @@ trait Infer {
case ExistentialType(quantified, tp1) =>
check(tp1, bound ::: quantified)
case ThisType(_) =>
- ;
+ ()
case NoPrefix =>
- ;
+ ()
case _ =>
patternWarning(tp, "type ")
+ ()
}
}
check(tp, List())
@@ -1304,7 +1220,7 @@ trait Infer {
}
}
- def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Type = {
+ def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type): Type = {
val pt = widen(pt0)
val ptparams = freeTypeParamsOfTerms.collect(pt)
val tpparams = freeTypeParamsOfTerms.collect(pattp)
@@ -1316,10 +1232,12 @@ trait Infer {
* This is the case if the scrutinee has no unresolved type arguments
* and is a "final type", meaning final + invariant in all type parameters.
*/
- if (pt.isFinalType && ptparams.isEmpty && !ptMatchesPattp)
- error(pos, "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt))
+ if (pt.isFinalType && ptparams.isEmpty && !ptMatchesPattp) {
+ IncompatibleScrutineeTypeError(tree0, pattp, pt)
+ return ErrorType
+ }
- checkCheckable(pos, pattp, "pattern ")
+ checkCheckable(tree0, pattp, "pattern ")
if (pattp <:< pt) ()
else {
debuglog("free type params (1) = " + tpparams)
@@ -1342,8 +1260,8 @@ trait Infer {
if (isPopulated(tp, pt1) && isInstantiatable(tvars ++ ptvars) || pattpMatchesPt)
ptvars foreach instantiateTypeVar
else {
- error(pos, "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt))
- return pattp
+ PatternTypeIncompatibleWithPtError1(tree0, pattp, pt)
+ return ErrorType
}
}
tvars foreach instantiateTypeVar
@@ -1364,30 +1282,8 @@ trait Infer {
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
if (pat.tpe <:< pt1)
ptvars foreach instantiateTypeVar
- else {
- val sym = pat.tpe.typeSymbol
- val clazz = sym.companionClass
- val addendum = (
- if (sym.isModuleClass && clazz.isCaseClass && (clazz isSubClass pt1.typeSymbol)) {
- // TODO: move these somewhere reusable.
- val typeString = clazz.typeParams match {
- case Nil => "" + clazz.name
- case xs => xs map (_ => "_") mkString (clazz.name + "[", ",", "]")
- }
- val caseString = (
- clazz.caseFieldAccessors
- map (_ => "_") // could use the actual param names here
- mkString (clazz.name + "(", ",", ")")
- )
- (
- "\nNote: if you intended to match against the class, try `case _: " +
- typeString + "` or `case " + caseString + "`"
- )
- }
- else ""
- )
- error(pat.pos, "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt) + addendum)
- }
+ else
+ PatternTypeIncompatibleWithPtError2(pat, pt1, pt)
}
object toOrigin extends TypeMap {
@@ -1464,7 +1360,7 @@ trait Infer {
* If several alternatives match `pt`, take parameterless one.
* If no alternative matches `pt`, take the parameterless one anyway.
*/
- def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {
+ def inferExprAlternative(tree: Tree, pt: Type) = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice {
val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
val secondTry = alts0.isEmpty
@@ -1495,15 +1391,10 @@ trait Infer {
case _ =>
}
}
- typeErrorTree(tree, tree.symbol.tpe, pt)
+ NoBestExprAlternativeError(tree, pt)
} else if (!competing.isEmpty) {
- if (secondTry) {
- typeErrorTree(tree, tree.symbol.tpe, pt)
- } else {
- if (!pt.isErroneous)
- context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
- setError(tree)
- }
+ if (secondTry) NoBestExprAlternativeError(tree, pt)
+ else { if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt) }
} else {
// val applicable = alts1 filter (alt =>
// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
@@ -1513,9 +1404,11 @@ trait Infer {
}
}
- @inline private def wrapTypeError(expr: => Boolean): Boolean =
- try expr
- catch { case _: TypeError => false }
+ @inline private def inSilentMode(expr: Typer => Boolean): Boolean = {
+ val silentContext = context.makeSilent(context.ambiguousErrors)
+ val res = expr(newTyper(silentContext))
+ if (silentContext.hasErrors) false else res
+ }
// Checks against the name of the parameter and also any @deprecatedName.
private def paramMatchesName(param: Symbol, name: Name) =
@@ -1585,9 +1478,7 @@ trait Infer {
val applicable = resolveOverloadedMethod(argtpes, {
alts filter { alt =>
- // TODO: this will need to be re-written once we substitute throwing exceptions
- // with generating error trees. We wrap this applicability in try/catch because of #4457.
- wrapTypeError(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
+ inSilentMode(typer0 => typer0.infer.isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
(!varArgsOnly || isVarArgsList(alt.tpe.params))
}
})
@@ -1603,16 +1494,13 @@ trait Infer {
if (improves(alt, best)) alt else best)
val competing = applicable.dropWhile(alt => best == alt || improves(best, alt))
if (best == NoSymbol) {
- if (pt == WildcardType) {
- errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
- } else {
+ if (pt == WildcardType)
+ NoBestMethodAlternativeError(tree, argtpes, pt)
+ else
inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
- }
} else if (!competing.isEmpty) {
if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous)
- context.ambiguousError(tree.pos, pre, best, competing.head,
- "argument types " + argtpes.mkString("(", ",", ")") +
- (if (pt == WildcardType) "" else " and expected result type " + pt))
+ AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt)
setError(tree)
()
} else {
@@ -1628,18 +1516,27 @@ trait Infer {
*
* @param infer ...
*/
- def tryTwice(infer: => Unit) {
+ def tryTwice(infer: => Unit): Unit = {
if (context.implicitsEnabled) {
- val reportGeneralErrors = context.reportGeneralErrors
- context.reportGeneralErrors = false
- try context.withImplicitsDisabled(infer)
- catch {
- case ex: CyclicReference => throw ex
- case ex: TypeError =>
- context.reportGeneralErrors = reportGeneralErrors
+ val saved = context.state
+ var fallback = false
+ context.setBufferErrors()
+ val res = try {
+ context.withImplicitsDisabled(infer)
+ if (context.hasErrors) {
+ fallback = true
+ context.restoreState(saved)
+ context.flushBuffer()
infer
+ }
+ } catch {
+ case ex: CyclicReference => throw ex
+ case ex: TypeError => // recoverable cyclic references
+ context.restoreState(saved)
+ if (!fallback) infer else ()
}
- context.reportGeneralErrors = reportGeneralErrors
+ context.restoreState(saved)
+ res
}
else infer
}
@@ -1654,13 +1551,13 @@ trait Infer {
def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Unit = {
val OverloadedType(pre, alts) = tree.tpe
val sym0 = tree.symbol filter (alt => sameLength(alt.typeParams, argtypes))
- def fail(msg: String): Unit = error(tree.pos, msg)
+ def fail(kind: PolyAlternativeErrorKind.ErrorType) =
+ PolyAlternativeError(tree, argtypes, sym0, kind)
- if (sym0 == NoSymbol) return fail(
+ if (sym0 == NoSymbol) return (
if (alts exists (_.typeParams.nonEmpty))
- "wrong number of type parameters for " + treeSymTypeMsg(tree)
- else treeSymTypeMsg(tree) + " does not take type parameters"
- )
+ fail(PolyAlternativeErrorKind.WrongNumber)
+ else fail(PolyAlternativeErrorKind.NoParams))
val (resSym, resTpe) = {
if (!sym0.isOverloaded)
@@ -1668,11 +1565,8 @@ trait Infer {
else {
val sym = sym0 filter (alt => isWithinBounds(pre, alt.owner, alt.typeParams, argtypes))
if (sym == NoSymbol) {
- if (argtypes forall (x => !x.isErroneous)) fail(
- "type arguments " + argtypes.mkString("[", ",", "]") +
- " conform to the bounds of none of the overloaded alternatives of\n "+sym0+
- ": "+sym0.info
- )
+ if (argtypes forall (x => !x.isErroneous))
+ fail(PolyAlternativeErrorKind.ArgsDoNotConform)
return
}
else if (sym.isOverloaded) {
@@ -1689,24 +1583,6 @@ trait Infer {
// Side effects tree with symbol and type
tree setSymbol resSym setType resTpe
}
-
- abstract class TreeForwarder(forwardTo: Tree) extends Tree {
- override def pos = forwardTo.pos
- override def hasSymbol = forwardTo.hasSymbol
- override def symbol = forwardTo.symbol
- override def symbol_=(x: Symbol) = forwardTo.symbol = x
- }
-
- case class AccessError(tree: Tree, sym: Symbol, pre: Type, explanation: String) extends TreeForwarder(tree) {
- setError(this)
-
- // @PP: It is improbable this logic shouldn't be in use elsewhere as well.
- private def location = if (sym.isClassConstructor) context.enclClass.owner else pre.widen
- def emit(): Tree = {
- val realsym = underlyingSymbol(sym)
- errorTree(tree, realsym.fullLocationString + " cannot be accessed in " + location + explanation)
- }
- }
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 7f9e56a926..c63ae90ef6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -97,8 +97,6 @@ trait Macros { self: Analyzer =>
override def defaultReflectiveClassLoader() = libraryClassLoader
}
- class MacroExpandError(val msg: String) extends Exception(msg)
-
/** Return optionally address of companion object and implementation method symbol
* of given macro; or None if implementation classfile cannot be loaded or does
* not contain the macro implementation.
@@ -127,7 +125,7 @@ trait Macros { self: Analyzer =>
* Or, if that fails, and the macro overrides a method return
* tree that calls this method instead of the macro.
*/
- def macroExpand(tree: Tree): Any = {
+ def macroExpand(tree: Tree, context: Context): Option[Any] = {
val macroDef = tree.symbol
macroImpl(macroDef) match {
case Some((receiver, rmeth)) =>
@@ -139,41 +137,55 @@ trait Macros { self: Analyzer =>
}
val rawArgs: Seq[Any] = rawArgss.flatten
try {
- mirror.invoke(receiver, rmeth, rawArgs: _*)
+ Some(mirror.invoke(receiver, rmeth, rawArgs: _*))
} catch {
case ex =>
val realex = ReflectionUtils.unwrapThrowable(ex)
val stacktrace = new java.io.StringWriter()
realex.printStackTrace(new java.io.PrintWriter(stacktrace))
val msg = System.getProperty("line.separator") + stacktrace
- throw new MacroExpandError("exception during macro expansion: " + msg)
+ context.unit.error(tree.pos, "exception during macro expansion: " + msg)
+ None
}
case None =>
val trace = scala.tools.nsc.util.trace when settings.debug.value
- def notFound() = throw new MacroExpandError("macro implementation not found: " + macroDef.name)
- def fallBackToOverridden(tree: Tree): Tree = {
+ def notFound() = {
+ context.unit.error(tree.pos, "macro implementation not found: " + macroDef.name)
+ None
+ }
+ def fallBackToOverridden(tree: Tree): Option[Tree] = {
tree match {
case Select(qual, name) if (macroDef.isMacro) =>
macroDef.allOverriddenSymbols match {
- case first :: others =>
- return Select(qual, name) setPos tree.pos setSymbol first
+ case first :: _ =>
+ Some(Select(qual, name) setPos tree.pos setSymbol first)
case _ =>
trace("macro is not overridden: ")(tree)
notFound()
}
case Apply(fn, args) =>
- Apply(fallBackToOverridden(fn), args) setPos tree.pos
+ fallBackToOverridden(fn) match {
+ case Some(fn1) => Some(Apply(fn1, args) setPos tree.pos)
+ case _ => None
+ }
case TypeApply(fn, args) =>
- TypeApply(fallBackToOverridden(fn), args) setPos tree.pos
+ fallBackToOverridden(fn) match {
+ case Some(fn1) => Some(TypeApply(fn1, args) setPos tree.pos)
+ case _ => None
+ }
case _ =>
trace("unexpected tree in fallback: ")(tree)
notFound()
}
}
- val tree1 = fallBackToOverridden(tree)
- trace("falling back to ")(tree1)
- currentRun.macroExpansionFailed = true
- tree1
+ fallBackToOverridden(tree) match {
+ case Some(tree1) =>
+ trace("falling back to ")(tree1)
+ currentRun.macroExpansionFailed = true
+ Some(tree1)
+ case None =>
+ None
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 29dffd99d6..0c32ff32c0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -17,6 +17,139 @@ trait MethodSynthesis {
import global._
import definitions._
+ import CODE._
+
+ object synthesisUtil {
+ type M[T] = Manifest[T]
+ type CM[T] = ClassManifest[T]
+
+ def ValOrDefDef(sym: Symbol, body: Tree) =
+ if (sym.isLazy) ValDef(sym, body)
+ else DefDef(sym, body)
+
+ def applyTypeInternal(manifests: List[M[_]]): Type = {
+ val symbols = manifests map manifestToSymbol
+ val container :: args = symbols
+ val tparams = container.typeConstructor.typeParams
+
+ // Conservative at present - if manifests were more usable this could do a lot more.
+ require(symbols forall (_ ne NoSymbol), "Must find all manifests: " + symbols)
+ require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container)
+ require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args)
+
+ typeRef(container.typeConstructor.prefix, container, args map (_.tpe))
+ }
+
+ def companionType[T](implicit m: M[T]) =
+ getRequiredModule(m.erasure.getName).tpe
+
+ // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]`
+ def applyType[CC](implicit m1: M[CC]): Type =
+ applyTypeInternal(List(m1))
+
+ def applyType[CC[X1], X1](implicit m1: M[CC[_]], m2: M[X1]): Type =
+ applyTypeInternal(List(m1, m2))
+
+ def applyType[CC[X1, X2], X1, X2](implicit m1: M[CC[_,_]], m2: M[X1], m3: M[X2]): Type =
+ applyTypeInternal(List(m1, m2, m3))
+
+ def applyType[CC[X1, X2, X3], X1, X2, X3](implicit m1: M[CC[_,_,_]], m2: M[X1], m3: M[X2], m4: M[X3]): Type =
+ applyTypeInternal(List(m1, m2, m3, m4))
+
+ def newMethodType[F](owner: Symbol)(implicit m: Manifest[F]): Type = {
+ val fnSymbol = manifestToSymbol(m)
+ assert(fnSymbol isSubClass FunctionClass(m.typeArguments.size - 1), (owner, m))
+ val symbols = m.typeArguments map (m => manifestToSymbol(m))
+ val formals = symbols.init map (_.typeConstructor)
+ val params = owner newSyntheticValueParams formals
+
+ MethodType(params, symbols.last.typeConstructor)
+ }
+ }
+ import synthesisUtil._
+
+ class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) {
+ private def isOverride(name: TermName) =
+ clazzMember(name).alternatives exists (sym => !sym.isDeferred && (sym.owner != clazz))
+
+ def newMethodFlags(name: TermName) = {
+ val overrideFlag = if (isOverride(name)) OVERRIDE else 0L
+ overrideFlag | SYNTHETIC
+ }
+ def newMethodFlags(method: Symbol) = {
+ val overrideFlag = if (isOverride(method.name)) OVERRIDE else 0L
+ (method.flags | overrideFlag | SYNTHETIC) & ~DEFERRED
+ }
+
+ private def finishMethod(method: Symbol, f: Symbol => Tree): Tree =
+ logResult("finishMethod")(localTyper typed ValOrDefDef(method, f(method)))
+
+ private def createInternal(name: Name, f: Symbol => Tree, info: Type): Tree = {
+ val m = clazz.newMethod(name.toTermName, clazz.pos.focus, newMethodFlags(name))
+ finishMethod(m setInfoAndEnter info, f)
+ }
+ private def createInternal(name: Name, f: Symbol => Tree, infoFn: Symbol => Type): Tree = {
+ val m = clazz.newMethod(name.toTermName, clazz.pos.focus, newMethodFlags(name))
+ finishMethod(m setInfoAndEnter infoFn(m), f)
+ }
+ private def cloneInternal(original: Symbol, f: Symbol => Tree, name: Name): Tree = {
+ val m = original.cloneSymbol(clazz, newMethodFlags(original)) setPos clazz.pos.focus
+ m.name = name
+ finishMethod(clazz.info.decls enter m, f)
+ }
+
+ private def cloneInternal(original: Symbol, f: Symbol => Tree): Tree =
+ cloneInternal(original, f, original.name)
+
+ def clazzMember(name: Name) = clazz.info nonPrivateMember name
+ def typeInClazz(sym: Symbol) = clazz.thisType memberType sym
+
+ /** Function argument takes the newly created method symbol of
+ * the same type as `name` in clazz, and returns the tree to be
+ * added to the template.
+ */
+ def overrideMethod(name: Name)(f: Symbol => Tree): Tree =
+ overrideMethod(clazzMember(name))(f)
+
+ def overrideMethod(original: Symbol)(f: Symbol => Tree): Tree =
+ cloneInternal(original, sym => f(sym setFlag OVERRIDE))
+
+ def deriveMethod(original: Symbol, nameFn: Name => Name)(f: Symbol => Tree): Tree =
+ cloneInternal(original, f, nameFn(original.name))
+
+ def createMethod(name: Name, paramTypes: List[Type], returnType: Type)(f: Symbol => Tree): Tree =
+ createInternal(name, f, (m: Symbol) => MethodType(m newSyntheticValueParams paramTypes, returnType))
+
+ def createMethod(name: Name, returnType: Type)(f: Symbol => Tree): Tree =
+ createInternal(name, f, NullaryMethodType(returnType))
+
+ def createMethod(original: Symbol)(f: Symbol => Tree): Tree =
+ createInternal(original.name, f, original.info)
+
+ def forwardMethod(original: Symbol, newMethod: Symbol)(transformArgs: List[Tree] => List[Tree]): Tree =
+ createMethod(original)(m => gen.mkMethodCall(newMethod, transformArgs(m.paramss.head map Ident)))
+
+ def createSwitchMethod(name: Name, range: Seq[Int], returnType: Type)(f: Int => Tree) = {
+ createMethod(name, List(IntClass.tpe), returnType) { m =>
+ val arg0 = Ident(m.firstParam)
+ val default = DEFAULT ==> THROW(IndexOutOfBoundsExceptionClass, arg0)
+ val cases = range.map(num => CASE(LIT(num)) ==> f(num)).toList :+ default
+
+ Match(arg0, cases)
+ }
+ }
+
+ // def foo() = constant
+ def constantMethod(name: Name, value: Any): Tree = {
+ val constant = Constant(value)
+ createMethod(name, Nil, constant.tpe)(_ => Literal(constant))
+ }
+ // def foo = constant
+ def constantNullary(name: Name, value: Any): Tree = {
+ val constant = Constant(value)
+ createMethod(name, constant.tpe)(_ => Literal(constant))
+ }
+ }
/** There are two key methods in here.
*
@@ -32,10 +165,12 @@ trait MethodSynthesis {
trait MethodSynth {
self: Namer =>
+ import NamerErrorGen._
+
def enterGetterSetter(tree: ValDef) {
val ValDef(mods, name, _, _) = tree
if (nme.isSetterName(name))
- context.error(tree.pos, "Names of vals or vars may not end in `_='")
+ ValOrValWithSetterSuffixError(tree)
val getter = Getter(tree).createAndEnterSymbol()
@@ -43,7 +178,7 @@ trait MethodSynthesis {
if (mods.isLazy) enterLazyVal(tree, getter)
else {
if (mods.isPrivateLocal)
- context.error(tree.pos, "private[this] not allowed for case class parameters")
+ PrivateThisCaseClassParameterError(tree)
// Create the setter if necessary.
if (mods.isMutable)
Setter(tree).createAndEnterSymbol()
@@ -187,7 +322,7 @@ trait MethodSynthesis {
override def validate() {
assert(derivedSym != NoSymbol, tree)
if (derivedSym.isOverloaded)
- context.error(derivedSym.pos, derivedSym+" is defined twice")
+ GetterDefinedTwiceError(derivedSym)
super.validate()
}
@@ -255,8 +390,7 @@ trait MethodSynthesis {
if (derivedSym == NoSymbol) {
// the namer decides whether to generate these symbols or not. at that point, we don't
// have symbolic information yet, so we only look for annotations named "BeanProperty".
- context.error(tree.pos,
- "implementation limitation: the BeanProperty annotation cannot be used in a type alias or renamed import")
+ BeanPropertyAnnotationLimitationError(tree)
}
super.validate()
}
@@ -304,9 +438,9 @@ trait MethodSynthesis {
val beans = beanAccessorsFromNames(tree)
if (beans.nonEmpty) {
if (!name(0).isLetter)
- context.error(tree.pos, "`BeanProperty' annotation can be applied only to fields that start with a letter")
+ BeanPropertyAnnotationFieldWithoutLetterError(tree)
else if (mods.isPrivate) // avoids name clashes with private fields in traits
- context.error(tree.pos, "`BeanProperty' annotation can be applied only to non-private fields")
+ BeanPropertyAnnotationPrivateFieldError(tree)
// Create and enter the symbols here, add the trees in finishGetterSetter.
beans foreach (_.createAndEnterSymbol())
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index e04d89047b..0ff2b418f4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -73,7 +73,9 @@ trait Namers extends MethodSynthesis {
classAndNamerOfModule.clear()
}
- abstract class Namer(val context: Context) extends MethodSynth {
+ abstract class Namer(val context: Context) extends MethodSynth with NamerContextErrors {
+
+ import NamerErrorGen._
val typer = newTyper(context)
private lazy val innerNamer =
@@ -87,7 +89,7 @@ trait Namers extends MethodSynthesis {
newNamer(context.makeNewScope(tree, sym))
}
def createInnerNamer() = {
- newNamer(context.make(context.tree, owner, new Scope))
+ newNamer(context.make(context.tree, owner, newScope))
}
def createPrimaryConstructorParameterNamer: Namer = { //todo: can we merge this with SCCmode?
val classContext = context.enclClass
@@ -109,9 +111,10 @@ trait Namers extends MethodSynthesis {
protected def owner = context.owner
private def contextFile = context.unit.source.file
- private def typeErrorHandler[T](pos: Position, alt: T): PartialFunction[Throwable, T] = {
+ private def typeErrorHandler[T](tree: Tree, alt: T): PartialFunction[Throwable, T] = {
case ex: TypeError =>
- typer.reportTypeError(pos, ex)
+ // H@ need to ensure that we handle only cyclic references
+ TypeSigError(tree, ex)
alt
}
// PRIVATE | LOCAL are fields generated for primary constructor arguments
@@ -129,10 +132,17 @@ trait Namers extends MethodSynthesis {
|| vd.symbol.isLazy
)
- def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = {
+ def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym =
if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym
- else sym setPrivateWithin typer.qualifyingClass(tree, mods.privateWithin, true)
- }
+ else sym setPrivateWithin (
+ typer.qualifyingClass(tree, mods.privateWithin, true) match {
+ case None =>
+ NoSymbol
+ case Some(sym) =>
+ sym
+ }
+ )
+
def setPrivateWithin(tree: MemberDef, sym: Symbol): Symbol =
setPrivateWithin(tree, sym, tree.mods)
@@ -195,14 +205,6 @@ trait Namers extends MethodSynthesis {
)
)
- private def doubleDefError(pos: Position, sym: Symbol) {
- val s1 = if (sym.isModule) "case class companion " else ""
- val s2 = if (sym.isSynthetic) "(compiler-generated) " + s1 else ""
- val s3 = if (sym.isCase) "case class " + sym.name else "" + sym
-
- context.error(pos, sym.name + " is already defined as " + s2 + s3)
- }
-
private def allowsOverload(sym: Symbol) = (
sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass
)
@@ -221,7 +223,7 @@ trait Namers extends MethodSynthesis {
if (!allowsOverload(sym)) {
val prev = scope.lookupEntry(sym.name)
if ((prev ne null) && prev.owner == scope && conflict(sym, prev.sym)) {
- doubleDefError(sym.pos, prev.sym)
+ DoubleDefError(sym, prev.sym)
sym setInfo ErrorType
scope unlink prev.sym // let them co-exist...
// FIXME: The comment "let them co-exist" is confusing given that the
@@ -250,7 +252,7 @@ trait Namers extends MethodSynthesis {
returnContext
}
tree.symbol match {
- case NoSymbol => try dispatch() catch typeErrorHandler(tree.pos, this.context)
+ case NoSymbol => try dispatch() catch typeErrorHandler(tree, this.context)
case sym => enterExistingSym(sym)
}
}
@@ -447,6 +449,7 @@ trait Namers extends MethodSynthesis {
}
private def checkSelectors(tree: Import): Unit = {
+ import DuplicatesErrorKinds._
val Import(expr, selectors) = tree
val base = expr.tpe
@@ -483,8 +486,10 @@ trait Namers extends MethodSynthesis {
typeSig(tree)
}
// for Java code importing Scala objects
- else if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from)))
- notAMemberError(tree.pos, expr, from)
+ else if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from))) {
+ typer.TyperErrorGen.NotAMemberError(tree, expr, from)
+ typer.infer.setError(tree)
+ }
}
// Setting the position at the import means that if there is
// more than one hidden name, the second will not be warned.
@@ -492,20 +497,21 @@ trait Namers extends MethodSynthesis {
checkNotRedundant(tree.pos withPoint fromPos, from, to)
}
}
- def noDuplicates(names: List[Name], message: String) {
+
+ def noDuplicates(names: List[Name], check: DuplicatesErrorKinds.Value) {
def loop(xs: List[Name]): Unit = xs match {
case Nil => ()
case hd :: tl =>
if (hd == nme.WILDCARD || !(tl contains hd)) loop(tl)
- else context.error(tree.pos, hd.decode + " " + message)
+ else DuplicatesError(tree, hd, check)
}
loop(names filterNot (x => x == null || x == nme.WILDCARD))
}
selectors foreach checkSelector
// checks on the whole set
- noDuplicates(selectors map (_.name), "is renamed twice")
- noDuplicates(selectors map (_.rename), "appears twice as a target of a renaming")
+ noDuplicates(selectors map (_.name), RenamedTwice)
+ noDuplicates(selectors map (_.rename), AppearsTwice)
}
def enterCopyMethodOrGetter(tree: Tree, tparams: List[TypeDef]): Symbol = {
@@ -620,7 +626,7 @@ trait Namers extends MethodSynthesis {
if (mods.isCase) {
if (treeInfo.firstConstructorArgs(impl.body).size > MaxFunctionArity)
- context.error(tree.pos, "Implementation restriction: case classes cannot have more than " + MaxFunctionArity + " parameters.")
+ MaxParametersCaseClassError(tree)
val m = ensureCompanionObject(tree, caseModuleDef)
classOfModuleClass(m.moduleClass) = new WeakReference(tree)
@@ -823,7 +829,7 @@ trait Namers extends MethodSynthesis {
val tp = tpt.tpe
val inheritsSelf = tp.typeSymbol == owner
if (inheritsSelf)
- context.error(tpt.pos, ""+tp.typeSymbol+" inherits itself")
+ InheritsItselfError(tpt)
if (inheritsSelf || tp.isError) AnyRefClass.tpe
else tp
@@ -832,7 +838,7 @@ trait Namers extends MethodSynthesis {
val parents = typer.parentTypes(templ) map checkParent
enterSelf(templ.self)
- val decls = new Scope
+ val decls = newScope
val templateNamer = newNamer(context.make(templ, clazz, decls))
templateNamer enterSyms templ.body
@@ -918,7 +924,7 @@ trait Namers extends MethodSynthesis {
}
def thisMethodType(restpe: Type) = {
- val checkDependencies = new DependentTypeChecker(context)
+ val checkDependencies = new DependentTypeChecker(context)(this)
checkDependencies check vparamSymss
// DEPMETTODO: check not needed when they become on by default
checkDependencies(restpe)
@@ -994,7 +1000,7 @@ trait Namers extends MethodSynthesis {
}
mforeach(vparamss) { vparam =>
if (vparam.tpt.isEmpty) {
- context.error(vparam.pos, "missing parameter type")
+ MissingParameterOrValTypeError(vparam)
vparam.tpt defineType ErrorType
}
}
@@ -1262,7 +1268,7 @@ trait Namers extends MethodSynthesis {
val typer1 = typer.constrTyperIf(isBeforeSupercall)
if (tpt.isEmpty) {
if (rhs.isEmpty) {
- context.error(tpt.pos, "missing parameter type");
+ MissingParameterOrValTypeError(tpt)
ErrorType
}
else assignTypeToTree(vdef, newTyper(typer1.context.make(vdef, sym)), WildcardType)
@@ -1276,7 +1282,7 @@ trait Namers extends MethodSynthesis {
val expr1 = typer.typedQualifier(expr)
typer checkStable expr1
if (expr1.symbol != null && expr1.symbol.isRootPackage)
- context.error(tree.pos, "_root_ cannot be imported")
+ RootImportError(tree)
val newImport = treeCopy.Import(tree, expr1, selectors).asInstanceOf[Import]
checkSelectors(newImport)
@@ -1290,7 +1296,7 @@ trait Namers extends MethodSynthesis {
val result =
try getSig
- catch typeErrorHandler(tree.pos, ErrorType)
+ catch typeErrorHandler(tree, ErrorType)
result match {
case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => typer.deskolemizeTypeParams(tparams)(result)
@@ -1337,43 +1343,43 @@ trait Namers extends MethodSynthesis {
* - declarations only in mixins or abstract classes (when not @native)
*/
def validate(sym: Symbol) {
- def fail(msg: String) = context.error(sym.pos, msg)
+ import SymValidateErrors._
+ def fail(kind: SymValidateErrors.Value) = SymbolValidationError(sym, kind)
+
def checkWithDeferred(flag: Int) {
if (sym hasFlag flag)
- fail("abstract member may not have " + flagsToString(flag) + " modifier")
+ AbstractMemberWithModiferError(sym, flag)
}
def checkNoConflict(flag1: Int, flag2: Int) {
if (sym hasAllFlags flag1 | flag2)
- fail("illegal combination of modifiers: %s and %s for: %s".format(
- flagsToString(flag1), flagsToString(flag2), sym))
+ IllegalModifierCombination(sym, flag1, flag2)
}
if (sym.isImplicit) {
if (sym.isConstructor)
- fail("`implicit' modifier not allowed for constructors")
+ fail(ImplicitConstr)
if (!sym.isTerm)
- fail("`implicit' modifier can be used only for values, variables and methods")
+ fail(ImplicitNotTerm)
if (sym.owner.isPackageClass)
- fail("`implicit' modifier cannot be used for top-level objects")
+ fail(ImplicitTopObject)
}
if (sym.isClass) {
if (sym.isAnyOverride && !sym.hasFlag(TRAIT))
- fail("`override' modifier not allowed for classes")
- }
- else {
+ fail(OverrideClass)
+ } else {
if (sym.isSealed)
- fail("`sealed' modifier can be used only for classes")
+ fail(SealedNonClass)
if (sym.hasFlag(ABSTRACT))
- fail("`abstract' modifier can be used only for classes; it should be omitted for abstract members")
+ fail(AbstractNonClass)
}
if (sym.isConstructor && sym.isAnyOverride)
- fail("`override' modifier not allowed for constructors")
+ fail(OverrideConstr)
if (sym.isAbstractOverride && !sym.owner.isTrait)
- fail("`abstract override' modifier only allowed for members of traits")
+ fail(AbstractOverride)
if (sym.isLazy && sym.hasFlag(PRESUPER))
- fail("`lazy' definitions may not be initialized early")
+ fail(LazyAndEarlyInit)
if (sym.info.typeSymbol == FunctionClass(0) && sym.isValueParameter && sym.owner.isCaseClass)
- fail("pass-by-name arguments not allowed for case class parameters")
+ fail(ByNameParameter)
if (sym.isDeferred) {
// Is this symbol type always allowed the deferred flag?
@@ -1391,7 +1397,7 @@ trait Namers extends MethodSynthesis {
if (sym hasAnnotation NativeAttr)
sym resetFlag DEFERRED
else if (!symbolAllowsDeferred && ownerRequiresConcrete)
- fail("only classes can have declared but undefined members" + abstractVarMessage(sym))
+ fail(AbstractVar)
checkWithDeferred(PRIVATE)
checkWithDeferred(FINAL)
@@ -1456,14 +1462,14 @@ trait Namers extends MethodSynthesis {
// def foo[T, T2](a: T, x: T2)(implicit w: ComputeT2[T, T2])
// moreover, the latter is not an encoding of the former, which hides type
// inference of T2, so you can specify T while T2 is purely computed
- private class DependentTypeChecker(ctx: Context) extends TypeTraverser {
+ private class DependentTypeChecker(ctx: Context)(namer: Namer) extends TypeTraverser {
private[this] val okParams = mutable.Set[Symbol]()
private[this] val method = ctx.owner
def traverse(tp: Type) = tp match {
case SingleType(_, sym) =>
if (sym.owner == method && sym.isValueParameter && !okParams(sym))
- ctx.error(sym.pos, "illegal dependent method type" + errorAddendum)
+ namer.NamerErrorGen.IllegalDependentMethTpeError(sym)(ctx)
case _ => mapOver(tp)
}
@@ -1476,8 +1482,6 @@ trait Namers extends MethodSynthesis {
okParams ++= vps
}
}
- private def errorAddendum =
- ": parameter appears in the type of another parameter in the same section or an earlier one"
}
@deprecated("Use underlyingSymbol instead", "2.10.0")
@@ -1506,7 +1510,7 @@ trait Namers extends MethodSynthesis {
}
catch {
case e: InvalidCompanions =>
- ctx.error(original.pos, e.getMessage)
+ ctx.unit.error(original.pos, e.getMessage)
NoSymbol
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 79cb211215..3a3c244d1c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -17,6 +17,7 @@ trait NamesDefaults { self: Analyzer =>
import global._
import definitions._
+ import NamesDefaultsErrorsGen._
val defaultParametersOfMethod =
perRunCaches.newWeakMap[Symbol, Set[Symbol]]() withDefaultValue Set()
@@ -312,8 +313,7 @@ trait NamesDefaults { self: Analyzer =>
// type the application without names; put the arguments in definition-site order
val typedApp = doTypedApply(tree, funOnly, reorderArgs(namelessArgs, argPos), mode, pt)
-
- if (typedApp.tpe.isError) setError(tree)
+ if (typedApp.isErrorTyped) tree
else typedApp match {
// Extract the typed arguments, restore the call-site evaluation order (using
// ValDef's in the block), change the arguments to these local values.
@@ -384,6 +384,7 @@ trait NamesDefaults { self: Analyzer =>
if (missing forall (_.hasDefaultFlag)) {
val defaultArgs = missing flatMap (p => {
val defGetter = defaultGetter(p, context)
+ // TODO #3649 can create spurious errors when companion object is gone (because it becomes unlinked from scope)
if (defGetter == NoSymbol) None // prevent crash in erroneous trees, #3649
else {
var default1 = qual match {
@@ -434,12 +435,12 @@ trait NamesDefaults { self: Analyzer =>
private def savingUndeterminedTParams[T](context: Context)(fn: List[Symbol] => T): T = {
val savedParams = context.extractUndetparams()
- val savedReporting = context.reportAmbiguousErrors
+ val savedReporting = context.ambiguousErrors
- context.reportAmbiguousErrors = false
+ context.setAmbiguousErrors(false)
try fn(savedParams)
finally {
- context.reportAmbiguousErrors = savedReporting
+ context.setAmbiguousErrors(savedReporting)
//@M note that we don't get here when an ambiguity was detected (during the computation of res),
// as errorTree throws an exception
context.undetparams = savedParams
@@ -488,7 +489,7 @@ trait NamesDefaults { self: Analyzer =>
// is called, and EmptyTree can only be typed NoType. Thus we need to
// disable conforms as a view...
try typer.silent(_.typed(arg, subst(paramtpe))) match {
- case t: Tree => !t.isErroneous
+ case SilentResultValue(t) => !t.isErroneous // #4041
case _ => false
}
catch {
@@ -496,9 +497,7 @@ trait NamesDefaults { self: Analyzer =>
// CyclicReferences. Fix for #3685
case cr @ CyclicReference(sym, _) =>
(sym.name == param.name) && sym.accessedOrSelf.isVariable && {
- context.error(sym.pos,
- "variable definition needs type because '%s' is used as a named argument in its body.".format(sym.name))
- typer.infer.setError(arg)
+ NameClashError(sym, arg)(typer.context)
true
}
}
@@ -514,18 +513,17 @@ trait NamesDefaults { self: Analyzer =>
* after named ones.
*/
def removeNames(typer: Typer)(args: List[Tree], params: List[Symbol]): (List[Tree], Array[Int]) = {
- import typer.context
+ implicit val context0 = typer.context
// maps indices from (order written by user) to (order of definition)
val argPos = Array.fill(args.length)(-1)
var positionalAllowed = true
val namelessArgs = mapWithIndex(args) { (arg, index) =>
- def fail(msg: String) = typer.infer.errorTree(arg, msg)
arg match {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
def matchesName(param: Symbol) = !param.isSynthetic && (
(param.name == name) || (param.deprecatedParamName match {
case Some(`name`) =>
- context.unit.deprecationWarning(arg.pos,
+ context0.unit.deprecationWarning(arg.pos,
"the parameter name "+ name +" has been deprecated. Use "+ param.name +" instead.")
true
case _ => false
@@ -539,12 +537,12 @@ trait NamesDefaults { self: Analyzer =>
// treat the arg as an assignment of type Unit
Assign(arg.lhs, rhs) setPos arg.pos
}
- else fail("unknown parameter name: " + name)
+ else UnknownParameterNameNamesDefaultError(arg, name)
}
else if (argPos contains pos)
- fail("parameter specified twice: " + name)
+ DoubleParamNamesDefaultError(arg, name)
else if (isAmbiguousAssignment(typer, params(pos), arg))
- fail("reference to " + name + " is ambiguous; it is both a method parameter and a variable in scope.")
+ AmbiguousReferenceInNamesDefaultError(arg, name)
else {
// if the named argument is on the original parameter
// position, positional after named is allowed.
@@ -556,7 +554,7 @@ trait NamesDefaults { self: Analyzer =>
case _ =>
argPos(index) = index
if (positionalAllowed) arg
- else fail("positional after named argument.")
+ else PositionalAfterNamedNamesDefaultError(arg)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 4104803194..44579400ff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -81,7 +81,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
// we don't transform after typers
// (that would require much more sophistication when generating trees,
// and the only place that emits Matches after typers is for exception handling anyway)
- assert(phase.id <= currentRun.typerPhase.id)
+ assert(phase.id <= currentRun.typerPhase.id, phase)
val scrutType = repeatedToSeq(elimAnonymousClass(scrut.tpe.widen))
@@ -315,7 +315,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
val extractorCall = try {
context.undetparams = Nil
silent(_.typed(Apply(Select(orig, extractor), List(Ident(nme.SELECTOR_DUMMY) setType fun.tpe.finalResultType)), EXPRmode, WildcardType), reportAmbiguousErrors = false) match {
- case extractorCall: Tree => extractorCall // if !extractorCall.containsError()
+ case SilentResultValue(extractorCall) => extractorCall // if !extractorCall.containsError()
case _ =>
// this fails to resolve overloading properly...
// Apply(typedOperator(Select(orig, extractor)), List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway
@@ -876,7 +876,7 @@ defined class Foo */
private val reusedBy = new collection.mutable.HashSet[Test]
var reuses: Option[Test] = None
def registerReuseBy(later: Test): Unit = {
- assert(later.reuses.isEmpty)
+ assert(later.reuses.isEmpty, later.reuses)
reusedBy += later
later.reuses = Some(this)
}
@@ -1128,62 +1128,48 @@ defined class Foo */
// }
// }
- def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Tree] = if (optimizingCodeGen) {
- def unfold(tms: List[TreeMaker], currLabel: Option[Symbol] = None, nextLabel: Option[Symbol] = None): List[CaseDef] = tms match {
- // constant
- case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil => import CODE._
- @inline
- def substedBody = btm.substitution(body)
- val labelledBody = currLabel match {
- case None => substedBody // currLabel.isEmpty implies nextLabel.isEmpty
- case Some(myLabel) =>
- LabelDef(myLabel, Nil,
- nextLabel match {
- case None => substedBody
- case Some(next) => ID(next) APPLY ()
- }
- )
- }
- List(CaseDef(const, EmptyTree, labelledBody))
-
- // alternatives
- case AlternativesTreeMaker(_, altss, _) :: bodyTm :: Nil => // assert(currLabel.isEmpty && nextLabel.isEmpty)
- val labels = altss map { alts =>
- Some(freshSym(NoPosition, MethodType(Nil, pt), "$alt$") setFlag (METHOD | LABEL))
- }
-
- val caseDefs = (altss, labels, labels.tail :+ None).zipped.map { case (alts, currLabel, nextLabel) =>
- unfold(alts :+ bodyTm, currLabel, nextLabel)
- }
-
- if (caseDefs exists (_.isEmpty)) Nil
- else caseDefs.flatten
-
- case _ => Nil // failure
- }
+ def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Tree] = if (!optimizingCodeGen) None else {
+ def sequence[T](xs: List[Option[T]]): Option[List[T]] =
+ if (xs exists (_.isEmpty)) None else Some(xs.flatten)
val caseDefs = cases map { makers =>
removeSubstOnly(makers) match {
// default case (don't move this to unfold, as it may only occur on the top level, not as an alternative -- well, except in degenerate matches)
case (btm@BodyTreeMaker(body, _)) :: Nil =>
- List(CaseDef(Ident(nme.WILDCARD), EmptyTree, btm.substitution(body)))
- case nonTrivialMakers =>
- unfold(nonTrivialMakers)
+ Some(CaseDef(Ident(nme.WILDCARD), EmptyTree, btm.substitution(body)))
+ // constant
+ case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil => import CODE._
+ Some(CaseDef(const, EmptyTree, btm.substitution(body)))
+ // alternatives
+ case AlternativesTreeMaker(_, altss, _) :: (btm@BodyTreeMaker(body, _)) :: Nil => // assert(currLabel.isEmpty && nextLabel.isEmpty)
+ val caseConstants = altss map {
+ case EqualityTestTreeMaker(_, const@SwitchablePattern(), _) :: Nil =>
+ Some(const)
+ case _ =>
+ None
+ }
+
+ sequence(caseConstants) map { contants =>
+ val substedBody = btm.substitution(body)
+ CaseDef(Alternative(contants), EmptyTree, substedBody)
+ }
+ case _ =>
+ None //failure (can't translate pattern to a switch)
}
}
- if (caseDefs exists (_.isEmpty)) None
- else { import CODE._
+ sequence(caseDefs) map { caseDefs =>
+ import CODE._
val matcher = BLOCK(
VAL(scrutSym) === scrut, // TODO: type test for switchable type if patterns allow switch but the scrutinee doesn't
- Match(REF(scrutSym), caseDefs.flatten) // match on scrutSym, not scrut to avoid duplicating scrut
+ Match(REF(scrutSym), caseDefs) // match on scrutSym, not scrut to avoid duplicating scrut
)
// matcher filter (tree => tree.tpe == null) foreach println
// treeBrowser browse matcher
- Some(matcher) // set type to avoid recursion in typedMatch
+ matcher // set type to avoid recursion in typedMatch
}
- } else None
+ }
def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] =
doCSE(prevBinder, doDCE(prevBinder, cases, pt), pt)
@@ -1253,7 +1239,7 @@ defined class Foo */
case d : DefTree if (d.symbol != NoSymbol) && ((d.symbol.owner == NoSymbol) || (d.symbol.owner == origOwner)) => // don't indiscriminately change existing owners! (see e.g., pos/t3440, pos/t3534, pos/unapplyContexts2)
// println("def: "+ (d, d.symbol.ownerChain, currentOwner.ownerChain))
if(d.symbol.isLazy) { // for lazy val's accessor -- is there no tree??
- assert(d.symbol.lazyAccessor != NoSymbol && d.symbol.lazyAccessor.owner == d.symbol.owner)
+ assert(d.symbol.lazyAccessor != NoSymbol && d.symbol.lazyAccessor.owner == d.symbol.owner, d.symbol.lazyAccessor)
d.symbol.lazyAccessor.owner = currentOwner
}
if(d.symbol.moduleClass ne NoSymbol)
@@ -1471,7 +1457,7 @@ defined class Foo */
def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") = {ctr += 1;
// assert(owner ne null)
// assert(owner ne NoSymbol)
- new TermSymbol(NoSymbol, pos, vpmName.counted(prefix, ctr)) setInfo repackExistential(tp)
+ NoSymbol.newTermSymbol(vpmName.counted(prefix, ctr), pos) setInfo repackExistential(tp)
}
def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 112aa47114..a99d09173e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -955,7 +955,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// Forward reference checking ---------------------------------------------------
class LevelInfo(val outer: LevelInfo) {
- val scope: Scope = if (outer eq null) new Scope else new Scope(outer.scope)
+ val scope: Scope = if (outer eq null) newScope else newNestedScope(outer.scope)
var maxindex: Int = Int.MinValue
var refpos: Position = _
var refsym: Symbol = _
@@ -1240,11 +1240,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
/* Check whether argument types conform to bounds of type parameters */
- private def checkBounds(pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type], pos: Position): Unit =
- try typer.infer.checkBounds(pos, pre, owner, tparams, argtps, "")
+ private def checkBounds(tree0: Tree, pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type]): Unit =
+ try typer.infer.checkBounds(tree0, pre, owner, tparams, argtps, "")
catch {
case ex: TypeError =>
- unit.error(pos, ex.getMessage());
+ unit.error(tree0.pos, ex.getMessage())
if (settings.explaintypes.value) {
val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds)
(argtps, bounds).zipped map ((targ, bound) => explainTypes(bound.lo, targ))
@@ -1374,22 +1374,22 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
false
}
- private def checkTypeRef(tp: Type, pos: Position) = tp match {
+ private def checkTypeRef(tp: Type, tree: Tree) = tp match {
case TypeRef(pre, sym, args) =>
- checkDeprecated(sym, pos)
+ checkDeprecated(sym, tree.pos)
if(sym.isJavaDefined)
sym.typeParams foreach (_.cookJavaRawInfo())
if (!tp.isHigherKinded)
- checkBounds(pre, sym.owner, sym.typeParams, args, pos)
+ checkBounds(tree, pre, sym.owner, sym.typeParams, args)
case _ =>
}
- private def checkAnnotations(tpes: List[Type], pos: Position) = tpes foreach (tp => checkTypeRef(tp, pos))
+ private def checkAnnotations(tpes: List[Type], tree: Tree) = tpes foreach (tp => checkTypeRef(tp, tree))
private def doTypeTraversal(tree: Tree)(f: Type => Unit) = if (!inPattern) tree.tpe foreach f
private def applyRefchecksToAnnotations(tree: Tree): Unit = {
def applyChecks(annots: List[AnnotationInfo]) = {
- checkAnnotations(annots map (_.atp), tree.pos)
+ checkAnnotations(annots map (_.atp), tree)
transformTrees(annots flatMap (_.args))
}
@@ -1404,7 +1404,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case tpt@TypeTree() =>
if(tpt.original != null) {
tpt.original foreach {
- case dc@TypeTreeWithDeferredRefCheck() => applyRefchecksToAnnotations(dc.check()) // #2416
+ case dc@TypeTreeWithDeferredRefCheck() =>
+ applyRefchecksToAnnotations(dc.check()) // #2416
case _ =>
}
}
@@ -1450,7 +1451,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
unit.error(tree.pos, "too many dimensions for array creation")
Literal(Constant(null))
} else {
- localTyper.getManifestTree(tree.pos, etpe, false)
+ localTyper.getManifestTree(tree, etpe, false)
}
}
val newResult = localTyper.typedPos(tree.pos) {
@@ -1490,7 +1491,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def checkSuper(mix: Name) =
// term should have been eliminated by super accessors
- assert(!(qual.symbol.isTrait && sym.isTerm && mix == tpnme.EMPTY))
+ assert(!(qual.symbol.isTrait && sym.isTerm && mix == tpnme.EMPTY), (qual.symbol, sym, mix))
transformCaseApply(tree,
qual match {
@@ -1578,13 +1579,13 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case ExistentialType(tparams, tpe) =>
existentialParams ++= tparams
case t: TypeRef =>
- checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree.pos)
+ checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree)
case _ =>
}
tree
case TypeApply(fn, args) =>
- checkBounds(NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe), tree.pos)
+ checkBounds(tree, NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe))
transformCaseApply(tree, ())
case x @ Apply(_, _) =>
@@ -1641,7 +1642,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
result
} catch {
case ex: TypeError =>
- if (settings.debug.value) ex.printStackTrace();
+ if (settings.debug.value) ex.printStackTrace()
unit.error(tree.pos, ex.getMessage())
tree
} finally {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 4e4fbe35cb..0ab09b4fec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -51,12 +51,21 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
private def checkPackedConforms(tree: Tree, pt: Type): Tree = {
+ def typeError(typer: analyzer.Typer, pos: Position, found: Type, req: Type) {
+ if (!found.isErroneous && !req.isErroneous) {
+ val msg = analyzer.ErrorUtils.typeErrorMsg(found, req, typer.infer.isPossiblyMissingArgs(found, req))
+ typer.context.error(pos, analyzer.withAddendum(pos)(msg))
+ if (settings.explaintypes.value)
+ explainTypes(found, req)
+ }
+ }
+
if (tree.tpe exists (_.typeSymbol.isExistentialSkolem)) {
val packed = localTyper.packedType(tree, NoSymbol)
if (!(packed <:< pt)) {
val errorContext = localTyper.context.make(localTyper.context.tree)
- errorContext.reportGeneralErrors = true
- analyzer.newTyper(errorContext).infer.typeError(tree.pos, packed, pt)
+ errorContext.setReportErrors()
+ typeError(analyzer.newTyper(errorContext), tree.pos, packed, pt)
}
}
tree
@@ -444,7 +453,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (referencingClass.isSubClass(sym.owner.enclClass)
|| referencingClass.thisSym.isSubClass(sym.owner.enclClass)
|| referencingClass.enclosingPackageClass == sym.owner.enclosingPackageClass) {
- assert(referencingClass.isClass)
+ assert(referencingClass.isClass, referencingClass)
referencingClass
} else if(referencingClass.owner.enclClass != NoSymbol)
hostForAccessorOf(sym, referencingClass.owner.enclClass)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 4e986dc5aa..4ea21b1c44 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -36,158 +36,13 @@ trait SyntheticMethods extends ast.TreeDSL {
import definitions._
import CODE._
- private object util {
- private type CM[T] = ClassManifest[T]
-
- def ValOrDefDef(sym: Symbol, body: Tree) =
- if (sym.isLazy) ValDef(sym, body)
- else DefDef(sym, body)
-
- /** To avoid unchecked warnings on polymorphic classes.
- */
- def clazzTypeToTest(clazz: Symbol) = clazz.tpe.normalize match {
- case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe)
- case tp => tp
- }
-
- def makeMethodPublic(method: Symbol): Symbol = (
- method setPrivateWithin NoSymbol resetFlag AccessFlags
- )
-
- def methodArg(method: Symbol, idx: Int): Tree = Ident(method.paramss.head(idx))
-
- private def applyTypeInternal(manifests: List[CM[_]]): Type = {
- val symbols = manifests map manifestToSymbol
- val container :: args = symbols
- val tparams = container.typeConstructor.typeParams
-
- // Overly conservative at present - if manifests were more usable
- // this could do a lot more.
- require(symbols forall (_ ne NoSymbol), "Must find all manifests: " + symbols)
- require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container)
- require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args)
- require(args forall (_.typeConstructor.typeParams.isEmpty), "Arguments must be unparameterized: " + args)
-
- typeRef(container.typeConstructor.prefix, container, args map (_.tpe))
- }
-
- def manifestToSymbol(m: CM[_]): Symbol = m match {
- case x: scala.reflect.AnyValManifest[_] => getMember(ScalaPackageClass, newTermName("" + x))
- case _ => getClassIfDefined(m.erasure.getName)
- }
- def companionType[T](implicit m: CM[T]) =
- getRequiredModule(m.erasure.getName).tpe
-
- // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]`
- def applyType[M](implicit m1: CM[M]): Type =
- applyTypeInternal(List(m1))
-
- def applyType[M[X1], X1](implicit m1: CM[M[_]], m2: CM[X1]): Type =
- applyTypeInternal(List(m1, m2))
-
- def applyType[M[X1, X2], X1, X2](implicit m1: CM[M[_,_]], m2: CM[X1], m3: CM[X2]): Type =
- applyTypeInternal(List(m1, m2, m3))
-
- def applyType[M[X1, X2, X3], X1, X2, X3](implicit m1: CM[M[_,_,_]], m2: CM[X1], m3: CM[X2], m4: CM[X3]): Type =
- applyTypeInternal(List(m1, m2, m3, m4))
- }
- import util._
-
- class MethodSynthesis(val clazz: Symbol, localTyper: Typer) {
- private def isOverride(method: Symbol) =
- clazzMember(method.name).alternatives exists (sym => (sym != method) && !sym.isDeferred)
-
- private def setMethodFlags(method: Symbol): Symbol = {
- val overrideFlag = if (isOverride(method)) OVERRIDE else 0L
-
- method setFlag (overrideFlag | SYNTHETIC) resetFlag DEFERRED
- }
-
- private def finishMethod(method: Symbol, f: Symbol => Tree): Tree = {
- setMethodFlags(method)
- clazz.info.decls enter method
- logResult("finishMethod")(localTyper typed ValOrDefDef(method, f(method)))
- }
-
- private def createInternal(name: Name, f: Symbol => Tree, info: Type): Tree = {
- val m = clazz.newMethod(name.toTermName, clazz.pos.focus)
- m setInfo info
- finishMethod(m, f)
- }
- private def createInternal(name: Name, f: Symbol => Tree, infoFn: Symbol => Type): Tree = {
- val m = clazz.newMethod(name.toTermName, clazz.pos.focus)
- m setInfo infoFn(m)
- finishMethod(m, f)
- }
- private def cloneInternal(original: Symbol, f: Symbol => Tree, name: Name): Tree = {
- val m = original.cloneSymbol(clazz) setPos clazz.pos.focus
- m.name = name
- finishMethod(m, f)
- }
-
- private def cloneInternal(original: Symbol, f: Symbol => Tree): Tree =
- cloneInternal(original, f, original.name)
-
- def clazzMember(name: Name) = clazz.info nonPrivateMember name match {
- case NoSymbol => log("In " + clazz + ", " + name + " not found: " + clazz.info) ; NoSymbol
- case sym => sym
- }
- def typeInClazz(sym: Symbol) = clazz.thisType memberType sym
-
- /** Function argument takes the newly created method symbol of
- * the same type as `name` in clazz, and returns the tree to be
- * added to the template.
- */
- def overrideMethod(name: Name)(f: Symbol => Tree): Tree =
- overrideMethod(clazzMember(name))(f)
-
- def overrideMethod(original: Symbol)(f: Symbol => Tree): Tree =
- cloneInternal(original, sym => f(sym setFlag OVERRIDE))
-
- def deriveMethod(original: Symbol, nameFn: Name => Name)(f: Symbol => Tree): Tree =
- cloneInternal(original, f, nameFn(original.name))
-
- def createMethod(name: Name, paramTypes: List[Type], returnType: Type)(f: Symbol => Tree): Tree =
- createInternal(name, f, (m: Symbol) => MethodType(m newSyntheticValueParams paramTypes, returnType))
-
- def createMethod(name: Name, returnType: Type)(f: Symbol => Tree): Tree =
- createInternal(name, f, NullaryMethodType(returnType))
-
- def createMethod(original: Symbol)(f: Symbol => Tree): Tree =
- createInternal(original.name, f, original.info)
-
- def forwardMethod(original: Symbol, newMethod: Symbol)(transformArgs: List[Tree] => List[Tree]): Tree =
- createMethod(original)(m => gen.mkMethodCall(newMethod, transformArgs(m.paramss.head map Ident)))
-
- def createSwitchMethod(name: Name, range: Seq[Int], returnType: Type)(f: Int => Tree) = {
- createMethod(name, List(IntClass.tpe), returnType) { m =>
- val arg0 = methodArg(m, 0)
- val default = DEFAULT ==> THROW(IndexOutOfBoundsExceptionClass, arg0)
- val cases = range.map(num => CASE(LIT(num)) ==> f(num)).toList :+ default
-
- Match(arg0, cases)
- }
- }
-
- // def foo() = constant
- def constantMethod(name: Name, value: Any): Tree = {
- val constant = Constant(value)
- createMethod(name, Nil, constant.tpe)(_ => Literal(constant))
- }
- // def foo = constant
- def constantNullary(name: Name, value: Any): Tree = {
- val constant = Constant(value)
- createMethod(name, constant.tpe)(_ => Literal(constant))
- }
- }
-
/** Add the synthetic methods to case classes.
*/
def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = {
if (phase.erasedTypes)
return templ
- val synthesizer = new MethodSynthesis(
+ val synthesizer = new ClassMethodSynthesis(
clazz0,
newTyper( if (reporter.hasErrors) context makeSilent false else context )
)
@@ -212,11 +67,12 @@ trait SyntheticMethods extends ast.TreeDSL {
// like Manifests and Arrays which are not robust and infer things
// which they shouldn't.
val accessorLub = (
- if (opt.experimental)
+ if (opt.experimental) {
global.weakLub(accessors map (_.tpe.finalResultType))._1 match {
case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents)
case tp => tp
}
+ }
else AnyClass.tpe
)
@@ -258,11 +114,10 @@ trait SyntheticMethods extends ast.TreeDSL {
/** The canEqual method for case classes.
* def canEqual(that: Any) = that.isInstanceOf[This]
*/
- def canEqualMethod: Tree = {
- createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m =>
- methodArg(m, 0) IS_OBJ clazzTypeToTest(clazz)
- )
- }
+ def canEqualMethod: Tree = (
+ createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m =>
+ Ident(m.firstParam) IS_OBJ typeCaseType(clazz))
+ )
/** The equality method for case classes.
* 0 args:
@@ -276,8 +131,8 @@ trait SyntheticMethods extends ast.TreeDSL {
* }
*/
def equalsClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m =>
- val arg0 = methodArg(m, 0)
- val thatTest = gen.mkIsInstanceOf(arg0, clazzTypeToTest(clazz), true, false)
+ val arg0 = Ident(m.firstParam)
+ val thatTest = gen.mkIsInstanceOf(arg0, typeCaseType(clazz), true, false)
val thatCast = gen.mkCast(arg0, clazz.tpe)
def argsBody: Tree = {
@@ -331,7 +186,7 @@ trait SyntheticMethods extends ast.TreeDSL {
Object_hashCode -> (() => constantMethod(nme.hashCode_, clazz.name.decode.hashCode)),
Object_toString -> (() => constantMethod(nme.toString_, clazz.name.decode))
// Not needed, as reference equality is the default.
- // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ methodArg(m, 0)))
+ // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ Ident(m.firstParam)))
)
/** If you serialize a singleton and then deserialize it twice,
@@ -381,7 +236,7 @@ trait SyntheticMethods extends ast.TreeDSL {
for (ddef @ DefDef(_, _, _, _, _, _) <- templ.body ; if isRewrite(ddef.symbol)) {
val original = ddef.symbol
val newAcc = deriveMethod(ddef.symbol, name => context.unit.freshTermName(name + "$")) { newAcc =>
- makeMethodPublic(newAcc)
+ newAcc.makePublic
newAcc resetFlag (ACCESSOR | PARAMACCESSOR)
ddef.rhs.duplicate
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index b0500776fe..ed263cbbef 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -142,11 +142,11 @@ abstract class TreeCheckers extends Analyzer {
result
}
def runWithUnit[T](unit: CompilationUnit)(body: => Unit): Unit = {
- val unit0 = currentRun.currentUnit
+ val unit0 = currentUnit
currentRun.currentUnit = unit
body
currentRun.advanceUnit
- assertFn(currentRun.currentUnit == unit, "currentUnit is " + currentRun.currentUnit + ", but unit is " + unit)
+ assertFn(currentUnit == unit, "currentUnit is " + currentUnit + ", but unit is " + unit)
currentRun.currentUnit = unit0
}
def check(unit: CompilationUnit) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index fe3ceafa2d..4f4087a953 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -39,8 +39,6 @@ trait TypeDiagnostics {
import definitions._
import global.typer.{ infer, context }
- private def currentUnit = currentRun.currentUnit
-
/** The common situation of making sure nothing is erroneous could be
* nicer if Symbols, Types, and Trees all implemented some common interface
* in which isErroneous and similar would be placed.
@@ -93,37 +91,6 @@ trait TypeDiagnostics {
}
}
- def notAMemberMessage(pos: Position, qual: Tree, name: Name) = {
- val owner = qual.tpe.typeSymbol
- val target = qual.tpe.widen
- def targetKindString = if (owner.isTypeParameterOrSkolem) "type parameter " else ""
- def nameString = decodeWithKind(name, owner)
- /** Illuminating some common situations and errors a bit further. */
- def addendum = {
- val companion = {
- if (name.isTermName && owner.isPackageClass) {
- target.member(name.toTypeName) match {
- case NoSymbol => ""
- case sym => "\nNote: %s exists, but it has no companion object.".format(sym)
- }
- }
- else ""
- }
- val semicolon = (
- if (posPrecedes(qual.pos, pos))
- "\npossible cause: maybe a semicolon is missing before `"+nameString+"'?"
- else
- ""
- )
- companion + semicolon
- }
-
- withAddendum(qual.pos)(
- if (name == nme.CONSTRUCTOR) target + " does not have a constructor"
- else nameString + " is not a member of " + targetKindString + target + addendum
- )
- }
-
/** An explanatory note to be added to error messages
* when there's a problem with abstract var defs */
def abstractVarMessage(sym: Symbol): String =
@@ -131,9 +98,6 @@ trait TypeDiagnostics {
"\n(Note that variables need to be initialized to be defined)"
else ""
- def notAMemberError(pos: Position, qual: Tree, name: Name) =
- context.error(pos, notAMemberMessage(pos, qual, name))
-
/** Only prints the parameter names if they're not synthetic,
* since "x$1: Int" does not offer any more information than "Int".
*/
@@ -154,21 +118,6 @@ trait TypeDiagnostics {
def alternativesString(tree: Tree) =
alternatives(tree) map (x => " " + methodTypeErrorString(x)) mkString ("", " <and>\n", "\n")
- def missingParameterTypeMsg(fun: Tree, vparam: ValDef, pt: Type) = {
- def anonMessage = (
- "\nThe argument types of an anonymous function must be fully known. (SLS 8.5)" +
- "\nExpected type was: " + pt.toLongString
- )
- val suffix =
- if (!vparam.mods.isSynthetic) ""
- else " for expanded function" + (fun match {
- case Function(_, Match(_, _)) => anonMessage
- case _ => " " + fun
- })
-
- "missing parameter type" + suffix
- }
-
/** The symbol which the given accessor represents (possibly in part).
* This is used for error messages, where we want to speak in terms
* of the actual declaration or definition, not in terms of the generated setters
@@ -202,34 +151,6 @@ trait TypeDiagnostics {
else defaultMessage
}
- def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]): String = {
- val suffix = {
- if (missing.isEmpty) ""
- else {
- val keep = missing take 3 map (_.name)
- ".\nUnspecified value parameter%s %s".format(
- if (missing.tail.isEmpty) "" else "s",
- if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ")
- else keep.mkString("", ", ", ".")
- )
- }
- }
-
- "not enough arguments for " + treeSymTypeMsg(fun) + suffix
- }
-
- def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = {
- def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")")
-
- def resType = if (pt isWildcard) "" else " with expected result type " + pt
- def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt
- def locals = alternatives(tree) flatMap (_.typeParams)
-
- withDisambiguation(locals, allTypes: _*) {
- treeSymTypeMsg(tree) + msg + asParams(argtpes) + resType
- }
- }
-
def disambiguate(ss: List[String]) = ss match {
case Nil => Nil
case s :: ss => s :: (ss map { case `s` => "(some other)"+s ; case x => x })
@@ -446,8 +367,8 @@ trait TypeDiagnostics {
trait TyperDiagnostics {
self: Typer =>
- private def contextError(pos: Position, msg: String) = context.error(pos, msg)
- private def contextError(pos: Position, err: Throwable) = context.error(pos, err)
+ private def contextError(context0: Analyzer#Context, pos: Position, msg: String) = context0.error(pos, msg)
+ private def contextError(context0: Analyzer#Context, pos: Position, err: Throwable) = context0.error(pos, err)
private def contextWarning(pos: Position, msg: String) = context.unit.warning(pos, msg)
def permanentlyHiddenWarning(pos: Position, hidden: Name, defn: Symbol) =
@@ -466,14 +387,8 @@ trait TypeDiagnostics {
// Error suppression will squash some of these warnings unless we circumvent it.
// It is presumed if you are using a -Y option you would really like to hear
// the warnings you've requested.
- if (settings.warnDeadCode.value && context.unit.exists && treeOK(tree) && exprOK) {
- val saved = context.reportGeneralErrors
- try {
- context.reportGeneralErrors = true
- context.warning(tree.pos, "dead code following this construct")
- }
- finally context.reportGeneralErrors = saved
- }
+ if (settings.warnDeadCode.value && context.unit.exists && treeOK(tree) && exprOK)
+ context.warning(tree.pos, "dead code following this construct", true)
tree
}
@@ -485,8 +400,8 @@ trait TypeDiagnostics {
}
}
- def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded
- def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive"
+ private def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded
+ private def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive"
/** Returns Some(msg) if the given tree is untyped apparently due
* to a cyclic reference, and None otherwise.
@@ -500,15 +415,18 @@ trait TypeDiagnostics {
"\nIf applicable, you may wish to try moving some members into another object."
)
}
-
+
/** Report a type error.
*
* @param pos0 The position where to report the error
* @param ex The exception that caused the error
*/
- def reportTypeError(pos: Position, ex: TypeError) {
+ def reportTypeError(context0: Context, pos: Position, ex: TypeError) {
if (ex.pos == NoPosition) ex.pos = pos
- if (!context.reportGeneralErrors) throw ex
+ // TODO: should be replaced by throwErrors
+ // but it seems that throwErrors excludes some of the errors that should actually be
+ // buffered, causing TypeErrors to fly around again. This needs some more investigation.
+ if (!context0.reportErrors) throw ex
if (settings.debug.value) ex.printStackTrace()
ex match {
@@ -517,12 +435,12 @@ trait TypeDiagnostics {
case Import(expr, _) => expr.pos
case _ => ex.pos
}
- contextError(pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
+ contextError(context0, pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
if (sym == ObjectClass)
throw new FatalError("cannot redefine root "+sym)
case _ =>
- contextError(ex.pos, ex)
+ contextError(context0, ex.pos, ex)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 216ad6cd4c..770b55d6ab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -12,14 +12,12 @@
package scala.tools.nsc
package typechecker
-import scala.collection.{ mutable, immutable }
+import scala.collection.mutable
import scala.tools.nsc.util.BatchSourceFile
import mutable.ListBuffer
import symtab.Flags._
import util.Statistics
import util.Statistics._
-import scala.tools.util.StringOps.{ countAsString, countElementsAsString }
-import scala.tools.util.EditDistance.similarString
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -60,7 +58,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
super.traverse(tree)
}
}
-/* needed for experimental version where eraly types can be type arguments
+/* needed for experimental version where early types can be type arguments
class EarlyMap(clazz: Symbol) extends TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(NoPrefix, sym, List()) if (sym hasFlag PRESUPER) =>
@@ -71,6 +69,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
*/
+ sealed abstract class SilentResult[+T]
+ case class SilentTypeError(err: AbsTypeError) extends SilentResult[Nothing] { }
+ case class SilentResultValue[+T](value: T) extends SilentResult[T] { }
+
def newTyper(context: Context): Typer = new NormalTyper(context)
private class NormalTyper(context : Context) extends Typer(context)
@@ -80,9 +82,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
private def isPastTyper = phase.id > currentRun.typerPhase.id
- abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation {
+ abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with TyperContextErrors {
import context0.unit
import typeDebug.{ ptTree, ptBlock, ptLine }
+ import TyperErrorGen._
val infer = new Inferencer(context0) {
override def isCoercible(tp: Type, pt: Type): Boolean = undoLog undo { // #3281
@@ -102,15 +105,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def mkNamedArg(argTree: Tree, paramName: Name) = atPos(argTree.pos)(new AssignOrNamedArg(Ident(paramName), (argTree)))
var mkArg: (Tree, Name) => Tree = mkPositionalArg
- def errorMessage(paramName: Name, paramTp: Type) =
- paramTp.typeSymbol match {
- case ImplicitNotFoundMsg(msg) => msg.format(paramName, paramTp)
- case _ =>
- "could not find implicit value for "+
- (if (paramName startsWith nme.EVIDENCE_PARAM_PREFIX) "evidence parameter of type "
- else "parameter "+paramName+": ")+paramTp
- }
-
// DEPMETTODO: instantiate type vars that depend on earlier implicit args (see adapt (4.1))
//
// apply the substitutions (undet type param -> type) that were determined
@@ -127,8 +121,19 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
argBuff += mkArg(res.tree, param.name)
} else {
mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
- if (!param.hasDefault)
- context.error(fun.pos, errorMessage(param.name, param.tpe))
+ if (!param.hasDefault) {
+ context.errBuffer.find(_.kind == ErrorKinds.Divergent) match {
+ case Some(divergentImplicit) =>
+ // DivergentImplicit error has higher priority than "no implicit found"
+ // no need to issue the problem again if we are still in silent mode
+ if (context.reportErrors) {
+ context.issue(divergentImplicit)
+ context.condBufferFlush(_.kind == ErrorKinds.Divergent)
+ }
+ case None =>
+ NoImplicitFoundError(fun, param)
+ }
+ }
/* else {
TODO: alternative (to expose implicit search failure more) -->
resolve argument, do type inference, keep emitting positional args, infer type params based on default value for arg
@@ -149,6 +154,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case ErrorType =>
fun
}
+
+ def inferView(tree: Tree, from: Type, to: Type, reportAmbiguous: Boolean): Tree =
+ inferView(tree, from, to, reportAmbiguous, true)
/** Infer an implicit conversion (``view'') between two types.
* @param tree The tree which needs to be converted.
@@ -157,8 +165,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* @param reportAmbiguous Should ambiguous implicit errors be reported?
* False iff we search for a view to find out
* whether one type is coercible to another.
+ * @param saveErrors Should ambiguous and divergent implicit errors that were buffered
+ * during the inference of a view be put into the original buffer.
+ * False iff we don't care about them.
*/
- def inferView(tree: Tree, from: Type, to: Type, reportAmbiguous: Boolean): Tree = {
+ def inferView(tree: Tree, from: Type, to: Type, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
debuglog("infer view from "+from+" to "+to)//debug
if (isPastTyper) EmptyTree
else from match {
@@ -167,7 +178,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case PolyType(_, _) => EmptyTree
case _ =>
def wrapImplicit(from: Type): Tree = {
- val result = inferImplicit(tree, functionType(List(from), to), reportAmbiguous, true, context)
+ val result = inferImplicit(tree, functionType(List(from), to), reportAmbiguous, true, context, saveErrors)
if (result.subst != EmptyTreeTypeSubstituter) result.subst traverse tree
result.tree
}
@@ -205,22 +216,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* @return ...
*/
def checkStable(tree: Tree): Tree =
- if (treeInfo.isExprSafeToInline(tree)) tree
- else errorTree(
- tree,
- "stable identifier required, but "+tree+" found."+
- (if (isStableExceptVolatile(tree)) {
- val tpe = tree.symbol.tpe match {
- case PolyType(_, rtpe) => rtpe
- case t => t
- }
- "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile."
- } else ""))
+ if (treeInfo.isExprSafeToInline(tree)) tree else UnstableTreeError(tree)
/** Would tree be a stable (i.e. a pure expression) if the type
* of its symbol was not volatile?
*/
- private def isStableExceptVolatile(tree: Tree) = {
+ protected def isStableExceptVolatile(tree: Tree) = {
tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
{ val savedTpe = tree.symbol.info
val savedSTABLE = tree.symbol getFlag STABLE
@@ -234,21 +235,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
/** Check that `tpt` refers to a non-refinement class type */
- def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean) {
- def errorNotClass(found: AnyRef) = error(tpt.pos, "class type required but "+found+" found")
- def check(tpe: Type): Unit = tpe.normalize match {
+ def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean): Boolean = {
+ def errorNotClass(found: AnyRef) = { ClassTypeRequiredError(tpt, found); false }
+ def check(tpe: Type): Boolean = tpe.normalize match {
case TypeRef(pre, sym, _) if sym.isClass && !sym.isRefinementClass =>
- if (stablePrefix && !isPastTyper) {
- if (!pre.isStable)
- error(tpt.pos, "type "+pre+" is not a stable prefix")
- // A type projection like X#Y can get by the stable check if the
- // prefix is singleton-bounded, so peek at the tree too.
- else tpt match {
+ if (stablePrefix && !isPastTyper)
+ if (!pre.isStable) {
+ TypeNotAStablePrefixError(tpt, pre)
+ false
+ } else
+ // A type projection like X#Y can get by the stable check if the
+ // prefix is singleton-bounded, so peek at the tree too.
+ tpt match {
case SelectFromTypeTree(qual, _) if !isSingleType(qual.tpe) => errorNotClass(tpt)
- case _ => ;
- }
- }
- case ErrorType => ;
+ case _ => true
+ }
+ else
+ true
+ case ErrorType => true
case PolyType(_, restpe) => check(restpe)
case ExistentialType(_, restpe) if existentialOK => check(restpe)
case AnnotatedType(_, underlying, _) => check(underlying)
@@ -264,17 +268,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* @return <code>true</code> if <code>tp</code> is not a subtype of itself.
*/
def checkNonCyclic(pos: Position, tp: Type): Boolean = {
- def checkNotLocked(sym: Symbol): Boolean = {
+ def checkNotLocked(sym: Symbol) = {
sym.initialize
- sym.lockOK || {error(pos, "cyclic aliasing or subtyping involving "+sym); false}
+ sym.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false }
}
tp match {
case TypeRef(pre, sym, args) =>
- (checkNotLocked(sym)) && (
- !sym.isNonClassType ||
- checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym) // @M! info for a type ref to a type parameter now returns a polytype
- // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym)
- )
+ checkNotLocked(sym) &&
+ ((!sym.isNonClassType) || checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym))
+ // @M! info for a type ref to a type parameter now returns a polytype
+ // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym)
+
case SingleType(pre, sym) =>
checkNotLocked(sym)
/*
@@ -293,10 +297,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Boolean = try {
- lockedSym.lock {
- throw new TypeError("illegal cyclic reference involving " + lockedSym)
- }
- checkNonCyclic(pos, tp)
+ if (!lockedSym.lock(CyclicReferenceError(pos, lockedSym))) false
+ else checkNonCyclic(pos, tp)
} finally {
lockedSym.unlock()
}
@@ -312,26 +314,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- def checkParamsConvertible(pos: Position, tpe: Type) {
- tpe match {
- case MethodType(formals, restpe) =>
- /*
- if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
- error(pos, "methods with `=>`-parameter can be converted to function values only if they take no other parameters")
- if (formals exists (isRepeatedParamType(_)))
- error(pos, "methods with `*`-parameters cannot be converted to function values");
- */
- if (restpe.isDependent)
- error(pos, "method with dependent type "+tpe+" cannot be converted to function value")
- checkParamsConvertible(pos, restpe)
- case _ =>
- }
+ def checkParamsConvertible(tree: Tree, tpe0: Type) {
+ def checkParamsConvertible0(tpe: Type) =
+ tpe match {
+ case MethodType(formals, restpe) =>
+ /*
+ if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
+ error(pos, "methods with `=>`-parameter can be converted to function values only if they take no other parameters")
+ if (formals exists (isRepeatedParamType(_)))
+ error(pos, "methods with `*`-parameters cannot be converted to function values");
+ */
+ if (restpe.isDependent)
+ DependentMethodTpeConversionToFunctionError(tree, tpe)
+ checkParamsConvertible(tree, restpe)
+ case _ =>
+ }
+ checkParamsConvertible0(tpe0)
}
- def checkStarPatOK(pos: Position, mode: Int) =
- if ((mode & STARmode) == 0 && !isPastTyper)
- error(pos, "star patterns must correspond with varargs parameters")
-
/** Check that type of given tree does not contain local or private
* components.
*/
@@ -362,13 +362,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def locals[T <: Tree](scope: Scope, pt: Type, tree: T): T =
check(NoSymbol, scope, pt, tree)
- def check[T <: Tree](owner: Symbol, scope: Scope, pt: Type, tree: T): T = {
+ private def check[T <: Tree](owner: Symbol, scope: Scope, pt: Type, tree: T): T = {
this.owner = owner
this.scope = scope
hiddenSymbols = List()
val tp1 = apply(tree.tpe)
if (hiddenSymbols.isEmpty) tree setType tp1
- else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
+ else if (hiddenSymbols exists (_.isErroneous)) HiddenSymbolWithError(tree)
else if (isFullyDefined(pt)) tree setType pt
else if (tp1.typeSymbol.isAnonymousClass)
check(owner, scope, pt, tree setType tp1.typeSymbol.classBound)
@@ -376,10 +376,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
tree setType packSymbols(hiddenSymbols.reverse, tp1)
else if (!phase.erasedTypes) { // privates
val badSymbol = hiddenSymbols.head
- error(tree.pos,
- (if (badSymbol.isPrivate) "private " else "") + badSymbol +
- " escapes its defining scope as part of type "+tree.tpe)
- setError(tree)
+ SymbolEscapesScopeError(tree, badSymbol)
} else tree
}
@@ -441,28 +438,66 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
/** The qualifying class
* of a this or super with prefix <code>qual</code>.
+ * packageOk is equal false when qualifying class symbol
*/
- def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean): Symbol =
+ def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean = false): Option[Symbol] =
context.enclClass.owner.ownerChain.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
case Some(c) if packageOK || !c.isPackageClass =>
- c
+ Some(c)
case _ =>
- error(
- tree.pos,
- if (qual.isEmpty) tree+" can be used only in a class, object, or template"
- else qual+" is not an enclosing class")
- NoSymbol
+ QualifyingClassError(tree, qual)
+ None
}
/** The typer for an expression, depending on where we are. If we are before a superclass
* call, this is a typer over a constructor context; otherwise it is the current typer.
*/
- def constrTyperIf(inConstr: Boolean): Typer =
+ @inline
+ final def constrTyperIf(inConstr: Boolean): Typer =
if (inConstr) {
- assert(context.undetparams.isEmpty)
+ assert(context.undetparams.isEmpty, context.undetparams)
newTyper(context.makeConstructorContext)
} else this
+ @inline
+ final def withCondConstrTyper[T](inConstr: Boolean)(f: Typer => T): T =
+ if (inConstr) {
+ assert(context.undetparams.isEmpty, context.undetparams)
+ val c = context.makeConstructorContext
+ typerWithLocalContext(c)(f)
+ } else {
+ f(this)
+ }
+
+ @inline
+ final def typerWithCondLocalContext[T](c: => Context)(cond: Boolean)(f: Typer => T): T =
+ if (cond) typerWithLocalContext(c)(f) else f(this)
+
+ @inline
+ final def typerWithLocalContext[T](c: Context)(f: Typer => T): T = {
+ val res = f(newTyper(c))
+ if (c.hasErrors)
+ context.updateBuffer(c.flushAndReturnBuffer())
+ res
+ }
+
+ @inline
+ final def typerReportAnyContextErrors[T](c: Context)(f: Typer => T): T = {
+ val res = f(newTyper(c))
+ if (c.hasErrors)
+ context.issue(c.errBuffer.head)
+ res
+ }
+
+ @inline
+ final def withSavedContext[T](c: Context)(f: => T) = {
+ val savedErrors = c.flushAndReturnBuffer()
+ val res = f
+ c.updateBuffer(savedErrors)
+ res
+ }
+
+
/** The typer for a label definition. If this is part of a template we
* first have to enter the label definition.
*/
@@ -573,9 +608,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
inferExprAlternative(tree, pt)
val sym = tree.symbol
- def fail() = errorTree(tree, sym.kindString + " " + sym.fullName + " is not a value")
+ def fail() = NotAValueError(tree, sym)
- if (tree.tpe.isError) tree
+ if (tree.isErrorTyped) tree
else if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) { // (1)
if (sym.isValue) checkStable(tree)
else fail()
@@ -629,15 +664,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def silent[T](op: Typer => T,
- reportAmbiguousErrors: Boolean = context.reportAmbiguousErrors,
- newtree: Tree = context.tree): Any /* in fact, TypeError or T */ = {
+ reportAmbiguousErrors: Boolean = context.ambiguousErrors,
+ newtree: Tree = context.tree): SilentResult[T] = {
val rawTypeStart = startCounter(rawTypeFailed)
val findMemberStart = startCounter(findMemberFailed)
val subtypeStart = startCounter(subtypeFailed)
val failedSilentStart = startTimer(failedSilentNanos)
try {
- if (context.reportGeneralErrors ||
- reportAmbiguousErrors != context.reportAmbiguousErrors ||
+ if (context.reportErrors ||
+ reportAmbiguousErrors != context.ambiguousErrors ||
newtree != context.tree) {
val context1 = context.makeSilent(reportAmbiguousErrors, newtree)
context1.undetparams = context.undetparams
@@ -648,38 +683,29 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
context.undetparams = context1.undetparams
context.savedTypeBounds = context1.savedTypeBounds
context.namedApplyBlockInfo = context1.namedApplyBlockInfo
- result
+ if (context1.hasErrors) SilentTypeError(context1.errBuffer.head)
+ else SilentResultValue(result)
} else {
- op(this)
+ assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
+ withSavedContext(context){
+ val res = op(this)
+ val errorsToReport = context.flushAndReturnBuffer()
+ if (errorsToReport.isEmpty) SilentResultValue(res) else SilentTypeError(errorsToReport.head)
+ }
}
} catch {
case ex: CyclicReference => throw ex
case ex: TypeError =>
+ // fallback in case TypeError is still thrown
+ // @H this happens for example in cps annotation checker
stopCounter(rawTypeFailed, rawTypeStart)
stopCounter(findMemberFailed, findMemberStart)
stopCounter(subtypeFailed, subtypeStart)
stopTimer(failedSilentNanos, failedSilentStart)
- ex
+ SilentTypeError(TypeErrorWrapper(ex))
}
}
- /** Utility method: Try op1 on tree. If that gives an error try op2 instead.
- */
- def tryBoth(tree: Tree)(op1: (Typer, Tree) => Tree)(op2: (Typer, Tree) => Tree): Tree =
- silent(op1(_, tree)) match {
- case result1: Tree =>
- result1
- case ex1: TypeError =>
- silent(op2(_, resetAllAttrs(tree))) match {
- case result2: Tree =>
-// println("snd succeeded: "+result2)
- result2
- case ex2: TypeError =>
- reportTypeError(tree.pos, ex1)
- setError(tree)
- }
- }
-
def isCodeType(tpe: Type) = tpe.typeSymbol isNonBottomSubClass CodeClass
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
@@ -724,8 +750,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (context.undetparams nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0`
// dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed
// needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition?
- context.undetparams =
- inferExprInstance(tree, context.extractUndetparams(), pt,
+ context.undetparams = inferExprInstance(tree, context.extractUndetparams(), pt,
// approximate types that depend on arguments since dependency on implicit argument is like dependency on type parameter
mt.approximate,
// if we are looking for a manifest, instantiate type to Nothing anyway,
@@ -736,18 +761,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
useWeaklyCompatible = true) // #3808
}
- val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree))
- if (original != EmptyTree && pt != WildcardType)
- typer1.silent(tpr => tpr.typed(tpr.applyImplicitArgs(tree), mode, pt)) match {
- case result: Tree => result
- case ex: TypeError =>
- debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original))
- val tree1 = typed(resetAllAttrs(original), mode, WildcardType)
- tree1.tpe = addAnnotations(tree1, tree1.tpe)
- if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, EmptyTree)
- }
- else
- typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
+ // avoid throwing spurious DivergentImplicit errors
+ if (context.hasErrors)
+ return setError(tree)
+
+ withCondConstrTyper(treeInfo.isSelfOrSuperConstrCall(tree)){ typer1 =>
+ if (original != EmptyTree && pt != WildcardType)
+ typer1.silent(tpr => tpr.typed(tpr.applyImplicitArgs(tree), mode, pt)) match {
+ case SilentResultValue(result) =>
+ result
+ case _ =>
+ debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original))
+ val tree1 = typed(resetAllAttrs(original), mode, WildcardType)
+ tree1.tpe = addAnnotations(tree1, tree1.tpe)
+ if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, EmptyTree)
+ }
+ else
+ typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
+ }
}
def instantiateToMethodType(mt: MethodType): Tree = {
@@ -758,7 +789,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
if (!meth.isConstructor && !meth.isMacro && isFunctionType(pt)) { // (4.2)
debuglog("eta-expanding " + tree + ":" + tree.tpe + " to " + pt)
- checkParamsConvertible(tree.pos, tree.tpe)
+ checkParamsConvertible(tree, tree.tpe)
val tree0 = etaExpand(context.unit, tree)
// println("eta "+tree+" ---> "+tree0+":"+tree0.tpe+" undet: "+context.undetparams+ " mode: "+Integer.toHexString(mode))
@@ -775,9 +806,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
} else if (!meth.isConstructor && mt.params.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt, original)
} else if (context.implicitsEnabled) {
- errorTree(tree, "missing arguments for " + meth + meth.locationString +
- (if (meth.isConstructor) ""
- else ";\nfollow this method with `_' if you want to treat it as a partially applied function"))
+ MissingArgsForMethodTpeError(tree, meth)
} else {
setError(tree)
}
@@ -792,8 +821,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *,
// and thus parameterized types must be applied to their type arguments
// @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
- errorTree(tree, tree.symbol + " takes type parameters")
- tree setType tree.tpe
+ MissingTypeParametersError(tree)
} else if ( // (7.1) @M: check kind-arity
// @M: removed check for tree.hasSymbol and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
(inHKMode(mode)) &&
@@ -808,9 +836,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// Note that we treat Any and Nothing as kind-polymorphic.
// We can't perform this check when typing type arguments to an overloaded method before the overload is resolved
// (or in the case of an error type) -- this is indicated by pt == WildcardType (see case TypeApply in typed1).
- errorTree(tree, tree.tpe + " takes " + countElementsAsString(tree.tpe.typeParams.length, "type parameter") +
- ", expected: " + countAsString(pt.typeParams.length))
- tree setType tree.tpe
+ KindArityMismatchError(tree, pt)
} else tree match { // (6)
case TypeTree() => tree
case _ => TypeTree(tree.tpe) setOriginal (tree) setPos (tree.pos)
@@ -836,12 +862,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
tree
}
} else {
- errorTree(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method")
+ CaseClassConstructorError(tree)
}
}
def insertApply(): Tree = {
- assert(!inHKMode(mode)) //@M
+ assert(!inHKMode(mode), modeString(mode)) //@M
val qual = adaptToName(tree, nme.apply) match {
case id @ Ident(_) =>
val pre = if (id.symbol.owner.isPackageClass) id.symbol.owner.thisType
@@ -922,7 +948,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
applyPossible)
insertApply()
else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9)
- assert(!inHKMode(mode)) //@M
+ assert(!inHKMode(mode), modeString(mode)) //@M
if (inExprModeButNot(mode, FUNmode) && pt.typeSymbol == UnitClass)
instantiateExpectingUnit(tree, mode)
else
@@ -960,7 +986,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (!context.undetparams.isEmpty) {
return instantiate(tree, mode, pt)
}
- if (context.implicitsEnabled && !tree.tpe.isError && !pt.isError) {
+ if (context.implicitsEnabled && !pt.isError && !tree.isErrorTyped) {
// (14); the condition prevents chains of views
debuglog("inferring view from " + tree.tpe + " to " + pt)
val coercion = inferView(tree, tree.tpe, pt, true)
@@ -977,8 +1003,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
unit.echo(tree.pos, msg)
debuglog(msg)
- return newTyper(context.makeImplicit(context.reportAmbiguousErrors)).typed(
+ val silentContext = context.makeImplicit(context.ambiguousErrors)
+ val res = newTyper(silentContext).typed(
new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt)
+ if (silentContext.hasErrors) context.issue(silentContext.errBuffer.head) else return res
}
}
}
@@ -986,31 +1014,34 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
log("error tree = " + tree)
if (settings.explaintypes.value) explainTypes(tree.tpe, pt)
}
- try {
- typeErrorTree(tree, tree.tpe, pt)
- } catch {
- case ex: TypeError =>
- if (isPastTyper && pt.existentialSkolems.nonEmpty) {
- // Ignore type errors raised in later phases that are due to mismatching types with existential skolems
- // We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
- // Here's my hypothsis why this happens. The pattern matcher defines a variable of type
- //
- // val x: T = expr
- //
- // where T is the type of expr, but T contains existential skolems ts.
- // In that case, this value definition does not typecheck.
- // The value definition
- //
- // val x: T forSome { ts } = expr
- //
- // would typecheck. Or one can simply leave out the type of the `val`:
- //
- // val x = expr
- context.unit.warning(tree.pos, "recovering from existential Skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
- adapt(tree, mode, deriveTypeWithWildcards(pt.existentialSkolems)(pt))
- } else
- throw ex
+
+ val found = tree.tpe
+ val req = pt
+ if (!found.isErroneous && !req.isErroneous) {
+ if (!context.reportErrors && isPastTyper && req.existentialSkolems.nonEmpty) {
+ // Ignore type errors raised in later phases that are due to mismatching types with existential skolems
+ // We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
+ // Here's my hypothsis why this happens. The pattern matcher defines a variable of type
+ //
+ // val x: T = expr
+ //
+ // where T is the type of expr, but T contains existential skolems ts.
+ // In that case, this value definition does not typecheck.
+ // The value definition
+ //
+ // val x: T forSome { ts } = expr
+ //
+ // would typecheck. Or one can simply leave out the type of the `val`:
+ //
+ // val x = expr
+ context.unit.warning(tree.pos, "recovering from existential Skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
+ adapt(tree, mode, deriveTypeWithWildcards(pt.existentialSkolems)(pt))
+ } else {
+ // create an actual error
+ AdaptTypeError(tree, found, req)
+ }
}
+ setError(tree)
}
}
}
@@ -1027,7 +1058,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def instantiateExpectingUnit(tree: Tree, mode: Int): Tree = {
val savedUndetparams = context.undetparams
silent(_.instantiate(tree, mode, UnitClass.tpe)) match {
- case t: Tree => t
+ case SilentResultValue(t) => t
case _ =>
context.undetparams = savedUndetparams
val valueDiscard = atPos(tree.pos)(Block(List(instantiate(tree, mode, WildcardType)), Literal(Constant())))
@@ -1053,15 +1084,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// Note: implicit arguments are still inferred (this kind of "chaining" is allowed)
)
}
+
+ def adaptToMember(qual: Tree, searchTemplate: Type): Tree =
+ adaptToMember(qual, searchTemplate, true, true)
+ def adaptToMember(qual: Tree, searchTemplate: Type, reportAmbiguous: Boolean): Tree =
+ adaptToMember(qual, searchTemplate, reportAmbiguous, true)
- def adaptToMember(qual: Tree, searchTemplate: Type): Tree = {
+ def adaptToMember(qual: Tree, searchTemplate: Type, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
if (isAdaptableWithView(qual)) {
qual.tpe.widen.normalize match {
case et: ExistentialType =>
qual setType et.skolemizeExistential(context.owner, qual) // open the existential
case _ =>
}
- inferView(qual, qual.tpe, searchTemplate, true) match {
+ inferView(qual, qual.tpe, searchTemplate, reportAmbiguous, saveErrors) match {
case EmptyTree => qual
case coercion =>
if (settings.logImplicitConv.value)
@@ -1083,13 +1119,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* If no conversion is found, return `qual` unchanged.
*
*/
- def adaptToArguments(qual: Tree, name: Name, args: List[Tree], pt: Type): Tree = {
+ def adaptToArguments(qual: Tree, name: Name, args: List[Tree], pt: Type, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
def doAdapt(restpe: Type) =
//util.trace("adaptToArgs "+qual+", name = "+name+", argtpes = "+(args map (_.tpe))+", pt = "+pt+" = ")
- adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), restpe))
+ adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), restpe), reportAmbiguous, saveErrors)
if (pt != WildcardType) {
silent(_ => doAdapt(pt)) match {
- case result: Tree if result != qual =>
+ case SilentResultValue(result) if result != qual =>
result
case _ =>
debuglog("fallback on implicits in adaptToArguments: "+qual+" . "+name)
@@ -1099,30 +1135,32 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
doAdapt(pt)
}
- /** Try o apply an implicit conversion to `qual` to that it contains
- * a method `name`. If that's ambiguous try taking arguments into account using `adaptToArguments`.
+ /** Try to apply an implicit conversion to `qual` so that it contains
+ * a method `name`. If that's ambiguous try taking arguments into
+ * account using `adaptToArguments`.
*/
- def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int): Tree = {
- try {
- adaptToMember(qual, HasMember(name))
- } catch {
- case ex: TypeError =>
- // this happens if implicits are ambiguous; try again with more context info.
- // println("last ditch effort: "+qual+" . "+name)
+ def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
+ def onError(reportError: => Tree): Tree = {
context.tree match {
- case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => // try handling the arguments
- // println("typing args: "+args)
+ case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty =>
silent(_.typedArgs(args, mode)) match {
- case args: List[_] =>
- adaptToArguments(qual, name, args.asInstanceOf[List[Tree]], WildcardType)
- case _ =>
- throw ex
+ case SilentResultValue(xs) =>
+ val args = xs.asInstanceOf[List[Tree]]
+ if (args exists (_.isErrorTyped))
+ reportError
+ else
+ adaptToArguments(qual, name, args, WildcardType, reportAmbiguous, saveErrors)
+ case _ =>
+ reportError
}
case _ =>
- // println("not in an apply: "+context.tree+"/"+tree)
- throw ex
+ reportError
}
}
+ silent(_.adaptToMember(qual, HasMember(name), false)) match {
+ case SilentResultValue(res) => res
+ case SilentTypeError(err) => onError({if (reportAmbiguous) { context.issue(err) }; setError(tree)})
+ }
}
/** Try to apply an implicit conversion to `qual` to that it contains a
@@ -1162,7 +1200,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// If first parent is a trait, make it first mixin and add its superclass as first parent
while ((supertpt.tpe.typeSymbol ne null) && supertpt.tpe.typeSymbol.initialize.isTrait) {
val supertpt1 = typedType(supertpt)
- if (!supertpt1.tpe.isError) {
+ if (!supertpt1.isErrorTyped) {
mixins = supertpt1 :: mixins
supertpt = TypeTree(supertpt1.tpe.parents.head) setPos supertpt.pos.focus
}
@@ -1201,19 +1239,22 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
})
val outercontext = context.outer
- assert(clazz != NoSymbol)
+ assert(clazz != NoSymbol, templ)
val cscope = outercontext.makeNewScope(constr, outercontext.owner)
val cbody2 = newTyper(cscope) // called both during completion AND typing.
.typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
+
superCall match {
case Apply(_, _) =>
val sarg = treeInfo.firstArgument(superCall)
if (sarg != EmptyTree && supertpe.typeSymbol != firstParent)
- error(sarg.pos, firstParent+" is a trait; does not take constructor arguments")
- if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus
+ ConstrArgsInTraitParentTpeError(sarg, firstParent)
+ if (!supertparams.isEmpty)
+ supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus
case _ =>
- if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
+ if (!supertparams.isEmpty)
+ MissingTypeArgumentsParentTpeError(supertpt)
}
val preSuperVals = treeInfo.preSuperFields(templ.body)
@@ -1223,7 +1264,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe)
case _ =>
- if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
+ if (!supertparams.isEmpty)
+ MissingTypeArgumentsParentTpeError(supertpt)
}
/* experimental: early types as type arguments
val hasEarlyTypes = templ.body exists (treeInfo.isEarlyTypeDef)
@@ -1256,8 +1298,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
catch {
case ex: TypeError =>
- templ.tpe = null
- reportTypeError(templ.pos, ex)
+ // fallback in case of cyclic errors
+ // @H none of the tests enter here but I couldn't rule it out
+ ParentTypesError(templ, ex)
List(TypeTree(AnyRefClass.tpe))
}
@@ -1276,30 +1319,29 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* </ul>
*/
def validateParentClasses(parents: List[Tree], selfType: Type) {
+ val pending = ListBuffer[AbsTypeError]()
def validateParentClass(parent: Tree, superclazz: Symbol) {
- if (!parent.tpe.isError) {
+ if (!parent.isErrorTyped) {
val psym = parent.tpe.typeSymbol.initialize
checkClassType(parent, false, true)
if (psym != superclazz) {
if (psym.isTrait) {
val ps = psym.info.parents
if (!ps.isEmpty && !superclazz.isSubClass(ps.head.typeSymbol))
- error(parent.pos, "illegal inheritance; super"+superclazz+
- "\n is not a subclass of the super"+ps.head.typeSymbol+
- "\n of the mixin " + psym)
+ pending += ParentSuperSubclassError(parent, superclazz, ps.head.typeSymbol, psym)
} else {
- error(parent.pos, psym+" needs to be a trait to be mixed in")
+ pending += ParentNotATraitMixinError(parent, psym)
}
}
- if (psym.isFinal) {
- error(parent.pos, "illegal inheritance from final "+psym)
- }
+ if (psym.isFinal)
+ pending += ParentFinalInheritanceError(parent, psym)
+
if (psym.isSealed && !phase.erasedTypes) {
// AnyVal is sealed, but we have to let the value classes through manually
if (context.unit.source.file == psym.sourceFile || isValueClass(context.owner))
psym addChild context.owner
else
- error(parent.pos, "illegal inheritance from sealed "+psym+": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath)
+ pending += ParentSealedInheritanceError(parent, psym)
}
if (!(selfType <:< parent.tpe.typeOfThis) &&
!phase.erasedTypes &&
@@ -1311,17 +1353,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
//Console.println(List.fromArray(context.owner.info.closure));//DEBUG
- error(parent.pos, "illegal inheritance;\n self-type "+
- selfType+" does not conform to "+parent +
- "'s selftype "+parent.tpe.typeOfThis)
+ pending += ParentSelfTypeConformanceError(parent, selfType)
if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
}
if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
- error(parent.pos, psym+" is inherited twice")
+ pending += ParentInheritedTwiceError(parent, psym)
}
}
-
- if (!parents.isEmpty && !parents.head.tpe.isError)
+ if (!parents.isEmpty && parents.forall(!_.isErrorTyped))
for (p <- parents) validateParentClass(p, parents.head.tpe.typeSymbol)
/*
@@ -1331,13 +1370,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
", baseclasses = "+(context.owner.info.baseClasses map (_.fullName))+
", lin = "+(context.owner.info.baseClasses map (context.owner.thisType.baseType)))
*/
+ pending.foreach(ErrorUtils.issueTypeError)
}
def checkFinitary(classinfo: ClassInfoType) {
val clazz = classinfo.typeSymbol
+
for (tparam <- clazz.typeParams) {
if (classinfo.expansiveRefs(tparam) contains tparam) {
- error(tparam.pos, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive")
val newinfo = ClassInfoType(
classinfo.parents map (_.instantiateTypeParams(List(tparam), List(AnyRefClass.tpe))),
classinfo.decls,
@@ -1348,6 +1388,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case _ => newinfo
}
}
+ FinitaryError(tparam)
}
}
}
@@ -1360,11 +1401,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// attributes(cdef)
val clazz = cdef.symbol
val typedMods = removeAnnotations(cdef.mods)
- assert(clazz != NoSymbol)
+ assert(clazz != NoSymbol, cdef)
reenterTypeParams(cdef.tparams)
val tparams1 = cdef.tparams mapConserve (typedTypeDef)
- val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope))
- .typedTemplate(cdef.impl, parentTypes(cdef.impl))
+ val impl1 = typerReportAnyContextErrors(context.make(cdef.impl, clazz, newScope)) {
+ _.typedTemplate(cdef.impl, parentTypes(cdef.impl))
+ }
val impl2 = finishMethodSynthesis(impl1, clazz, context)
if ((clazz != ClassfileAnnotationClass) &&
(clazz isNonBottomSubClass ClassfileAnnotationClass))
@@ -1397,17 +1439,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val clazz = mdef.symbol.moduleClass
val typedMods = removeAnnotations(mdef.mods)
assert(clazz != NoSymbol, mdef)
-
- val typer0 = newTyper(context.make(mdef.impl, clazz, new Scope))
- val impl1 = typer0.typedTemplate(mdef.impl, {
- parentTypes(mdef.impl) ++ (
- if (linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) Nil
- else {
- clazz.makeSerializable()
- List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus)
- }
- )
- })
+ val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, newScope)) {
+ _.typedTemplate(mdef.impl, {
+ parentTypes(mdef.impl) ++ (
+ if (linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) Nil
+ else {
+ clazz.makeSerializable()
+ List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus)
+ }
+ )
+ })
+ }
val impl2 = finishMethodSynthesis(impl1, clazz, context)
treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
@@ -1516,14 +1558,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (sym.hasAnnotation(definitions.VolatileAttr)) {
if (!sym.isMutable)
- error(vdef.pos, "values cannot be volatile")
+ VolatileValueError(vdef)
else if (sym.isFinal)
- error(vdef.pos, "final vars cannot be volatile")
+ FinalVolatileVarError(vdef)
}
val rhs1 =
if (vdef.rhs.isEmpty) {
if (sym.isVariable && sym.owner.isTerm && !isPastTyper)
- error(vdef.pos, "local variables must be initialized")
+ LocalVarUninitializedError(vdef)
vdef.rhs
} else {
val tpt2 = if (sym.hasDefault) {
@@ -1569,18 +1611,19 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(call, List())
}
val (superConstr, superArgs) = decompose(rhs)
- assert(superConstr.symbol ne null)//debug
+ assert(superConstr.symbol ne null, superConstr)//debug
+ val pending = ListBuffer[AbsTypeError]()
// an object cannot be allowed to pass a reference to itself to a superconstructor
// because of initialization issues; bug #473
for (arg <- superArgs ; tree <- arg) {
val sym = tree.symbol
if (sym != null && (sym.info.baseClasses contains clazz)) {
if (sym.isModule)
- error(tree.pos, "super constructor cannot be passed a self reference unless parameter is declared by-name")
+ pending += SuperConstrReferenceError(tree)
tree match {
case This(qual) =>
- error(tree.pos, "super constructor arguments cannot reference unconstructed `this`")
+ pending += SuperConstrArgsThisReferenceError(tree)
case _ => ()
}
}
@@ -1613,6 +1656,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
}
+ pending.foreach(ErrorUtils.issueTypeError)
}
/** Check if a structurally defined method violates implementation restrictions.
@@ -1661,7 +1705,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
lookupVariable(name.toString.substring(1), enclClass) match {
case Some(repl) =>
silent(_.typedTypeConstructor(stringParser(repl).typ())) match {
- case tpt: Tree =>
+ case SilentResultValue(tpt) =>
val alias = enclClass.newAliasType(name.toTypeName, useCase.pos)
val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias)
alias setInfo typeFun(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
@@ -1711,7 +1755,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
if (isRepeatedParamType(vparam1.symbol.tpe))
- error(vparam1.pos, "*-parameter must come last")
+ StarParamNotLastError(vparam1)
var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt))
checkNonCyclic(ddef, tpt1)
@@ -1723,7 +1767,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(!meth.owner.isClass ||
meth.owner.isModuleClass ||
meth.owner.isAnonOrRefinementClass))
- error(ddef.pos, "constructor definition not allowed here")
+ InvalidConstructorDefError(ddef)
typed(ddef.rhs)
} else if (meth.isMacro) {
EmptyTree
@@ -1738,30 +1782,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (!isPastTyper && meth.owner.isClass &&
meth.paramss.exists(ps => ps.exists(_.hasDefaultFlag) && isRepeatedParamType(ps.last.tpe)))
- error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
+ StarWithDefaultError(meth)
if (!isPastTyper) {
val allParams = meth.paramss.flatten
for (p <- allParams) {
for (n <- p.deprecatedParamName) {
if (allParams.exists(p1 => p1.name == n || (p != p1 && p1.deprecatedParamName.exists(_ == n))))
- error(p.pos, "deprecated parameter name "+ n +" has to be distinct from any other parameter name (deprecated or not).")
+ DeprecatedParamNameError(p, n)
}
}
}
if (meth.isStructuralRefinementMember)
checkMethodStructuralCompatible(meth)
-
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
- def typedTypeDef(tdef: TypeDef): TypeDef = {
- def typeDefTyper = {
- if(tdef.tparams isEmpty) Typer.this
- else newTyper(context.makeNewScope(tdef, tdef.symbol))
+ def typedTypeDef(tdef: TypeDef): TypeDef =
+ typerWithCondLocalContext(context.makeNewScope(tdef, tdef.symbol))(tdef.tparams.nonEmpty){
+ _.typedTypeDef0(tdef)
}
- typeDefTyper.typedTypeDef0(tdef)
- }
// call typedTypeDef instead
// a TypeDef with type parameters must always be type checked in a new scope
@@ -1783,10 +1823,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
checkNonCyclic(tdef.symbol)
if (tdef.symbol.owner.isType)
rhs1.tpe match {
- case TypeBounds(lo1, hi1) =>
- if (!(lo1 <:< hi1))
- error(tdef.pos, "lower bound "+lo1+" does not conform to upper bound "+hi1)
- case _ =>
+ case TypeBounds(lo1, hi1) if (!(lo1 <:< hi1)) => LowerBoundError(tdef, lo1, hi1)
+ case _ => ()
}
treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
}
@@ -1906,9 +1944,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
// verify no _* except in last position
for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
- error(x.pos, "_* may only come last")
+ StarPositionInPatternError(x)
- val pat1: Tree = typedPattern(cdef.pat, pattpe)
+ val pat1 = typedPattern(cdef.pat, pattpe)
// When case classes have more than two parameter lists, the pattern ends
// up typed as a method. We only pattern match on the first parameter
// list, so substitute the final result type of the method, i.e. the type
@@ -1952,7 +1990,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val codeExpected = !forMSIL && (pt.typeSymbol isNonBottomSubClass CodeClass)
if (numVparams > definitions.MaxFunctionArity)
- return errorTree(fun, "implementation restricts functions to " + definitions.MaxFunctionArity + " parameters")
+ return MaxFunctionArityError(fun)
def decompose(pt: Type): (Symbol, List[Type], Type) =
if ((isFunctionType(pt)
@@ -1968,9 +2006,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType)
val (clazz, argpts, respt) = decompose(if (codeExpected) pt.normalize.typeArgs.head else pt)
-
if (argpts.lengthCompare(numVparams) != 0)
- errorTree(fun, "wrong number of parameters; expected = " + argpts.length)
+ WrongNumberOfParametersError(fun, argpts)
else {
val vparamSyms = map2(fun.vparams, argpts) { (vparam, argpt) =>
if (vparam.tpt.isEmpty) {
@@ -1980,7 +2017,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
fun match {
case etaExpansion(vparams, fn, args) if !codeExpected =>
silent(_.typed(fn, forFunMode(mode), pt)) match {
- case fn1: Tree if context.undetparams.isEmpty =>
+ case SilentResultValue(fn1) if context.undetparams.isEmpty =>
// if context,undetparams is not empty, the function was polymorphic,
// so we need the missing arguments to infer its type. See #871
//println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams)
@@ -1991,7 +2028,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
case _ =>
}
- error(vparam.pos, missingParameterTypeMsg(fun, vparam, pt))
+ MissingParameterTypeError(fun, vparam, pt)
ErrorType
}
if (!vparam.tpt.pos.isDefined) vparam.tpt setPos vparam.pos.focus
@@ -2005,12 +2042,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// for (vparam <- vparams) {
// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
// }
- var body = typed(fun.body, respt)
+ val body1 = typed(fun.body, respt)
val formals = vparamSyms map (_.tpe)
- val restpe = packedType(body, fun.symbol).deconst.resultType
+ val restpe = packedType(body1, fun.symbol).deconst.resultType
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe)
// body = checkNoEscaping.locals(context.scope, restpe, body)
- val fun1 = treeCopy.Function(fun, vparams, body).setType(funtpe)
+ val fun1 = treeCopy.Function(fun, vparams, body1).setType(funtpe)
if (codeExpected) lifted(fun1) else fun1
}
}
@@ -2025,7 +2062,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
unit.toCheck += { () =>
// go to next outer context which is not silent, see #3614
var c = context
- while (!c.reportGeneralErrors) c = c.outer
+ while (c.bufferErrors) c = c.outer
val stats1 = newTyper(c).typedStats(stats, NoSymbol)
for (stat <- stats1 if stat.isDef) {
val member = stat.symbol
@@ -2041,11 +2078,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Some(imp1: Import) => imp1
case None => log("unhandled import: "+imp+" in "+unit); imp
}
-
private def isWarnablePureExpression(tree: Tree) = tree match {
case EmptyTree | Literal(Constant(())) => false
case _ =>
- (treeInfo isExprSafeToInline tree) && {
+ !tree.isErrorTyped && (treeInfo isExprSafeToInline tree) && {
val sym = tree.symbol
(sym == null) || !(sym.isModule || sym.isLazy) || {
debuglog("'Pure' but side-effecting expression in statement position: " + tree)
@@ -2059,9 +2095,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def includesTargetPos(tree: Tree) =
tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos)
val localTarget = stats exists includesTargetPos
+ val statsErrors = scala.collection.mutable.LinkedHashSet[AbsTypeError]()
def typedStat(stat: Tree): Tree = {
if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat))
- errorTree(stat, "only declarations allowed here")
+ OnlyDeclarationsError(stat)
else
stat match {
case imp @ Import(_, _) =>
@@ -2074,20 +2111,25 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// the targetposition
stat
} else {
- val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
- else newTyper(context.make(stat, exprOwner))
+ val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) {
+ context.flushBuffer()
+ this
+ } else newTyper(context.make(stat, exprOwner))
// XXX this creates a spurious dead code warning if an exception is thrown
// in a constructor, even if it is the only thing in the constructor.
val result = checkDead(localTyper.typed(stat, EXPRmode | BYVALmode, WildcardType))
+
if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.pointOrElse(0) >= exprOwner.enclMethod.pos.pointOrElse(0))
- error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ ConstructorsOrderError(stat)
}
+
if (isWarnablePureExpression(result)) context.warning(stat.pos,
"a pure expression does nothing in statement position; " +
"you may be omitting necessary parentheses"
)
+ statsErrors ++= localTyper.context.errBuffer
result
}
}
@@ -2121,9 +2163,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// error for this is issued in RefChecks.checkDefaultsInOverloaded
if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
!e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
- error(e.sym.pos, e1.sym+" is defined twice"+
- {if(!settings.debug.value) "" else " in "+unit.toString}+
- {if (e.sym.isMacro && e1.sym.isMacro) " \n(note that macros cannot be overloaded)" else ""})
+ DefDefinedTwiceError(e.sym, e1.sym)
scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
}
e1 = scope.lookupNextEntry(e1)
@@ -2168,14 +2208,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}) ::: newStats.toList
}
}
- val result = stats mapConserve typedStat
- if (phase.erasedTypes) result
- else checkNoDoubleDefsAndAddSynthetics(result)
+
+ val stats1 = withSavedContext(context) {
+ val result = stats mapConserve typedStat
+ context.flushBuffer()
+ result
+ }
+ context.updateBuffer(statsErrors)
+ if (phase.erasedTypes) stats1
+ else checkNoDoubleDefsAndAddSynthetics(stats1)
}
def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = {
val typedMode = onlyStickyModes(mode) | newmode
- val t = constrTyperIf((mode & SCCmode) != 0).typed(arg, typedMode, pt)
+ val t = withCondConstrTyper((mode & SCCmode) != 0)(_.typed(arg, typedMode, pt))
checkDead.inMode(typedMode, t)
}
@@ -2244,8 +2290,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Int, pt: Type): Tree = {
// TODO_NMT: check the assumption that args nonEmpty
- def errTree = setError(treeCopy.Apply(tree, fun0, args))
- def errorTree(msg: String) = { error(tree.pos, msg); errTree }
+ def duplErrTree = setError(treeCopy.Apply(tree, fun0, args))
+ def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree }
var fun = fun0
if (fun.hasSymbol && fun.symbol.isOverloaded) {
@@ -2308,8 +2354,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
arg1
}
context.undetparams = undetparams
- inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
- doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
+ if (context.hasErrors)
+ setError(tree)
+ else {
+ inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
+ doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
+ }
case mt @ MethodType(params, _) =>
val paramTypes = mt.paramTypes
@@ -2329,7 +2379,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// the inner "doTypedApply" does "extractUndetparams" => restore when it fails
val savedUndetparams = context.undetparams
silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) match {
- case t: Tree =>
+ case SilentResultValue(t) =>
// Depending on user options, may warn or error here if
// a Unit or tuple was inserted.
Some(t) filter (tupledTree =>
@@ -2337,7 +2387,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|| tupledTree.symbol == null
|| checkValidAdaptation(tupledTree, args)
)
- case ex =>
+ case _ =>
context.undetparams = savedUndetparams
None
}
@@ -2352,21 +2402,21 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def tryNamesDefaults: Tree = {
val lencmp = compareLengths(args, formals)
- if (mt.isErroneous) errTree
- else if (inPatternMode(mode))
+ if (mt.isErroneous) duplErrTree
+ else if (inPatternMode(mode)) {
// #2064
- errorTree("wrong number of arguments for "+ treeSymTypeMsg(fun))
- else if (lencmp > 0) {
- tryTupleApply getOrElse errorTree("too many arguments for "+treeSymTypeMsg(fun))
+ duplErrorTree(WrongNumberOfArgsError(tree, fun))
+ } else if (lencmp > 0) {
+ tryTupleApply getOrElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun))
} else if (lencmp == 0) {
// we don't need defaults. names were used, so this application is transformed
// into a block (@see transformNamedApplication in NamesDefaults)
val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
if (namelessArgs exists (_.isErroneous)) {
- errTree
+ duplErrTree
} else if (!isIdentity(argPos) && !sameLength(formals, params))
// !isIdentity indicates that named arguments are used to re-order arguments
- errorTree("when using named arguments, the vararg parameter has to be specified exactly once")
+ duplErrorTree(MultipleVarargError(tree))
else if (isIdentity(argPos) && !isNamedApplyBlock(fun)) {
// if there's no re-ordering, and fun is not transformed, no need to transform
// more than an optimization, e.g. important in "synchronized { x = update-x }"
@@ -2380,7 +2430,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// calls to the default getters. Example:
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
- if (fun1.isErroneous) errTree
+ if (fun1.isErroneous) duplErrTree
else {
assert(isNamedApplyBlock(fun1), fun1)
val NamedApplyInfo(qual, targs, previousArgss, _) = context.namedApplyBlockInfo.get._2
@@ -2397,17 +2447,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val lencmp2 = compareLengths(allArgs, formals)
if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) {
- errorTree("module extending its companion class cannot use default constructor arguments")
+ duplErrorTree(ModuleUsingCompanionClassDefaultArgsErrror(tree))
} else if (lencmp2 > 0) {
removeNames(Typer.this)(allArgs, params) // #3818
- errTree
+ duplErrTree
} else if (lencmp2 == 0) {
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
val note = "Error occurred in an application involving default arguments."
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
} else {
- tryTupleApply getOrElse errorTree(notEnoughArgumentsMsg(fun, missing))
+ tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing))
}
}
}
@@ -2466,13 +2516,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
atPos(tree.pos)(gen.mkNil setType restpe)
else
constfold(treeCopy.Apply(tree, fun, args1) setType ifPatternSkipFormals(restpe))
-
} else if (needsInstantiation(tparams, formals, args)) {
//println("needs inst "+fun+" "+tparams+"/"+(tparams map (_.info)))
inferExprInstance(fun, tparams)
doTypedApply(tree, fun, args, mode, pt)
} else {
- assert(!inPatternMode(mode)) // this case cannot arise for patterns
+ assert(!inPatternMode(mode), modeString(mode)) // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
if (targ == WildcardType) tparam.tpe else targ) //@M TODO: should probably be .tpeHK
@@ -2488,11 +2537,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (!argtparams.isEmpty) {
val strictPt = formal.instantiateTypeParams(tparams, strictTargs)
inferArgumentInstance(arg1, argtparams, strictPt, lenientPt)
- }
- arg1
+ arg1
+ } else arg1
}
val args1 = map2(args, formals)(typedArgToPoly)
- if (args1 exists (_.tpe.isError)) errTree
+ if (args1 exists {_.isErrorTyped}) duplErrTree
else {
debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug
// define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
@@ -2509,12 +2558,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
doTypedApply(tree, fun setType fun.tpe.widen, args, mode, pt)
case ErrorType =>
- setError(treeCopy.Apply(tree, fun, args))
+ if (!tree.isErrorTyped) setError(tree) else tree
+ // @H change to setError(treeCopy.Apply(tree, fun, args))
/* --- begin unapply --- */
case otpe if inPatternMode(mode) && unapplyMember(otpe).exists =>
if (args.length > MaxTupleArity)
- error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity)
+ return duplErrorTree(TooManyArgsPatternError(fun))
//
def freshArgType(tp: Type): (List[Symbol], Type) = tp match {
@@ -2522,11 +2572,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(Nil, param.tpe)
case PolyType(tparams, restpe) =>
createFromClonedSymbols(tparams, freshArgType(restpe)._2)((ps, t) => ((ps, t)))
+ // No longer used, see test case neg/t960.scala (#960 has nothing to do with it)
case OverloadedType(_, _) =>
- error(fun.pos, "cannot resolve overloaded unapply")
+ OverloadedUnapplyError(fun)
(Nil, ErrorType)
case _ =>
- error(fun.pos, "an unapply method must accept a single argument.")
+ UnapplyWithSingleArgError(fun)
(Nil, ErrorType)
}
@@ -2542,7 +2593,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
freeVars foreach unapplyContext.scope.enter
val typer1 = newTyper(unapplyContext)
- val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
+ val pattp = typer1.infer.inferTypedPattern(tree, unappFormal, arg.tpe)
// turn any unresolved type variables in freevars into existential skolems
val skolems = freeVars map (fv => unapplyContext.owner.newExistentialSkolem(fv, fv))
@@ -2553,8 +2604,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// setType null is necessary so that ref will be stabilized; see bug 881
val fun1 = typedPos(fun.pos)(Apply(Select(fun setType null, unapp), List(arg)))
- if (fun1.tpe.isErroneous) errTree
- else {
+ if (fun1.tpe.isErroneous) {
+ duplErrTree
+ } else {
val formals0 = unapplyTypeList(fun1.symbol, fun1.tpe)
val formals1 = formalTypes(formals0, args.length)
if (sameLength(formals1, args)) {
@@ -2567,15 +2619,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val itype = glb(List(pt1, arg.tpe))
arg.tpe = pt1 // restore type (arg is a dummy tree, just needs to pass typechecking)
UnApply(fun1, args1) setPos tree.pos setType itype
- }
- else {
- errorTree("wrong number of arguments for "+treeSymTypeMsg(fun))
- }
+ } else
+ duplErrorTree(WrongNumberArgsPatternError(tree, fun))
}
/* --- end unapply --- */
case _ =>
- errorTree(fun.tpe+" does not take parameters")
+ duplErrorTree(ApplyWithoutArgsError(tree, fun))
}
}
@@ -2587,8 +2637,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedAnnotation(ann: Tree, mode: Int = EXPRmode, selfsym: Symbol = NoSymbol, annClass: Symbol = AnnotationClass, requireJava: Boolean = false): AnnotationInfo = {
lazy val annotationError = AnnotationInfo(ErrorType, Nil, Nil)
var hasError: Boolean = false
- def error(pos: Position, msg: String) = {
- context.error(pos, msg)
+ val pending = ListBuffer[AbsTypeError]()
+
+ def reportAnnotationError(err: AbsTypeError) = {
+ pending += err
hasError = true
annotationError
}
@@ -2604,13 +2656,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case tpe => null
}
}
- def fail(msg: String) = { error(tr.pos, msg) ; None }
- if (const == null)
- fail("annotation argument needs to be a constant; found: " + tr)
- else if (const.value == null)
- fail("annotation argument cannot be null")
- else
+ if (const == null) {
+ reportAnnotationError(AnnotationNotAConstantError(tr)); None
+ } else if (const.value == null) {
+ reportAnnotationError(AnnotationArgNullError(tr)); None
+ } else
Some(LiteralAnnotArg(const))
}
@@ -2619,16 +2670,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
*/
def tree2ConstArg(tree: Tree, pt: Type): Option[ClassfileAnnotArg] = tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) if (pt.typeSymbol == ArrayClass) =>
- error(tree.pos, "Array constants have to be specified using the `Array(...)' factory method")
- None
+ reportAnnotationError(ArrayConstantsError(tree)); None
case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
val annInfo = typedAnnotation(ann, mode, NoSymbol, pt.typeSymbol, true)
- if (annInfo.atp.isErroneous) {
- // recursive typedAnnotation call already printed an error, so don't call "error"
- hasError = true
- None
- } else Some(NestedAnnotArg(annInfo))
+ if (annInfo.atp.isErroneous) { hasError = true; None }
+ else Some(NestedAnnotArg(annInfo))
// use of Array.apply[T: ClassManifest](xs: T*): Array[T]
// and Array.apply(x: Int, xs: Int*): Array[Int] (and similar)
@@ -2643,13 +2690,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// BT = Int, .., String, Class[_], JavaAnnotClass
// T = BT | Array[BT]
// So an array literal as argument can only be valid if pt is Array[_]
- error(tree.pos, "found array constant, expected argument of type "+ pt)
+ reportAnnotationError(ArrayConstantsTypeMismatchError(tree, pt))
None
}
- else
- tryConst(tree, pt)
+ else tryConst(tree, pt)
- case Typed(t, _) => tree2ConstArg(t, pt)
+ case Typed(t, _) =>
+ tree2ConstArg(t, pt)
case tree =>
tryConst(tree, pt)
@@ -2669,13 +2716,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Select(New(tpt), nme.CONSTRUCTOR) =>
(fun, outerArgss)
case _ =>
- error(fun.pos, "unexpected tree in annotation: "+ fun)
+ reportAnnotationError(UnexpectedTreeAnnotation(fun))
(setError(fun), outerArgss)
}
extract(ann, List())
}
- if (fun.isErroneous) annotationError
+ val res = if (fun.isErroneous) annotationError
else {
val typedFun @ Select(New(tpt), _) = typed(fun, forFunMode(mode), WildcardType)
val annType = tpt.tpe
@@ -2685,9 +2732,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// annotation to be saved as java classfile annotation
val isJava = typedFun.symbol.owner.isJavaDefined
if (!annType.typeSymbol.isNonBottomSubClass(annClass)) {
- error(tpt.pos, "expected annotation of type "+ annClass.tpe +", found "+ annType)
+ reportAnnotationError(AnnotationTypeMismatchError(tpt, annClass.tpe, annType))
} else if (argss.length > 1) {
- error(ann.pos, "multiple argument lists on classfile annotation")
+ reportAnnotationError(MultipleArgumentListForAnnotationError(ann))
} else {
val args =
if (argss.head.length == 1 && !isNamed(argss.head.head))
@@ -2703,10 +2750,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val sym = if (isJava) annScope.lookup(name)
else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol)
if (sym == NoSymbol) {
- error(arg.pos, "unknown annotation argument name: " + name)
+ reportAnnotationError(UnknownAnnotationNameError(arg, name))
(nme.ERROR, None)
} else if (!names.contains(sym)) {
- error(arg.pos, "duplicate value for annotation argument " + name)
+ reportAnnotationError(DuplicateValueAnnotationError(arg, name))
(nme.ERROR, None)
} else {
names -= sym
@@ -2715,21 +2762,21 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(sym.name, annArg)
}
case arg =>
- error(arg.pos, "classfile annotation arguments have to be supplied as named arguments")
+ reportAnnotationError(ClassfileAnnotationsAsNamedArgsError(arg))
(nme.ERROR, None)
}
for (sym <- names) {
// make sure the flags are up to date before erroring (jvm/t3415 fails otherwise)
sym.initialize
if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefaultFlag)
- error(ann.pos, "annotation " + annType.typeSymbol.fullName + " is missing argument " + sym.name)
+ reportAnnotationError(AnnotationMissingArgError(ann, annType, sym))
}
if (hasError) annotationError
else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setPos(ann.pos)
}
} else if (requireJava) {
- error(ann.pos, "nested classfile annotations must be defined in java; found: "+ annType)
+ reportAnnotationError(NestedAnnotationError(ann, annType))
} else {
val typedAnn = if (selfsym == NoSymbol) {
typed(ann, mode, annClass.tpe)
@@ -2781,7 +2828,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
annInfo(fun)
case _ =>
- error(t.pos, "unexpected tree after typing annotation: "+ typedAnn)
+ reportAnnotationError(UnexpectedTreeAnnotationError(t, typedAnn))
}
if (annType.typeSymbol == DeprecatedAttr && argss.flatten.size < 2)
@@ -2791,6 +2838,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else annInfo(typedAnn)
}
}
+
+ if (hasError) {
+ pending.foreach(ErrorUtils.issueTypeError)
+ annotationError
+ } else res
}
def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type?
@@ -2890,7 +2942,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (sym.isAliasType && containsLocal(tp)) apply(tp.normalize)
else {
if (pre.isVolatile)
- context.error(tree.pos, "Inferred type "+tree.tpe+" contains type selection from volatile type "+pre)
+ InferTypeWithVolatileTypeSelectionError(tree, pre)
mapOver(tp)
}
case _ =>
@@ -2907,8 +2959,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
localSyms += sym
remainingSyms += sym
} else {
- unit.error(tree.pos,
- "can't existentially abstract over parameterized type " + tp)
+ AbstractExistentiallyOverParamerizedTpeError(tree, tp)
}
}
}
@@ -2977,10 +3028,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
new DeSkolemizeMap mapOver tp
}
- def typedClassOf(tree: Tree, tpt: Tree) = {
- checkClassType(tpt, true, false)
- atPos(tree.pos)(gen.mkClassOf(tpt.tpe))
- }
+ def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
+ if (!checkClassType(tpt, true, false) && noGen) tpt
+ else atPos(tree.pos)(gen.mkClassOf(tpt.tpe))
protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = {
for (wc <- tree.whereClauses)
@@ -2989,7 +3039,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val whereClauses1 = typedStats(tree.whereClauses, context.owner)
for (vd @ ValDef(_, _, _, _) <- tree.whereClauses)
if (vd.symbol.tpe.isVolatile)
- error(vd.pos, "illegal abstraction from value with volatile type "+vd.symbol.tpe)
+ AbstractionFromVolatileTypeError(vd)
val tpt1 = typedType(tree.tpt, mode)
existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) =>
TypeTree(newExistentialType(tparams, tp)) setOriginal tree
@@ -3012,7 +3062,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// Martin, I'm using fake trees, because, if you use args or arg.map(typedType),
// inferPolyAlternatives loops... -- I have no idea why :-(
// ...actually this was looping anyway, see bug #278.
- return errorTree(fun, "wrong number of type parameters for "+treeSymTypeMsg(fun))
+ return TypedApplyWrongNumberOfTpeParametersError(fun, fun)
typedTypeApply(tree, mode, fun, args1)
case SingleType(_, _) =>
@@ -3020,12 +3070,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case PolyType(tparams, restpe) if tparams.nonEmpty =>
if (sameLength(tparams, args)) {
val targs = args map (_.tpe)
- checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "")
+ checkBounds(tree, NoPrefix, NoSymbol, tparams, targs, "")
if (fun.symbol == Predef_classOf)
- typedClassOf(tree, args.head)
+ typedClassOf(tree, args.head, true)
else {
if (!isPastTyper && fun.symbol == Any_isInstanceOf && !targs.isEmpty)
- checkCheckable(tree.pos, targs.head, "")
+ checkCheckable(tree, targs.head, "")
val resultpe = restpe.instantiateTypeParams(tparams, targs)
//@M substitution in instantiateParams needs to be careful!
//@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int]
@@ -3036,12 +3086,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.TypeApply(tree, fun, args) setType resultpe
}
} else {
- errorTree(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun))
+ TypedApplyWrongNumberOfTpeParametersError(tree, fun)
}
case ErrorType =>
setError(treeCopy.TypeApply(tree, fun, args))
case _ =>
- errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.")
+ TypedApplyDoesNotTakeTpeParametersError(tree, fun)
}
@inline final def deindentTyping() = context.typingIndentLevel -= 2
@@ -3110,6 +3160,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// this annotation did not need it
if (ainfo.isErroneous)
+ // Erroneous annotations were already reported in typedAnnotation
arg1 // simply drop erroneous annotations
else {
ann.tpe = atype
@@ -3149,7 +3200,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
vble = context.owner.newValue(name, tree.pos)
if (vble.name.toTermName != nme.WILDCARD) {
if ((mode & ALTmode) != 0)
- error(tree.pos, "illegal variable in pattern alternative")
+ VariableInPatternAlternativeError(tree)
vble = namer.enterInScope(vble)
}
val body1 = typed(body, mode, pt)
@@ -3176,18 +3227,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType)
val varsym = lhs1.symbol
- def failMsg =
- if (varsym != null && varsym.isValue) "reassignment to val"
- else "assignment to non variable"
- def fail = {
- if (!lhs1.tpe.isError)
- error(tree.pos, failMsg)
+ // see #2494 for double error message example
+ def fail() =
+ if (lhs1.isErrorTyped) lhs1
+ else AssignmentError(tree, varsym)
- setError(tree)
- }
if (varsym == null)
- return fail
+ return fail()
if (treeInfo.mayBeVarGetter(varsym)) {
treeInfo.methPart(lhs1) match {
@@ -3203,7 +3250,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val rhs1 = typed(rhs, EXPRmode | BYVALmode, lhs1.tpe)
treeCopy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
}
- else fail
+ else fail()
}
def typedIf(cond: Tree, thenp: Tree, elsep: Tree) = {
@@ -3273,12 +3320,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
enclMethod.owner.isConstructor ||
context.enclClass.enclMethod == enclMethod // i.e., we are in a constructor of a local class
) {
- errorTree(tree, "return outside method definition")
+ ReturnOutsideOfDefError(tree)
} else {
val DefDef(_, name, _, _, restpt, _) = enclMethod.tree
- if (restpt.tpe eq null)
- errorTree(tree, enclMethod.owner + " has return statement; needs result type")
- else {
+ if (restpt.tpe eq null) {
+ ReturnWithoutTypeError(tree, enclMethod.owner)
+ } else {
context.enclMethod.returnsSeen = true
val expr1: Tree = typed(expr, EXPRmode | BYVALmode, restpt.tpe)
// Warn about returning a value if no value can be returned.
@@ -3297,12 +3344,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedNew(tpt: Tree) = {
val tpt1 = {
val tpt0 = typedTypeConstructor(tpt)
- checkClassType(tpt0, false, true)
- if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
- context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
- TypeTree().setOriginal(tpt0)
- .setType(appliedType(tpt0.tpe, context.undetparams map (_.tpeHK))) // @PP: tpeHK! #3343, #4018, #4347.
- } else tpt0
+ if (checkClassType(tpt0, false, true))
+ if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
+ context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
+ TypeTree().setOriginal(tpt0)
+ .setType(appliedType(tpt0.tpe, context.undetparams map (_.tpeHK))) // @PP: tpeHK! #3343, #4018, #4347.
+ } else tpt0
+ else tpt0
}
/** If current tree <tree> appears in <val x(: T)? = <tree>>
@@ -3321,17 +3369,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val tp = tpt1.tpe
val sym = tp.typeSymbol.initialize
if (sym.isAbstractType || sym.hasAbstractFlag)
- error(tree.pos, sym + " is abstract; cannot be instantiated")
+ IsAbstractError(tree, sym)
else if (!( tp == sym.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable
// sym.thisSym.tpe == tp.typeOfThis (except for objects)
|| narrowRhs(tp) <:< tp.typeOfThis
|| phase.erasedTypes
)) {
- error(tree.pos, sym +
- " cannot be instantiated because it does not conform to its self-type "+
- tp.typeOfThis)
- }
- treeCopy.New(tree, tpt1).setType(tp)
+ DoesNotConformToSelfTypeError(tree, sym, tp.typeOfThis)
+ } else
+ treeCopy.New(tree, tpt1).setType(tp)
}
def typedEta(expr1: Tree): Tree = expr1.tpe match {
@@ -3369,22 +3415,28 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case ErrorType =>
expr1
case _ =>
- errorTree(expr1, "_ must follow method; cannot follow " + expr1.tpe)
+ UnderscoreEtaError(expr1)
}
/**
* @param args ...
* @return ...
*/
- def tryTypedArgs(args: List[Tree], mode: Int, other: TypeError): List[Tree] = {
+ def tryTypedArgs(args: List[Tree], mode: Int): Option[List[Tree]] = {
val c = context.makeSilent(false)
c.retyping = true
try {
- newTyper(c).typedArgs(args, mode)
+ val res = newTyper(c).typedArgs(args, mode)
+ if (c.hasErrors) None else Some(res)
} catch {
- case ex: CyclicReference => throw ex
- case ex: TypeError =>
- null
+ case ex: CyclicReference =>
+ throw ex
+ case te: TypeError =>
+ // @H some of typer erros can still leak,
+ // for instance in continuations
+ None
+ } finally {
+ c.flushBuffer()
}
}
@@ -3393,10 +3445,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
*/
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = startTimer(failedApplyNanos)
- silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
- case t: Tree =>
- t
- case ex: TypeError =>
+
+ def onError(typeError: AbsTypeError): Tree = {
stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -3419,27 +3469,39 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r)
case _ => Nil
})
- def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == ex.pos)
- val retry = fun :: tree :: args exists errorInResult
+ def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos)
+
+ val retry = (typeError.errPos != null) && (fun :: tree :: args exists errorInResult)
printTyping {
val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ")
if (retry) "second try: " + funStr
- else "no second try: " + funStr + " because error not in result: " + ex.pos+"!="+tree.pos
+ else "no second try: " + funStr + " because error not in result: " + typeError.errPos+"!="+tree.pos
}
if (retry) {
val Select(qual, name) = fun
- val args1 = tryTypedArgs(args, forArgMode(fun, mode), ex)
- val qual1 =
- if ((args1 ne null) && !pt.isError) adaptToArguments(qual, name, args1, pt)
- else qual
- if (qual1 ne qual) {
- val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
- return typed1(tree1, mode | SNDTRYmode, pt)
+ tryTypedArgs(args, forArgMode(fun, mode)) match {
+ case Some(args1) =>
+ assert((args1.length == 0) || !args1.head.tpe.isErroneous, "try typed args is ok")
+ val qual1 =
+ if (!pt.isError) adaptToArguments(qual, name, args1, pt, true, true)
+ else qual
+ if (qual1 ne qual) {
+ val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
+ return typed1(tree1, mode | SNDTRYmode, pt)
+ }
+ case _ => ()
}
}
- reportTypeError(tree.pos, ex)
+ issue(typeError)
setError(treeCopy.Apply(tree, fun, args))
}
+
+ silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
+ case SilentResultValue(t) =>
+ t
+ case SilentTypeError(err) =>
+ onError(err)
+ }
}
def typedApply(fun: Tree, args: List[Tree]) = {
@@ -3451,10 +3513,28 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val funpt = if (isPatternMode) pt else WildcardType
val appStart = startTimer(failedApplyNanos)
val opeqStart = startTimer(failedOpEqNanos)
+
+ def onError(reportError: => Tree): Tree = {
+ fun match {
+ case Select(qual, name)
+ if !isPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) =>
+ val qual1 = typedQualifier(qual)
+ if (treeInfo.isVariableOrGetter(qual1)) {
+ stopTimer(failedOpEqNanos, opeqStart)
+ convertToAssignment(fun, qual1, name, args)
+ } else {
+ stopTimer(failedApplyNanos, appStart)
+ reportError
+ }
+ case _ =>
+ stopTimer(failedApplyNanos, appStart)
+ reportError
+ }
+ }
silent(_.typed(fun, forFunMode(mode), funpt),
- if ((mode & EXPRmode) != 0) false else context.reportAmbiguousErrors,
+ if ((mode & EXPRmode) != 0) false else context.ambiguousErrors,
if ((mode & EXPRmode) != 0) tree else context.tree) match {
- case fun1: Tree =>
+ case SilentResultValue(fun1) =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
incCounter(typedApplyCount)
def isImplicitMethod(tpe: Type) = tpe match {
@@ -3481,7 +3561,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
//if (fun2.hasSymbol && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
// But this causes cyclic reference for Array class in Cleanup. It is easy to overcome this
// by calling ArrayClass.info here (or some other place before specialize).
- if (fun2.symbol == Array_apply) {
+ if (fun2.symbol == Array_apply && !res.isErrorTyped) {
val checked = gen.mkCheckInit(res)
// this check is needed to avoid infinite recursion in Duplicators
// (calling typed1 more than once for the same tree)
@@ -3489,30 +3569,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else res
} else
res
- case ex: TypeError =>
- fun match {
- case Select(qual, name)
- if !isPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) =>
- val qual1 = typedQualifier(qual)
- if (treeInfo.isVariableOrGetter(qual1)) {
- stopTimer(failedOpEqNanos, opeqStart)
- convertToAssignment(fun, qual1, name, args, ex)
- }
- else {
- stopTimer(failedApplyNanos, appStart)
- reportTypeError(fun.pos, ex)
- setError(tree)
- }
- case _ =>
- stopTimer(failedApplyNanos, appStart)
- reportTypeError(fun.pos, ex)
- setError(tree)
- }
+ case SilentTypeError(err) =>
+ onError({issue(err); setError(tree)})
}
}
}
- def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree], ex: TypeError): Tree = {
+ def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = {
val prefix = name.subName(0, name.length - nme.EQL.length)
def mkAssign(vble: Tree): Tree =
Assign(
@@ -3553,25 +3616,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Apply(fn, indices) =>
treeInfo.methPart(fn) match {
case Select(table, nme.apply) => mkUpdate(table, indices)
- case _ => errorTree(qual, "Unexpected tree during assignment conversion.")
+ case _ => UnexpectedTreeAssignmentConversionError(qual)
}
}
typed1(tree1, mode, pt)
-/*
- debuglog("retry assign: "+tree1)
- silent(_.typed1(tree1, mode, pt)) match {
- case t: Tree =>
- t
- case _ =>
- reportTypeError(tree.pos, ex)
- setError(tree)
- }
-*/
}
- def qualifyingClassSym(qual: Name): Symbol =
- if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(tree, qual, false)
-
def typedSuper(qual: Tree, mix: TypeName) = {
val qual1 = typed(qual)
@@ -3596,12 +3646,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// println(mix)
// the reference to super class got lost during erasure
restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class")
+ ErrorType
} else {
- error(tree.pos, mix+" does not name a parent class of "+clazz)
+ MixinMissingParentClassNameError(tree, mix, clazz)
+ ErrorType
}
- ErrorType
} else if (!ps.tail.isEmpty) {
- error(tree.pos, "ambiguous parent class qualifier")
+ AmbiguousParentClassError(tree)
ErrorType
} else {
ps.head
@@ -3618,16 +3669,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
findMixinSuper(clazz.tpe)
}
- treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype)
- }
+ treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype)
+ }
def typedThis(qual: Name) = {
- val clazz = qualifyingClassSym(qual)
- if (clazz == NoSymbol) setError(tree)
- else {
- tree setSymbol clazz setType clazz.thisType.underlying
- if (isStableContext(tree, mode, pt)) tree setType clazz.thisType
- tree
+ val qualifyingClassSym = if (tree.symbol != NoSymbol) Some(tree.symbol) else qualifyingClass(tree, qual)
+ qualifyingClassSym match {
+ case Some(clazz) =>
+ tree setSymbol clazz setType clazz.thisType.underlying
+ if (isStableContext(tree, mode, pt)) tree setType clazz.thisType
+ tree
+ case None => tree
}
}
@@ -3659,10 +3711,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
val qual1 =
if (member(qual, name) != NoSymbol) qual
- else adaptToMemberWithArgs(tree, qual, name, mode)
- if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
- }
+ else adaptToMemberWithArgs(tree, qual, name, mode, true, true)
+ if (qual1 ne qual)
+ return typed(treeCopy.Select(tree, qual1, name), mode, pt)
+ }
if (!reallyExists(sym)) {
if (context.owner.toplevelClass.isJavaDefined && name.isTypeName) {
val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
@@ -3691,7 +3744,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
)
}
- def makeErrorTree = {
+ def makeInteractiveErrorTree = {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
@@ -3700,24 +3753,31 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
if (name == nme.ERROR && forInteractive)
- return makeErrorTree
+ return makeInteractiveErrorTree
if (!qual.tpe.widen.isErroneous) {
if ((mode & QUALmode) != 0) {
val lastTry = missingHook(qual.tpe.typeSymbol, name)
if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt)
}
- notAMemberError(tree.pos, qual, name)
+ NotAMemberError(tree, qual, name)
}
- if (forInteractive) makeErrorTree else setError(tree)
+ if (forInteractive) makeInteractiveErrorTree else setError(tree)
} else {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
}
- val (tree2, pre2) = makeAccessible(tree1, sym, qual.tpe, qual)
- val result = stabilize(tree2, pre2, mode, pt)
+ val (result, accessibleError) = silent(_.makeAccessible(tree1, sym, qual.tpe, qual)) match {
+ case SilentTypeError(err) =>
+ if (err.kind != ErrorKinds.Access) {
+ context issue err
+ return setError(tree)
+ } else (tree1, Some(err))
+ case SilentResultValue(treeAndPre) =>
+ (stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None)
+ }
def isPotentialNullDeference() = {
!isPastTyper &&
@@ -3736,16 +3796,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
result,
(TypeTreeWithDeferredRefCheck(){ () => val tp = qual.tpe; val sym = tp.typeSymbolDirect
// will execute during refchecks -- TODO: make private checkTypeRef in refchecks public and call that one?
- checkBounds(qual.pos, tp.prefix, sym.owner, sym.typeParams, tp.typeArgs, "")
+ checkBounds(qual, tp.prefix, sym.owner, sym.typeParams, tp.typeArgs, "")
qual // you only get to see the wrapped tree after running this check :-p
}) setType qual.tpe setPos qual.pos,
name)
- case accErr: Inferencer#AccessError =>
- val qual1 =
- try adaptToMemberWithArgs(tree, qual, name, mode)
- catch { case _: TypeError => qual }
- if (qual1 ne qual) typed(Select(qual1, name) setPos tree.pos, mode, pt)
- else accErr.emit()
+ case _ if accessibleError.isDefined =>
+ val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, false, false)
+ if (!qual1.isErrorTyped && (qual1 ne qual))
+ typed(Select(qual1, name) setPos tree.pos, mode, pt)
+ else {
+ issue(accessibleError.get)
+ setError(tree)
+ }
case _ =>
result
}
@@ -3753,7 +3815,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// getClass, we have to catch it immediately so expressions
// like x.getClass().newInstance() are typed with the type of x.
val isRefinableGetClass = (
- selection.symbol.name == nme.getClass_
+ !selection.isErrorTyped
+ && selection.symbol.name == nme.getClass_
&& selection.tpe.params.isEmpty
// TODO: If the type of the qualifier is inaccessible, we can cause private types
// to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this
@@ -3761,7 +3824,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
&& qual.tpe.typeSymbol.isPublic
)
if (isRefinableGetClass)
- selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe))
+ selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe))
else
selection
}
@@ -3775,8 +3838,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* (2) Change imported symbols to selections
*/
def typedIdent(name: Name): Tree = {
- def ambiguousError(msg: String) =
- error(tree.pos, "reference to " + name + " is ambiguous;\n" + msg)
+ var errorContainer: AbsTypeError = null
+ @inline
+ def ambiguousError(msg: String) = {
+ assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
+ errorContainer = AmbiguousIdentError(tree, name, msg)
+ }
+ @inline
+ def identError(tree: AbsTypeError) = {
+ assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
+ errorContainer = tree
+ }
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -3896,7 +3968,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
ambiguousError(
"it is imported twice in the same scope by\n"+imports.head + "\nand "+imports1.head)
}
- while (!imports1.isEmpty &&
+ while (errorContainer == null && !imports1.isEmpty &&
(!imports.head.isExplicitImport(name) ||
imports1.head.depth == imports.head.depth)) {
var impSym1 = imports1.head.importedSymbol(name)
@@ -3930,74 +4002,49 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (inaccessibleSym eq NoSymbol) {
// Avoiding some spurious error messages: see SI-2388.
if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) ()
- else {
- // This laborious determination arrived at to keep the tests working.
- val calcSimilar = (
- name.length > 2 && (
- startingIdentContext.reportGeneralErrors
- || startingIdentContext.enclClassOrMethod.reportGeneralErrors
- )
- )
- // avoid calculating if we're in "silent" mode.
- // name length check to limit unhelpful suggestions for e.g. "x" and "b1"
- val similar = {
- if (!calcSimilar) ""
- else {
- val allowed = (
- startingIdentContext.enclosingContextChain
- flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols))
- filter (sym => sym.isTerm == name.isTermName)
- filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName)
- )
- val allowedStrings = (
- allowed.map("" + _.name).distinct.sorted
- filterNot (s => (s contains '$') || (s contains ' '))
- )
- similarString("" + name, allowedStrings)
- }
- }
- error(tree.pos, "not found: "+decodeWithKind(name, context.owner) + similar)
- }
- }
- else new AccessError(
- tree, inaccessibleSym, context.enclClass.owner.thisType,
- inaccessibleExplanation
- ).emit()
+ else identError(SymbolNotFoundError(tree, name, context.owner, startingIdentContext))
+ } else
+ identError(InferErrorGen.AccessError(
+ tree, inaccessibleSym, context.enclClass.owner.thisType, context.enclClass.owner,
+ inaccessibleExplanation
+ ))
defSym = context.owner.newErrorSymbol(name)
}
}
}
- if (defSym.owner.isPackageClass)
- pre = defSym.owner.thisType
+ if (errorContainer != null) {
+ ErrorUtils.issueTypeError(errorContainer)
+ setError(tree)
+ } else {
+ if (defSym.owner.isPackageClass)
+ pre = defSym.owner.thisType
- // Inferring classOf type parameter from expected type.
- if (defSym.isThisSym) {
- typed1(This(defSym.owner) setPos tree.pos, mode, pt)
- }
- // Inferring classOf type parameter from expected type. Otherwise an
- // actual call to the stubbed classOf method is generated, returning null.
- else if (isPredefMemberNamed(defSym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty)
- typedClassOf(tree, TypeTree(pt.typeArgs.head))
- else {
- val tree1 = (
- if (qual == EmptyTree) tree
- // atPos necessary because qualifier might come from startContext
- else atPos(tree.pos)(Select(qual, name))
- )
- val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual)
- // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right?
- stabilize(tree2, pre2, mode, pt) match {
- case accErr: Inferencer#AccessError => accErr.emit()
- case result => result
+ // Inferring classOf type parameter from expected type.
+ if (defSym.isThisSym) {
+ typed1(This(defSym.owner) setPos tree.pos, mode, pt)
+ }
+ // Inferring classOf type parameter from expected type. Otherwise an
+ // actual call to the stubbed classOf method is generated, returning null.
+ else if (isPredefMemberNamed(defSym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty)
+ typedClassOf(tree, TypeTree(pt.typeArgs.head))
+ else {
+ val tree1 = (
+ if (qual == EmptyTree) tree
+ // atPos necessary because qualifier might come from startContext
+ else atPos(tree.pos)(Select(qual, name))
+ )
+ val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual)
+ // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right?
+ stabilize(tree2, pre2, mode, pt)
}
}
}
def typedCompoundTypeTree(templ: Template) = {
val parents1 = templ.parents mapConserve (typedType(_, mode))
- if (parents1 exists (_.tpe.isError)) tree setType ErrorType
+ if (parents1 exists (_.isErrorTyped)) tree setType ErrorType
else {
- val decls = new Scope
+ val decls = newScope
//Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
@@ -4007,10 +4054,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedAppliedTypeTree(tpt: Tree, args: List[Tree]) = {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
- if (tpt1.tpe.isError) {
- setError(tree)
+ if (tpt1.isErrorTyped) {
+ tpt1
} else if (!tpt1.hasSymbol) {
- errorTree(tree, tpt1.tpe+" does not take type parameters")
+ AppliedTypeNoParametersError(tree, tpt1.tpe)
} else {
val tparams = tpt1.symbol.typeParams
if (sameLength(tparams, args)) {
@@ -4042,16 +4089,16 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// wrap the tree and include the bounds check -- refchecks will perform this check (that the beta reduction was indeed allowed) and unwrap
// we can't simply use original in refchecks because it does not contains types
// (and the only typed trees we have have been mangled so they're not quite the original tree anymore)
- checkBounds(result.pos, tpt1.tpe.prefix, tpt1.symbol.owner, tpt1.symbol.typeParams, argtypes, "")
+ checkBounds(result, tpt1.tpe.prefix, tpt1.symbol.owner, tpt1.symbol.typeParams, argtypes, "")
result // you only get to see the wrapped tree after running this check :-p
} setType (result.tpe) setPos(result.pos)
else result
} else if (tparams.isEmpty) {
- errorTree(tree, tpt1.tpe+" does not take type parameters")
+ AppliedTypeNoParametersError(tree, tpt1.tpe)
} else {
//Console.println("\{tpt1}:\{tpt1.symbol}:\{tpt1.symbol.info}")
if (settings.debug.value) Console.println(tpt1+":"+tpt1.symbol+":"+tpt1.symbol.info)//debug
- errorTree(tree, "wrong number of type arguments for "+tpt1.tpe+", should be "+tparams.length)
+ AppliedTypeWrongNumberOfArgsError(tree, tpt1, tparams)
}
}
}
@@ -4098,8 +4145,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val typer1 = newTyper(context.makeNewScope(tree, context.owner))
for (useCase <- comment.useCases) {
typer1.silent(_.typedUseCase(useCase)) match {
- case ex: TypeError =>
- unit.warning(useCase.pos, ex.msg)
+ case SilentTypeError(err) =>
+ unit.warning(useCase.pos, err.errMsg)
case _ =>
}
for (useCaseSym <- useCase.defined) {
@@ -4114,17 +4161,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
typedAnnotated(constr, typed(arg, mode, pt))
case tree @ Block(_, _) =>
- newTyper(context.makeNewScope(tree, context.owner))
- .typedBlock(tree, mode, pt)
+ typerWithLocalContext(context.makeNewScope(tree, context.owner)){
+ _.typedBlock(tree, mode, pt)
+ }
case Alternative(alts) =>
val alts1 = alts mapConserve (alt => typed(alt, mode | ALTmode, pt))
treeCopy.Alternative(tree, alts1) setType pt
case Star(elem) =>
- checkStarPatOK(tree.pos, mode)
- val elem1 = typed(elem, mode, pt)
- treeCopy.Star(tree, elem1) setType makeFullyDefined(pt)
+ if ((mode & STARmode) == 0 && !isPastTyper)
+ StarPatternWithVarargParametersError(tree)
+ treeCopy.Star(tree, typed(elem, mode, pt)) setType makeFullyDefined(pt)
case Bind(name, body) =>
typedBind(name, body)
@@ -4141,8 +4189,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case tree @ Function(_, _) =>
if (tree.symbol == NoSymbol)
tree.symbol = context.owner.newAnonymousFunctionValue(tree.pos)
-
- newTyper(context.makeNewScope(tree, tree.symbol)).typedFunction(tree, mode, pt)
+ typerWithLocalContext(context.makeNewScope(tree, tree.symbol))(_.typedFunction(tree, mode, pt))
case Assign(lhs, rhs) =>
typedAssign(lhs, rhs)
@@ -4181,17 +4228,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Typed(expr, Function(List(), EmptyTree)) =>
typedEta(checkDead(typed1(expr, mode, pt)))
- case Typed(expr, tpt @ Ident(tpnme.WILDCARD_STAR)) =>
- val expr0 = typed(expr, onlyStickyModes(mode), WildcardType)
+ case Typed(expr0, tpt @ Ident(tpnme.WILDCARD_STAR)) =>
+ val expr = typed(expr0, onlyStickyModes(mode), WildcardType)
def subArrayType(pt: Type) =
if (isValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt)
else {
val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt)
newExistentialType(List(tparam), arrayType(tparam.tpe))
}
- val (expr1, baseClass) = expr0.tpe.typeSymbol match {
- case ArrayClass => (adapt(expr0, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
- case _ => (adapt(expr0, onlyStickyModes(mode), seqType(pt)), SeqClass)
+
+ val (expr1, baseClass) = expr.tpe.typeSymbol match {
+ case ArrayClass => (adapt(expr, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
+ case _ => (adapt(expr, onlyStickyModes(mode), seqType(pt)), SeqClass)
}
expr1.tpe.baseType(baseClass) match {
case TypeRef(_, _, List(elemtp)) =>
@@ -4203,11 +4251,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Typed(expr, tpt) =>
val tpt1 = typedType(tpt, mode)
val expr1 = typed(expr, onlyStickyModes(mode), tpt1.tpe.deconst)
- val owntype =
- if (isPatternMode) inferTypedPattern(tpt1.pos, tpt1.tpe, pt)
- else tpt1.tpe
- //Console.println(typed pattern: "+tree+":"+", tp = "+tpt1.tpe+", pt = "+pt+" ==> "+owntype)//DEBUG
- treeCopy.Typed(tree, expr1, tpt1) setType owntype
+ val ownType = if (isPatternMode) inferTypedPattern(tpt1, tpt1.tpe, pt) else tpt1.tpe
+ treeCopy.Typed(tree, expr1, tpt1) setType ownType
case TypeApply(fun, args) =>
// @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
@@ -4259,12 +4304,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// convert new Array^N[T](len) for N > 1 to evidence[ClassManifest[T]].newArrayN(len)
val Some((level, manifType)) = erasure.GenericArray.unapply(tpt.tpe)
if (level > MaxArrayDims)
- error(tree.pos, "cannot create a generic multi-dimensional array of more than "+MaxArrayDims+" dimensions")
- val newArrayApp = atPos(tree.pos) {
- val manif = getManifestTree(tree.pos, manifType, false)
- new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
+ MultiDimensionalArrayError(tree)
+ else {
+ val newArrayApp = atPos(tree.pos) {
+ val manif = getManifestTree(tree, manifType, false)
+ new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
+ }
+ typed(newArrayApp, mode, pt)
}
- typed(newArrayApp, mode, pt)
case tree1 =>
tree1
}
@@ -4295,18 +4342,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val tree1 = // temporarily use `filter` and an alternative for `withFilter`
if (name == nme.withFilter)
silent(_ => typedSelect(qual1, name)) match {
- case result1: Tree =>
- result1
- case ex1: TypeError =>
+ case SilentResultValue(result) =>
+ result
+ case _ =>
silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match {
- case result2: Tree =>
+ case SilentResultValue(result2) =>
unit.deprecationWarning(
tree.pos, "`withFilter' method does not yet exist on "+qual1.tpe.widen+
", using `filter' method instead")
result2
- case ex2: TypeError =>
- reportTypeError(tree.pos, ex1)
- setError(tree)
+ case SilentTypeError(err) =>
+ WithFilterError(tree, err)
}
}
else
@@ -4339,8 +4385,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case SelectFromTypeTree(qual, selector) =>
val qual1 = typedType(qual, mode)
- if (qual1.tpe.isVolatile) error(tree.pos, "illegal type selection from volatile type "+qual.tpe)
- typedSelect(qual1, selector)
+ if (qual1.tpe.isVolatile) TypeSelectionFromVolatileTypeError(tree, qual)
+ else typedSelect(qual1, selector)
case CompoundTypeTree(templ) =>
typedCompoundTypeTree(templ)
@@ -4354,7 +4400,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
- newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt, mode)
+ typerWithLocalContext(context.makeNewScope(tree, context.owner)){
+ _.typedExistentialTypeTree(etpt, mode)
+ }
case dc@TypeTreeWithDeferredRefCheck() => dc // TODO: should we re-type the wrapped tree? then we need to change TypeTreeWithDeferredRefCheck's representation to include the wrapped tree explicitly (instead of in its closure)
case tpt @ TypeTree() =>
@@ -4366,7 +4414,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// whatever type to tree; we just have to survive until a real error message is issued.
tree setType AnyClass.tpe
case Import(expr, selectors) =>
- assert(forInteractive) // should not happen in normal circumstances.
+ assert(forInteractive, "!forInteractive") // should not happen in normal circumstances.
tree setType tree.symbol.tpe
case _ =>
abort("unexpected tree: " + tree.getClass + "\n" + tree)//debug
@@ -4404,7 +4452,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
ptLine("typing %s: pt = %s".format(ptTree(tree), pt),
"undetparams" -> context.undetparams,
"implicitsEnabled" -> context.implicitsEnabled,
- "silent" -> !context.reportGeneralErrors,
+ "silent" -> context.bufferErrors,
"context.owner" -> context.owner
)
)
@@ -4424,16 +4472,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
tree1, tree1.tpe.widen, pt, context.undetparamsString)
) //DEBUG
}
-
-// for (t <- tree1.tpe) assert(t != WildcardType)
-// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
if (!isPastTyper) signalDone(context.asInstanceOf[analyzer.Context], tree, result)
result
} catch {
case ex: TypeError =>
tree.tpe = null
+ // The only problematic case are (recoverable) cyclic reference errors which can pop up almost anywhere.
printTyping("caught %s: while typing %s".format(ex, tree)) //DEBUG
- reportTypeError(tree.pos, ex)
+
+ reportTypeError(context, tree.pos, ex)
setError(tree)
case ex: Exception =>
if (settings.debug.value) // @M causes cyclic reference error
@@ -4455,14 +4502,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- def expandMacro(tree: Tree): Tree = try {
- macroExpand(tree) match {
- case t: Tree => t
- case t => errorTree(tree, "macros must return a compiler-specific tree; returned class is: " + t.getClass)
+ def expandMacro(tree: Tree): Tree =
+ macroExpand(tree, context) match {
+ case Some(t: Tree) => t
+ case Some(t) => MacroExpandError(tree, t)
+ case None => setError(tree) // error already reported
}
- } catch {
- case ex: MacroExpandError => errorTree(tree, ex.msg)
- }
def atOwner(owner: Symbol): Typer =
newTyper(context.make(context.tree, owner))
@@ -4547,22 +4592,22 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// to see are those in the signatures. These do not need a unique object as a prefix.
// The situation is different for new's and super's, but scalac does not look deep
// enough to see those. See #3938
- error(tree.pos, restpe.prefix+" is not a legal prefix for a constructor")
- }
-
- //@M fix for #2208
- // if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef
- if(result.tpe.typeArgs.isEmpty) {
- // minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) {
- // must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not
- // designed to deal with the cycles in the scala package (ScalaObject extends
- // AnyRef, but the AnyRef type alias is entered after the scala package is
- // loaded and completed, so that ScalaObject is unpickled while AnyRef is not
- // yet defined )
- result setType(restpe)
- } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208
- // during uncurry (after refchecks), all types are normalized
- result
+ ConstructorPrefixError(tree, restpe)
+ } else {
+ //@M fix for #2208
+ // if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef
+ if (result.tpe.typeArgs.isEmpty) {
+ // minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) {
+ // must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not
+ // designed to deal with the cycles in the scala package (ScalaObject extends
+ // AnyRef, but the AnyRef type alias is entered after the scala package is
+ // loaded and completed, so that ScalaObject is unpickled while AnyRef is not
+ // yet defined )
+ result setType(restpe)
+ } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208
+ // during uncurry (after refchecks), all types are normalized
+ result
+ }
}
}
@@ -4586,11 +4631,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
true, false, context)
}
- def getManifestTree(pos: Position, tp: Type, full: Boolean): Tree = {
+ def getManifestTree(tree: Tree, tp: Type, full: Boolean): Tree = {
val manifestOpt = findManifest(tp, full)
if (manifestOpt.tree.isEmpty) {
- error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp)
- Literal(Constant(null))
+ MissingManifestError(tree, full, tp)
} else {
manifestOpt.tree
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index a7cd89621c..19b8632ed7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -25,7 +25,7 @@ trait Unapplies extends ast.TreeDSL
/** returns type list for return type of the extraction */
def unapplyTypeList(ufn: Symbol, ufntpe: Type) = {
- assert(ufn.isMethod)
+ assert(ufn.isMethod, ufn)
//Console.println("utl "+ufntpe+" "+ufntpe.typeSymbol)
ufn.name match {
case nme.unapply => unapplyTypeListFromReturnType(ufntpe)
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index a1ec90ed3f..53c767be20 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -9,7 +9,30 @@ package util
object Position {
val tabInc = 8
+
+ /** Prints the message with the given position indication. */
+ def formatMessage(posIn: Position, msg: String, shortenFile: Boolean): String = {
+ val pos = (
+ if (posIn eq null) NoPosition
+ else if (posIn.isDefined) posIn.inUltimateSource(posIn.source)
+ else posIn
+ )
+ def file = pos.source.file
+ def prefix = if (shortenFile) file.name else file.path
+
+ pos match {
+ case FakePos(fmsg) => fmsg+" "+msg
+ case NoPosition => msg
+ case _ =>
+ List(
+ "%s:%s: %s".format(prefix, pos.line, msg),
+ pos.lineContent.stripLineEnd,
+ " " * (pos.column - 1) + "^"
+ ) mkString "\n"
+ }
+ }
}
+
/** The Position class and its subclasses represent positions of ASTs and symbols.
* Except for NoPosition and FakePos, every position refers to a SourceFile
* and to an offset in the sourcefile (its `point`). For batch compilation,
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index 4405b3457b..e1ae96da8c 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -34,7 +34,7 @@ abstract class SourceFile {
* For regular source files, simply return the argument.
*/
def positionInUltimateSource(position: Position) = position
- override def toString(): String = file.name /* + ":" + content.length */
+ override def toString() = file.name
def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString
def path = file.path
@@ -61,7 +61,7 @@ object NoSourceFile extends SourceFile {
def length = -1
def offsetToLine(offset: Int) = -1
def lineToOffset(index : Int) = -1
- override def toString = "NoSourceFile"
+ override def toString = "<no source file>"
}
object NoFile extends VirtualFile("<no file>", "<no file>")
diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala
index e9cd474b82..fee2c5a273 100644
--- a/src/detach/plugin/scala/tools/detach/Detach.scala
+++ b/src/detach/plugin/scala/tools/detach/Detach.scala
@@ -735,7 +735,7 @@ abstract class Detach extends PluginComponent
iface.sourceFile = clazz.sourceFile
iface setFlag (ABSTRACT | TRAIT | INTERFACE) // Java interface
val iparents = List(ObjectClass.tpe, RemoteClass.tpe, ScalaObjectClass.tpe)
- iface setInfo ClassInfoType(iparents, new Scope, iface)
+ iface setInfo ClassInfoType(iparents, newScope, iface)
// methods must throw RemoteException
iface addAnnotation remoteAnnotationInfo
@@ -749,7 +749,7 @@ abstract class Detach extends PluginComponent
// Variant 2: un-/exportObject
//val cparents = List(ObjectClass.tpe, iface.tpe,
// UnreferencedClass.tpe, ScalaObjectClass.tpe)
- iclaz setInfo ClassInfoType(cparents, new Scope, iclaz)
+ iclaz setInfo ClassInfoType(cparents, newScope, iclaz)
val proxy = (iface, iclaz, new mutable.HashMap[Symbol, Symbol])
proxies(clazz) = proxy
proxy
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 6d84b4276b..02298ef096 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -151,8 +151,9 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] with GenSeqLike[A, Repr]
def next(): Repr = {
if (!hasNext)
Iterator.empty.next
-
- val result = (self.newBuilder ++= elms.toList).result
+
+ val forcedElms = new mutable.ArrayBuffer[A](elms.size) ++= elms
+ val result = (self.newBuilder ++= forcedElms).result
var i = idxs.length - 2
while(i >= 0 && idxs(i) >= idxs(i+1))
i -= 1
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 55ce8fa822..9cde20f1df 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -111,7 +111,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
// TODO: add HashMap2, HashMap3, ...
- class HashMap1[A,+B](private[HashMap] var key: A, private[HashMap] var hash: Int, private[collection] var value: (B @uV), private[collection] var kv: (A,B @uV)) extends HashMap[A,B] {
+ class HashMap1[A,+B](private[collection] val key: A, private[collection] val hash: Int, private[collection] val value: (B @uV), private[collection] var kv: (A,B @uV)) extends HashMap[A,B] {
override def size = 1
private[collection] def getKey = key
@@ -176,13 +176,14 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def iterator: Iterator[(A,B)] = Iterator(ensurePair)
override def foreach[U](f: ((A, B)) => U): Unit = f(ensurePair)
+ // this method may be called multiple times in a multithreaded environment, but that's ok
private[HashMap] def ensurePair: (A,B) = if (kv ne null) kv else { kv = (key, value); kv }
protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = {
that.updated0(key, hash, level, value, kv, merger)
}
}
- private[collection] class HashMapCollision1[A, +B](private[HashMap] var hash: Int, var kvs: ListMap[A, B @uV])
+ private[collection] class HashMapCollision1[A, +B](private[collection] val hash: Int, val kvs: ListMap[A, B @uV])
extends HashMap[A, B @uV] {
override def size = kvs.size
@@ -227,9 +228,9 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
}
class HashTrieMap[A, +B](
- private[HashMap] var bitmap: Int,
- private[collection] var elems: Array[HashMap[A, B @uV]],
- private[HashMap] var size0: Int
+ private[collection] val bitmap: Int,
+ private[collection] val elems: Array[HashMap[A, B @uV]],
+ private[collection] val size0: Int
) extends HashMap[A, B @uV] {
/*
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 8cb19d4f31..79d2fb71cc 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -105,7 +105,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
// TODO: add HashSet2, HashSet3, ...
- class HashSet1[A](private[HashSet] var key: A, private[HashSet] var hash: Int) extends HashSet[A] {
+ class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends HashSet[A] {
override def size = 1
override def get0(key: A, hash: Int, level: Int): Boolean =
@@ -131,7 +131,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override def foreach[U](f: A => U): Unit = f(key)
}
- private[immutable] class HashSetCollision1[A](private[HashSet] var hash: Int, var ks: ListSet[A])
+ private[immutable] class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A])
extends HashSet[A] {
override def size = ks.size
@@ -178,7 +178,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
- class HashTrieSet[A](private var bitmap: Int, private[collection] var elems: Array[HashSet[A]], private var size0: Int)
+ class HashTrieSet[A](private val bitmap: Int, private[collection] val elems: Array[HashSet[A]], private val size0: Int)
extends HashSet[A] {
override def size = size0
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index c92c0268b6..7537558f0b 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -286,18 +286,36 @@ extends collection.AbstractSeq[Int]
object Range {
private[immutable] val MAX_PRINT = 512 // some arbitrary value
- /** Counts in "Long arithmetic" so we can recognize overflow.
+ /** Counts the number of range elements.
+ * @pre step != 0
+ * If the size of the range exceeds Int.MaxValue, the
+ * result will be negative.
*/
- def count(start: Int, end: Int, step: Int): Int =
- count(start, end, step, false)
-
def count(start: Int, end: Int, step: Int, isInclusive: Boolean): Int = {
- // faster path for the common counting range
- if (start >= 0 && end > start && end < scala.Int.MaxValue && step == 1)
- (end - start) + ( if (isInclusive) 1 else 0 )
- else
- NumericRange.count[Long](start, end, step, isInclusive)
+ if (step == 0)
+ throw new IllegalArgumentException("step cannot be 0.")
+
+ val isEmpty = (
+ if (start == end) !isInclusive
+ else if (start < end) step < 0
+ else step > 0
+ )
+ if (isEmpty) 0
+ else {
+ // Counts with Longs so we can recognize too-large ranges.
+ val gap: Long = end.toLong - start.toLong
+ val jumps: Long = gap / step
+ // Whether the size of this range is one larger than the
+ // number of full-sized jumps.
+ val hasStub = isInclusive || (gap % step != 0)
+ val result: Long = jumps + ( if (hasStub) 1 else 0 )
+
+ if (result > scala.Int.MaxValue) -1
+ else result.toInt
+ }
}
+ def count(start: Int, end: Int, step: Int): Int =
+ count(start, end, step, false)
class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
// override def par = new ParRange(this)
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index e6587f9615..2eb2f8eb09 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -929,13 +929,19 @@ self =>
/** A specialized, extra-lazy implementation of a stream iterator, so it can
* iterate as lazily as it traverses the tail.
*/
-final class StreamIterator[+A](self: Stream[A]) extends AbstractIterator[A] with Iterator[A] {
+final class StreamIterator[+A] private() extends AbstractIterator[A] with Iterator[A] {
+ def this(self: Stream[A]) {
+ this()
+ these = new LazyCell(self)
+ }
+
// A call-by-need cell.
class LazyCell(st: => Stream[A]) {
lazy val v = st
}
- private var these = new LazyCell(self)
+ private var these: LazyCell = _
+
def hasNext: Boolean = these.v.nonEmpty
def next(): A =
if (isEmpty) Iterator.empty.next
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index 90b64c17f9..390bd72ab5 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -895,7 +895,8 @@ self: ParIterableLike[T, Repr, Sequential] =>
@volatile var result: R1 = null.asInstanceOf[R1]
def map(r: R): R1
def leaf(prevr: Option[R1]) = {
- result = map(executeAndWaitResult(inner))
+ val initialResult = executeAndWaitResult(inner)
+ result = map(initialResult)
}
private[parallel] override def signalAbort() {
inner.signalAbort
diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala
index 873291fb2d..b705909cad 100644
--- a/src/library/scala/collection/parallel/Tasks.scala
+++ b/src/library/scala/collection/parallel/Tasks.scala
@@ -88,7 +88,7 @@ trait Tasks {
if (this.throwable == null && that.throwable == null && (this.result == null || that.result == null)) {
println("This: " + this + ", thr=" + this.throwable + "; merged with " + that + ", thr=" + that.throwable)
} else if (this.throwable != null || that.throwable != null) {
- println("merging this thr: " + this.throwable + " with " + that + ", thr=" + that.throwable)
+ println("merging this: " + this + " with thr: " + this.throwable + " with " + that + ", thr=" + that.throwable)
}
}
@@ -118,7 +118,7 @@ trait Tasks {
/** Try to cancel the task.
* @return `true` if cancellation is successful.
*/
- def tryCancel: Boolean
+ def tryCancel(): Boolean
/** If the task has been cancelled successfully, those syncing on it may
* automatically be notified, depending on the implementation. If they
* aren't, this release method should be called after processing the
@@ -161,32 +161,39 @@ trait AdaptiveWorkStealingTasks extends Tasks {
def split: Seq[TaskImpl[R, Tp]]
- def compute() = if (body.shouldSplitFurther) internal else body.tryLeaf(None)
+ def compute() = if (body.shouldSplitFurther) {
+ internal()
+ release()
+ } else {
+ body.tryLeaf(None)
+ release()
+ }
def internal() = {
var last = spawnSubtasks()
-
+
last.body.tryLeaf(None)
+ last.release()
body.result = last.body.result
body.throwable = last.body.throwable
-
+
while (last.next != null) {
// val lastresult = Option(last.body.result)
val beforelast = last
last = last.next
- if (last.tryCancel) {
+ if (last.tryCancel()) {
// println("Done with " + beforelast.body + ", next direct is " + last.body)
last.body.tryLeaf(Some(body.result))
- last.release
+ last.release()
} else {
// println("Done with " + beforelast.body + ", next sync is " + last.body)
- last.sync
+ last.sync()
}
// println("Merging " + body + " with " + last.body)
body.tryMerge(last.body.repr)
}
}
-
+
def spawnSubtasks() = {
var last: TaskImpl[R, Tp] = null
var head: TaskImpl[R, Tp] = this
@@ -196,7 +203,7 @@ trait AdaptiveWorkStealingTasks extends Tasks {
for (t <- subtasks.tail.reverse) {
t.next = last
last = t
- t.start
+ t.start()
}
} while (head.body.shouldSplitFurther);
head.next = last
@@ -230,12 +237,12 @@ trait ThreadPoolTasks extends Tasks {
// utb: var future: Future[_] = null
@volatile var owned = false
@volatile var completed = false
-
+
def start() = synchronized {
// debuglog("Starting " + body)
// utb: future = executor.submit(this)
executor.synchronized {
- incrTasks
+ incrTasks()
executor.submit(this)
}
}
@@ -249,9 +256,9 @@ trait ThreadPoolTasks extends Tasks {
//assert(executor.getCorePoolSize == (coresize + 1))
}
}
- if (!completed) this.wait
+ while (!completed) this.wait
}
- def tryCancel = synchronized {
+ def tryCancel() = synchronized {
// utb: future.cancel(false)
if (!owned) {
// debuglog("Cancelling " + body)
@@ -259,7 +266,7 @@ trait ThreadPoolTasks extends Tasks {
true
} else false
}
- def run = {
+ def run() = {
// utb: compute
var isOkToRun = false
synchronized {
@@ -270,17 +277,17 @@ trait ThreadPoolTasks extends Tasks {
}
if (isOkToRun) {
// debuglog("Running body of " + body)
- compute
- release
+ compute()
} else {
// just skip
// debuglog("skipping body of " + body)
}
}
- override def release = synchronized {
+ override def release() = synchronized {
+ //println("releasing: " + this + ", body: " + this.body)
completed = true
executor.synchronized {
- decrTasks
+ decrTasks()
}
this.notifyAll
}
@@ -305,10 +312,10 @@ trait ThreadPoolTasks extends Tasks {
val t = newTaskImpl(task)
// debuglog("-----------> Executing without wait: " + task)
- t.start
+ t.start()
() => {
- t.sync
+ t.sync()
t.body.forwardThrowable
t.body.result
}
@@ -318,9 +325,9 @@ trait ThreadPoolTasks extends Tasks {
val t = newTaskImpl(task)
// debuglog("-----------> Executing with wait: " + task)
- t.start
-
- t.sync
+ t.start()
+
+ t.sync()
t.body.forwardThrowable
t.body.result
}
@@ -369,7 +376,7 @@ trait FutureThreadPoolTasks extends Tasks {
def sync() = future.get
def tryCancel = false
def run = {
- compute
+ compute()
}
}
diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
index 1fec522a93..e785932933 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
@@ -304,14 +304,21 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], (K, V), Has
evaluateCombiners(trie)
trie.asInstanceOf[HashMap[K, Repr]]
}
- private def evaluateCombiners(trie: HashMap[K, Combiner[V, Repr]]): Unit = trie match {
+ private def evaluateCombiners(trie: HashMap[K, Combiner[V, Repr]]): HashMap[K, Repr] = trie match {
case hm1: HashMap.HashMap1[_, _] =>
- hm1.asInstanceOf[HashMap.HashMap1[K, Repr]].value = hm1.value.result
- hm1.kv = null
+ val evaledvalue = hm1.value.result
+ new HashMap.HashMap1[K, Repr](hm1.key, hm1.hash, evaledvalue, null)
case hmc: HashMap.HashMapCollision1[_, _] =>
- hmc.asInstanceOf[HashMap.HashMapCollision1[K, Repr]].kvs = hmc.kvs map { p => (p._1, p._2.result) }
- case htm: HashMap.HashTrieMap[_, _] =>
- for (hm <- htm.elems) evaluateCombiners(hm)
+ val evaledkvs = hmc.kvs map { p => (p._1, p._2.result) }
+ new HashMap.HashMapCollision1[K, Repr](hmc.hash, evaledkvs)
+ case htm: HashMap.HashTrieMap[k, v] =>
+ var i = 0
+ while (i < htm.elems.length) {
+ htm.elems(i) = evaluateCombiners(htm.elems(i)).asInstanceOf[HashMap[k, v]]
+ i += 1
+ }
+ htm.asInstanceOf[HashMap[K, Repr]]
+ case empty => empty.asInstanceOf[HashMap[K, Repr]]
}
def split = {
val fp = howmany / 2
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index addc366072..f152629c50 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -117,7 +117,7 @@ package parallel {
/** Composite throwable - thrown when multiple exceptions are thrown at the same time. */
final case class CompositeThrowable(
val throwables: Set[Throwable]
- ) extends Throwable(
+ ) extends Exception(
"Multiple exceptions thrown during a parallel computation: " +
throwables.map(t => t + "\n" + t.getStackTrace.take(10).++("...").mkString("\n")).mkString("\n\n")
)
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 361e02cb16..8a53afaa62 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -309,7 +309,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
override def byteValue = intValue.toByte
/** Converts this BigInt to a <tt>short</tt>.
- * If the BigInt is too big to fit in a byte, only the low-order 16 bits are returned.
+ * If the BigInt is too big to fit in a short, only the low-order 16 bits are returned.
* Note that this conversion can lose information about the overall magnitude of the
* BigInt value as well as return a result with the opposite sign.
*/
@@ -323,7 +323,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
def charValue = intValue.toChar
/** Converts this BigInt to an <tt>int</tt>.
- * If the BigInt is too big to fit in a char, only the low-order 32 bits
+ * If the BigInt is too big to fit in a int, only the low-order 32 bits
* are returned. Note that this conversion can lose information about the
* overall magnitude of the BigInt value as well as return a result with
* the opposite sign.
@@ -331,7 +331,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
def intValue = this.bigInteger.intValue
/** Converts this BigInt to a <tt>long</tt>.
- * If the BigInt is too big to fit in a char, only the low-order 64 bits
+ * If the BigInt is too big to fit in a long, only the low-order 64 bits
* are returned. Note that this conversion can lose information about the
* overall magnitude of the BigInt value as well as return a result with
* the opposite sign.
diff --git a/src/library/scala/reflect/api/Names.scala b/src/library/scala/reflect/api/Names.scala
index e226d2265a..9498f0af36 100755
--- a/src/library/scala/reflect/api/Names.scala
+++ b/src/library/scala/reflect/api/Names.scala
@@ -1,32 +1,59 @@
package scala.reflect
package api
+/** A trait that manages names.
+ * A name is a string in one of two name universes: terms and types.
+ * The same string can be a name in both universes.
+ * Two names are equal if they represent the same string and they are
+ * members of the same universe.
+ *
+ * Names are interned. That is, for two names `name11 and `name2`,
+ * `name1 == name2` implies `name1 eq name2`.
+ */
trait Names {
-
+
+ /** The abstract type of names */
type Name >: Null <: AbsName
+
+ /** The abstract type of names representing terms */
type TypeName <: Name
+
+ /** The abstract type of names representing types */
type TermName <: Name
abstract class AbsName {
+ /** Is this name a term name? */
def isTermName: Boolean
+
+ /** Is this name a type name? */
def isTypeName: Boolean
+
+ /** Returns a term name that represents the same string as this name */
def toTermName: TermName
+
+ /** Returns a type name that represents the same string as this name */
def toTypeName: TypeName
- /** Replace all occurrences of $op_names in this name by corresponding operator symbols.
+ /** Replaces all occurrences of $op_names in this name by corresponding operator symbols.
* Example: `foo_+=` becomes `foo_$plus$eq`.
*/
def decode: String
- /** Replace all occurrences of operator symbols in this name by corresponding $op_names.
+ /** Replaces all occurrences of operator symbols in this name by corresponding $op_names.
* Example: `foo_$plus$eq` becomes `foo_+=`
*/
def encode: Name
}
+ /** Create a new term name.
+ */
def newTermName(s: String): TermName
+
+ /** Creates a new type name.
+ */
def newTypeName(s: String): TypeName
def EmptyTermName: TermName = newTermName("")
+
def EmptyTypeName: TypeName = EmptyTermName.toTypeName
}
diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala
index 6b480ab83d..08071660a2 100755
--- a/src/library/scala/reflect/api/StandardDefinitions.scala
+++ b/src/library/scala/reflect/api/StandardDefinitions.scala
@@ -12,9 +12,7 @@ trait StandardDefinitions { self: Universe =>
abstract class AbsDefinitions {
// outer packages and their classes
- // Under consideration
- // def RootPackage: Symbol
-
+ def RootPackage: Symbol
def RootClass: Symbol
def EmptyPackage: Symbol
def EmptyPackageClass: Symbol
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 8b4b170847..01c1a0f2ae 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -15,7 +15,14 @@ trait Symbols { self: Universe =>
*/
def hasModifier(mod: Modifier.Value): Boolean
- /** The owner of this symbol.
+ /** The owner of this symbol. This is the symbol
+ * that directly contains the current symbol's definition.
+ * The `NoSymbol` symbol does not have an owner, and calling this method
+ * on one causes an internal error.
+ * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]]
+ * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`.
+ * Every other symbol has a chain of owners that ends in
+ * [[scala.reflect.api.mirror.RootClass]].
*/
def owner: Symbol
@@ -74,23 +81,6 @@ trait Symbols { self: Universe =>
*/
def annotations: List[self.AnnotationInfo]
- /** The type of the symbol
- */
- def tpe: Type
-
- /** The info of the symbol. This is like tpe, except for class symbols where the `info`
- * describes the contents of the class whereas the `tpe` is a reference to the class.
- */
- def info: Type
-
- /** If this symbol is a class or trait, its self type, otherwise the type of the symbol itself
- */
- def typeOfThis: Type
-
- /** The type `C.this`, where `C` is the current class.
- */
- def thisType: Type
-
/** For a class: the module or case class factory with the same name in the same package.
* For all others: NoSymbol
*/
@@ -114,20 +104,43 @@ trait Symbols { self: Universe =>
/** The top-level class containing this symbol. */
def toplevelClass: Symbol
- /** The next enclosing class */
+ /** The next enclosing class, or `NoSymbol` if none exists */
def enclClass : Symbol
- /** The next enclosing method */
+ /** The next enclosing method, or `NoSymbol` if none exists */
def enclMethod : Symbol
+ /** Does this symbol represent the definition of term?
+ * Note that every symbol is either a term or a type.
+ * So for every symbol `sym`, either `sym.isTerm` is true
+ * or `sym.isType` is true.
+ */
def isTerm : Boolean
+
+ /** Does this symbol represent the definition of type?
+ * Note that every symbol is either a term or a type.
+ * So for every symbol `sym`, either `sym.isTerm` is true
+ * or `sym.isType` is true.
+ */
def isType : Boolean
+
+ /** Does this symbol represent the definition of class?
+ * If yes, `isType` is also guaranteed to be true.
+ */
def isClass : Boolean
+
+ /** Does this symbol represent the definition of a type alias?
+ * If yes, `isType` is also guaranteed to be true.
+ */
def isAliasType : Boolean
+
+ /** Does this symbol represent the definition of an abstract type?
+ * If yes, `isType` is also guaranteed to be true.
+ */
def isAbstractType : Boolean
/** The type signature of this symbol.
- * Note if symbol is a member of a class, one almost always is interested
+ * Note if the symbol is a member of a class, one almost always is interested
* in `typeSigIn` with a site type instead.
*/
def typeSig: Type
@@ -136,22 +149,44 @@ trait Symbols { self: Universe =>
*/
def typeSigIn(site: Type): Type
- /** The type constructor corresponding to this type symbol.
- */
- def asTypeConstructor: Type // needed by LiftCode
-
- /** A type reference that refers to this type symbol
+ /** A type reference that refers to this type symbol
* Note if symbol is a member of a class, one almost always is interested
* in `asTypeIn` with a site type instead.
+ *
+ * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
+ * `C`. Then `C.asType` is the type `C[T]`.
+ *
+ * By contrast, `C.typeSig` would be a type signature of form
+ * `PolyType(ClassInfoType(...))` that describes type parameters, value
+ * parameters, parent types, and members of `C`.
*/
def asType: Type
- /** A type reference that refers to this type symbol seen as a member of given type `site`.
+ /** A type reference that refers to this type symbol seen
+ * as a member of given type `site`.
*/
def asTypeIn(site: Type): Type
+ /** The type constructor corresponding to this type symbol.
+ * This is different from `asType` in that type parameters
+ * are part of results of `asType`, but not of `asTypeConstructor`.
+ *
+ * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
+ * `C`. Then `C.asType` is the type `C[T]`, but `C.asTypeCponstructor` is `C`.
+ */
+ def asTypeConstructor: Type // needed by LiftCode
+
+ /** If this symbol is a class or trait, its self type, otherwise the type
+ * of the symbol itself.
+ */
+ def typeOfThis: Type
+
+ /** If this symbol is a class, the type `C.this`, otherwise `NoPrefix`.
+ */
+ def thisType: Type
+
/** A fresh symbol with given name `name`, position `pos` and flags `flags` that has
- * the current symbol as its owner.
+ * the current symbol as its owner.
*/
def newNestedSymbol(name: Name, pos: Position, flags: Long): Symbol // needed by LiftCode
diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala
index 2394925657..03b043c188 100644
--- a/src/library/scala/reflect/api/Trees.scala
+++ b/src/library/scala/reflect/api/Trees.scala
@@ -8,9 +8,8 @@ package api
import scala.collection.mutable.ListBuffer
-//import scala.tools.nsc.util.{ FreshNameCreator, HashSet, SourceFile }
-
-trait Trees /*extends reflect.generic.Trees*/ { self: Universe =>
+// Syncnote: Trees are currently not thread-safe.
+trait Trees { self: Universe =>
private[scala] var nodeCount = 0
@@ -549,7 +548,7 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe =>
Select(qualifier, sym.name) setSymbol sym
/** Identifier <name> */
- case class Ident(name: Name) extends RefTree { }
+ case class Ident(name: Name) extends RefTree
def Ident(name: String): Ident =
Ident(newTermName(name))
diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala
index 4b959649fd..6185a788ae 100755
--- a/src/library/scala/reflect/api/Types.scala
+++ b/src/library/scala/reflect/api/Types.scala
@@ -20,7 +20,7 @@ trait Types { self: Universe =>
/** The collection of declarations in this type
*/
- def allDeclarations: Iterable[Symbol]
+ def declarations: Iterable[Symbol]
/** The member with given name, either directly declared or inherited,
* an OverloadedSymbol if several exist, NoSymbol if none exist.
@@ -36,7 +36,7 @@ trait Types { self: Universe =>
* Members appear in the linearization order of their owners.
* Members with the same owner appear in reverse order of their declarations.
*/
- def allMembers: Iterable[Symbol]
+ def members: Iterable[Symbol]
/** An iterable containing all non-private members of this type (directly declared or inherited)
* Members appear in the linearization order of their owners.
@@ -125,19 +125,23 @@ trait Types { self: Universe =>
/** Does this type contain a reference to given symbol? */
def contains(sym: Symbol): Boolean
- }
- /** This class declares methods that are visible in a `SingleType`.
- */
- trait AbsSingletonType extends AbsType {
+ /** If this is a compound type, the list of its parent types;
+ * otherwise the empty list
+ */
+ def parents: List[Type]
- /** The type underlying a singleton type */
+ /** If this is a singleton type, returns the type underlying it;
+ * otherwise returns this type itself.
+ */
def underlying: Type
- /** Widen from singleton type to its underlying non-singleton
- * base type by applying one or more `underlying` dereferences,
- * identity for all other types.
+ /** If this is a singleton type, widen it to its nearest underlying non-singleton
+ * base type by applying one or more `underlying` dereferences.
+ * If this is not a singlecon type, returns this type itself.
*
+ * Example:
+ *
* class Outer { class C ; val x: C }
* val o: Outer
* <o.x.type>.widen = o.C
@@ -145,19 +149,6 @@ trait Types { self: Universe =>
def widen: Type
}
- /** This class declares methods that are visible in a `CompoundType` (i.e.
- * a class/trait/object template or refined type of the form
- * {{{
- * P_1 with ... with P_m { D_1; ...; D_n }
- * }}}
- * P_n
- */
- trait AbsCompoundType extends AbsType {
-
- /** The list of parent types of this compound type */
- def parents: List[Type]
- }
-
/** The type of Scala types, and also Scala type signatures.
* (No difference is internally made between the two).
*/
@@ -293,7 +284,7 @@ trait Types { self: Universe =>
/** A subtype of Type representing refined types as well as `ClassInfo` signatures.
*/
- type CompoundType <: /*AbsCompoundType with*/ Type
+ type CompoundType <: Type
/** The `RefinedType` type defines types of any of the forms on the left,
* with their RefinedType representations to the right.
diff --git a/src/partest-alternative/README b/src/partest-alternative/README
deleted file mode 100644
index c7673fe2f8..0000000000
--- a/src/partest-alternative/README
+++ /dev/null
@@ -1,50 +0,0 @@
-If you're looking for something to read, I suggest running ../test/partest
-with no arguments, which at this moment prints this:
-
-Usage: partest [<options>] [<test> <test> ...]
- <test>: a path to a test designator, typically a .scala file or a directory.
- Examples: files/pos/test1.scala, files/res/bug785
-
- Test categories:
- --all run all tests (default, unless no options given)
- --pos Compile files that are expected to build
- --neg Compile files that are expected to fail
- --run Test JVM backend
- --jvm Test JVM backend
- --res Run resident compiler scenarii
- --buildmanager Run Build Manager scenarii
- --scalacheck Run Scalacheck tests
- --script Run script files
- --shootout Run shootout tests
- --scalap Run scalap tests
-
- Test "smart" categories:
- --grep run all tests with a source file containing <expr>
- --failed run all tests which failed on the last run
-
- Specifying paths and additional flags, ~ means repository root:
- --rootdir path from ~ to partest (default: test)
- --builddir path from ~ to test build (default: build/pack)
- --srcdir path from --rootdir to sources (default: files)
- --javaopts flags to java on all runs (overrides JAVA_OPTS)
- --scalacopts flags to scalac on all tests (overrides SCALAC_OPTS)
- --pack alias for --builddir build/pack
- --quick alias for --builddir build/quick
-
- Options influencing output:
- --trace show the individual steps taken by each test
- --show-diff show diff between log and check file
- --show-log show log on failures
- --dry-run do not run tests, only show their traces.
- --terse be less verbose (almost silent except for failures)
- --verbose be more verbose (additive with --trace)
- --debug maximum debugging output
- --ansi print output in color
-
- Other options:
- --timeout Timeout in seconds
- --cleanup delete all stale files and dirs before run
- --nocleanup do not delete any logfiles or object dirs
- --stats collect and print statistics about the tests
- --validate examine test filesystem for inconsistencies
- --version print version
diff --git a/src/partest-alternative/scala/tools/partest/Actions.scala b/src/partest-alternative/scala/tools/partest/Actions.scala
deleted file mode 100644
index 9a64edeadc..0000000000
--- a/src/partest-alternative/scala/tools/partest/Actions.scala
+++ /dev/null
@@ -1,189 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import util._
-import nsc.io._
-import scala.sys.process._
-
-trait Actions {
- partest: Universe =>
-
- class TestSequence(val actions: List[TestStep]) extends AbsTestSequence {
- }
-
- implicit def createSequence(xs: List[TestStep]) = new TestSequence(xs)
-
- trait ExecSupport {
- self: TestEntity =>
-
- def execEnv: Map[String, String] = {
- val map = assembleEnvironment()
- val cwd = execCwd.toList map ("CWD" -> _.path)
-
- map ++ cwd
- }
- def execCwd = if (commandFile.isFile) Some(sourcesDir) else None
-
- def runExec(args: List[String]): Boolean = {
- val cmd = fromArgs(args)
-
- if (isVerbose) {
- trace("runExec: " + execEnv.mkString("ENV(", "\n", "\n)"))
- execCwd foreach (x => trace("CWD(" + x + ")"))
- }
-
- trace("runExec: " + cmd)
- isDryRun || execAndLog(cmd)
- }
-
- /** Exec a process to run a command. Assumes 0 exit value is success.
- * Of necessity, also treats no available exit value as success.
- */
- protected def execAndLog(cmd: String) = (cmd #> logFile.jfile !) == 0
- }
-
- trait ScriptableTest {
- self: TestEntity =>
-
- /** Translates a line from a .cmds file into a teststep.
- */
- def customTestStep(line: String): TestStep = {
- trace("customTestStep: " + line)
- val (cmd, rest) = line span (x => !Character.isWhitespace(x))
- def qualify(name: String) = sourcesDir / name path
- val args = toArgs(rest) map qualify
- def fail: TestStep = (_: TestEntity) => error("Parse error: did not understand '%s'" format line)
-
- val f: TestEntity => Boolean = cmd match {
- case "scalac" => _ scalac args
- case "javac" => _ javac args
- case "scala" => _ runScala args
- case _ => fail
- }
- f
- }
- }
-
- trait CompilableTest extends CompileExecSupport {
- self: TestEntity =>
-
- def sourceFiles = location.walk collect { case f: File if isJavaOrScala(f) => f } toList
- def allSources = sourceFiles map (_.path)
- def scalaSources = sourceFiles filter isScala map (_.path)
- def javaSources = sourceFiles filter isJava map (_.path)
-
- /** If there are mixed java and scala files, the standard compilation
- * sequence is:
- *
- * scalac with all files
- * javac with only java files
- * scalac with only scala files
- *
- * This should be expanded to encompass other strategies so we know how
- * well they're working or not working - notably, it would be very useful
- * to know exactly when and how two-pass compilation fails.
- */
- def compile() = {
- trace("compile: " + sourceFiles)
-
- def compileJava() = javac(javaSources)
- def compileScala() = scalac(scalaSources)
- def compileAll() = scalac(allSources)
- def compileMixed() = compileAll() && compileJava() && compileScala()
-
- if (scalaSources.nonEmpty && javaSources.nonEmpty) compileMixed()
- else compileScala()
- }
- }
-
- trait DiffableTest {
- self: TestEntity =>
-
- def checkFile: File = withExtension("check").toFile
- def checkFileRequired =
- returning(checkFile.isFile)(res => if (!res) warnAndLog("A checkFile at '%s' is mandatory.\n" format checkFile.path))
-
- lazy val sourceFileNames = sourceFiles map (_.name)
-
- /** Given the difficulty of verifying that any selective approach works
- * everywhere, the algorithm now is to look for the name of any known
- * source file for this test, and if seen, remove all the non-whitespace
- * preceding it. (Paths with whitespace don't work anyway.) This should
- * wipe out all slashes, backslashes, C:\, cygwin/windows differences,
- * and whatever else makes a simple diff not simple.
- *
- * The log and check file are both transformed, which I don't think is
- * correct -- only the log should be -- but doing it this way until I
- * can clarify martin's comments in #3283.
- */
- def normalizePaths(s: String) =
- sourceFileNames.foldLeft(s)((res, name) => res.replaceAll("""\S+\Q%s\E""" format name, name))
-
- /** The default cleanup normalizes paths relative to sourcesDir,
- * absorbs line terminator differences by going to lines and back,
- * and trims leading or trailing whitespace.
- */
- def diffCleanup(f: File) = safeLines(f) map normalizePaths mkString "\n" trim
-
- /** diffFiles requires actual Files as arguments but the output we want
- * is the post-processed versions of log/check, so we resort to tempfiles.
- */
- lazy val diffOutput = {
- if (!checkFile.exists) "" else {
- val input = diffCleanup(checkFile)
- val output = diffCleanup(logFile)
- def asFile(s: String) = returning(File.makeTemp("partest-diff"))(_ writeAll s)
-
- if (input == output) ""
- else diffFiles(asFile(input), asFile(output))
- }
- }
- private def checkTraceName = tracePath(checkFile)
- private def logTraceName = tracePath(logFile)
- private def isDiffConfirmed = checkFile.exists && (diffOutput == "")
-
- private def sendTraceMsg() {
- def result =
- if (isDryRun) ""
- else if (isDiffConfirmed) " [passed]"
- else if (checkFile.exists) " [failed]"
- else " [unchecked]"
-
- trace("diff %s %s%s".format(checkTraceName, logTraceName, result))
- }
-
- /** If optional is true, a missing check file is considered
- * a successful diff. Necessary since many categories use
- * checkfiles in an ad hoc manner.
- */
- def runDiff() = {
- sendTraceMsg()
-
- def updateCheck = (
- isUpdateCheck && {
- val formatStr = "** diff %s %s: " + (
- if (checkFile.exists) "failed, updating '%s' and marking as passed."
- else if (diffOutput == "") "not creating checkFile at '%s' as there is no output."
- else "was unchecked, creating '%s' for future tests."
- ) + "\n"
-
- normal(formatStr.format(checkTraceName, logTraceName, checkFile.path))
- if (diffOutput != "") normal(diffOutput)
-
- checkFile.writeAll(diffCleanup(logFile), "\n")
- true
- }
- )
-
- isDryRun || isDiffConfirmed || (updateCheck || !checkFile.exists)
- }
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Alarms.scala b/src/partest-alternative/scala/tools/partest/Alarms.scala
deleted file mode 100644
index ef30d13705..0000000000
--- a/src/partest-alternative/scala/tools/partest/Alarms.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools
-package partest
-
-import java.util.{ Timer, TimerTask }
-
-trait Alarms {
- self: Universe =>
-
- def interruptMeIn[T](debugMsg: String, seconds: Int)(body: => T): Option[T] = {
- val thisThread = currentThread
- val alarm = new SimpleAlarm(seconds * 1000) set thisThread.interrupt()
- debug("interruptMeIn(%d) '%s'".format(seconds, debugMsg))
-
- try { Some(body) }
- catch { case _: InterruptedException => debug("Received interrupted exception.") ; None }
- finally { debug("Cancelling interruptMeIn '%s'" format debugMsg) ; alarm.cancel() ; Thread.interrupted() }
- }
-
- case class AlarmerAction(secs: Int, action: () => Unit) extends Runnable {
- override def run() = action()
- }
-
- /** Set any number of alarms up with tuples of the form:
- * seconds to alarm -> Function0[Unit] to execute
- */
- class Alarmer(alarms: AlarmerAction*) {
- import java.util.concurrent._
-
- val exec = Executors.newSingleThreadScheduledExecutor()
- alarms foreach (x => exec.schedule(x, x.secs, TimeUnit.SECONDS))
- exec.shutdown()
-
- def cancelAll() = exec.shutdownNow()
- }
-
- class SimpleAlarm(timeout: Long) {
- private val alarm = new Timer
-
- /** Start a timer, running the given body if it goes off.
- */
- def set(body: => Unit) = returning(new TimerTask { def run() = body })(alarm.schedule(_, timeout))
-
- /** Cancel the timer.
- */
- def cancel() = alarm.cancel()
- }
-
- trait TestAlarms {
- test: TestEntity =>
-
- private def warning1 = AlarmerAction(testWarning, () => warning(
- """|I've been waiting %s seconds for this to complete:
- | %s
- |It may be stuck, or if not, it should be broken into smaller tests.
- |""".stripMargin.format(testWarning, test))
- )
- private def warning2 = AlarmerAction(testWarning * 2, () => warning(
- """|Now I've been waiting %s seconds for this to complete:
- | %s
- |If partest seems hung it would be a good place to look.
- |""".stripMargin.format(testWarning * 2, test))
- )
-
- def startAlarms(onTimeout: => Unit) =
- if (isNoAlarms) new Alarmer() // for alarm debugging
- else new Alarmer(Seq(warning1, warning2, AlarmerAction(testTimeout, () => onTimeout)): _*)
- }
-
- // Thread.setDefaultUncaughtExceptionHandler(new UncaughtException)
- // class UncaughtException extends Thread.UncaughtExceptionHandler {
- // def uncaughtException(t: Thread, e: Throwable) {
- // Console.println("Uncaught in %s: %s".format(t, e))
- // }
- // }
- //
- // lazy val logger = File("/tmp/partest.log").bufferedWriter()
- // def flog(msg: String) = logger synchronized {
- // logger write (msg + "\n")
- // logger.flush()
- // }
-}
diff --git a/src/partest-alternative/scala/tools/partest/BuildContributors.scala b/src/partest-alternative/scala/tools/partest/BuildContributors.scala
deleted file mode 100644
index 85ca895103..0000000000
--- a/src/partest-alternative/scala/tools/partest/BuildContributors.scala
+++ /dev/null
@@ -1,102 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import nsc.util.ClassPath
-
-trait BuildContributors {
- universe: Universe =>
-
- /** A trait mixed into types which contribute a portion of the values.
- * The basic mechanism is the TestBuild, TestCategory, and TestEntity
- * can each contribute to each value. They are assembled at the last
- * moment by the ContributorAssembler (presently the TestEntity.)
- */
- trait BuildContributor {
- def javaFlags: List[String]
- def scalacFlags: List[String]
- def classpathPaths: List[Path]
- def buildProperties: List[(String, Any)]
- def buildEnvironment: Map[String, String]
- }
-
- trait ContributorAssembler {
- def contributors: List[BuildContributor]
- def assemble[T](what: BuildContributor => List[T]): List[T] = contributors flatMap what
-
- /** !!! This will need work if we want to achieve real composability,
- * but it can wait for the demand.
- */
- def assembleScalacArgs(args: List[String]) = assemble(_.scalacFlags) ++ args
- def assembleJavaArgs(args: List[String]) = assemble(_.javaFlags) ++ args
- def assembleProperties() = assemble(_.buildProperties)
- def assembleClasspaths(paths: List[Path]) = assemble(_.classpathPaths) ++ paths
- def assembleEnvironment() = assemble(_.buildEnvironment.toList).toMap
-
- def createClasspathString() = ClassPath fromPaths (assembleClasspaths(Nil) : _*)
- def createPropertyString() = assembleProperties() map { case (k, v) => "-D%s=%s".format(k, v.toString) }
- }
-
- trait BuildContribution extends BuildContributor {
- self: TestBuild =>
-
- /** The base classpath and system properties.
- * !!! TODO - this should adjust itself depending on the build
- * being tested, because pack and quick at least need different jars.
- */
- def classpathPaths = List[Path](library, compiler, partest, fjbg) ++ forkJoinPath
- def buildProperties = List(
- "scala.home" -> testBuildDir,
- "partest.lib" -> library, // used in jvm/inner
- "java.awt.headless" -> true,
- "user.language" -> "en",
- "user.country" -> "US",
- "partest.debug" -> isDebug,
- "partest.verbose" -> isVerbose
- // Disabled because there are no natives tests.
- // "java.library.path" -> srcLibDir
- )
- def javaFlags: List[String] = toArgs(javaOpts)
- def scalacFlags: List[String] = toArgs(scalacOpts)
-
- /** We put the build being tested's /bin directory in the front of the
- * path so the scripts and such written to execute "scala" will use this
- * build and not whatever happens to be on their path.
- */
- private def modifiedPath = ClassPath.join(scalaBin.path, Properties.envOrElse("PATH", ""))
- def buildEnvironment = Map("PATH" -> modifiedPath)
- }
-
- trait CategoryContribution extends BuildContributor {
- self: DirBasedCategory =>
-
- /** Category-wide classpath additions placed in <category>/lib. */
- private def libContents = root / "lib" ifDirectory (_.list.toList)
-
- def classpathPaths = libContents getOrElse Nil
- def buildProperties = Nil
- def javaFlags = Nil
- def scalacFlags = Nil
- def buildEnvironment = Map()
- }
-
- trait TestContribution extends BuildContributor with ContributorAssembler {
- self: TestEntity =>
-
- def jarsInTestDir = location.walk collect { case f: File if f hasExtension "jar" => f } toList
-
- def contributors = List(build, category, self)
- def javaFlags = safeArgs(javaOptsFile)
- def scalacFlags = safeArgs(scalaOptsFile)
- def classpathPaths = jarsInTestDir :+ outDir
- def buildProperties = List(
- "partest.output" -> outDir.toAbsolute, // used in jvm/inner
- "partest.cwd" -> outDir.parent.toAbsolute // used in shootout tests
- )
- def buildEnvironment = Map("JAVA_OPTS" -> fromArgs(assembleJavaArgs(Nil)))
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/Categories.scala b/src/partest-alternative/scala/tools/partest/Categories.scala
deleted file mode 100644
index c517a3f931..0000000000
--- a/src/partest-alternative/scala/tools/partest/Categories.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import nsc.Settings
-import nsc.io._
-import nsc.util.{ ClassPath }
-
-trait Categories {
- self: Universe =>
-
- trait TestCategory extends AbsTestCategory {
- def kind: String
- def startMessage: String = "Executing test group"
- def testSequence: TestSequence
-
- class TestSettings(entity: TestEntity, error: String => Unit) extends Settings(error) {
- def this(entity: TestEntity) = this(entity, Console println _)
-
- deprecation.value = false
- encoding.value = "ISO-8859-1"
- classpath.value = entity.testClasspath
- outdir.value = entity.outDir.path
- }
-
- def createSettings(entity: TestEntity): TestSettings = new TestSettings(entity)
- def createTest(location: Path): TestEntity =
- if (location.isFile) TestFile(this, location.toFile)
- else if (location.isDirectory) TestDirectory(this, location.toDirectory)
- else error("Failed to create test at '%s'" format location)
-
- /** Category test identification.
- */
- def denotesTestFile(p: Path) = p.isFile && (p hasExtension "scala")
- def denotesTestDir(p: Path) = p.isDirectory && !ignorePath(p)
- def denotesTest(p: Path) = denotesTestDir(p) || denotesTestFile(p)
-
- /** This should verify that all necessary files are present.
- * By default it delegates to denotesTest.
- */
- def denotesValidTest(p: Path) = denotesTest(p)
- }
-
- abstract class DirBasedCategory(val kind: String) extends TestCategory with CategoryContribution {
- lazy val root = Directory(src / kind).normalize
- def enumerate = root.list filter denotesTest map createTest toList
-
- /** Standard actions. These can be overridden either on the
- * Category level or by individual tests.
- */
- def compile: TestStep = (_: TestEntity).compile()
- def checkFileRequired: TestStep = (_: TestEntity).checkFileRequired
- def diff: TestStep = (_: TestEntity).diff()
- def run: TestStep = (_: TestEntity).run()
- def exec: TestStep = (_: TestEntity).exec()
-
- /** Combinators.
- */
- def not(f: TestStep): TestStep = !f(_: TestEntity)
-
- override def toString = kind
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/Compilable.scala b/src/partest-alternative/scala/tools/partest/Compilable.scala
deleted file mode 100644
index 65b5d5da0e..0000000000
--- a/src/partest-alternative/scala/tools/partest/Compilable.scala
+++ /dev/null
@@ -1,106 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.tools.nsc.io._
-import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError }
-import scala.tools.nsc.util.{ ClassPath }
-import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
-
-trait PartestCompilation {
- self: Universe =>
-
- trait CompileExecSupport extends ExecSupport {
- self: TestEntity =>
-
- def javacpArg = "-classpath " + testClasspath
- def scalacpArg = "-usejavacp"
-
- /** Not used, requires tools.jar.
- */
- // def javacInternal(args: List[String]) = {
- // import com.sun.tools.javac.Main
- // Main.compile(args.toArray, logWriter)
- // }
-
- def javac(args: List[String]): Boolean = {
- val allArgString = fromArgs(javacpArg :: javacOpts :: args)
-
- // javac -d outdir -classpath <basepath> <files>
- val cmd = "%s -d %s %s".format(javacCmd, outDir, allArgString)
- def traceMsg =
- if (isVerbose) cmd
- else "%s -d %s %s".format(tracePath(Path(javacCmd)), tracePath(outDir), fromArgs(args))
-
- trace(traceMsg)
-
- isDryRun || execAndLog(cmd)
- }
-
- def scalac(args: List[String]): Boolean = {
- val allArgs = assembleScalacArgs(args)
- val (global, files) = newGlobal(allArgs)
- def nonFileArgs = if (isVerbose) global.settings.recreateArgs else assembleScalacArgs(Nil)
- def traceArgs = fromArgs(nonFileArgs ++ (files map tracePath))
- def traceMsg = "scalac " + traceArgs
-
- trace(traceMsg)
- isDryRun || global.partestCompile(files, true)
- }
-
- /** Actually running the test, post compilation.
- * Normally args will be List("Test", "jvm"), main class and arg to it.
- */
- def runScala(args: List[String]): Boolean = {
- val scalaRunnerClass = "scala.tools.nsc.MainGenericRunner"
-
- // java $JAVA_OPTS <javaopts> -classpath <cp>
- val javaCmdAndOptions = javaCmd +: assembleJavaArgs(List(javacpArg))
- // MainGenericRunner -usejavacp <scalacopts> Test jvm
- val scalaCmdAndOptions = List(scalaRunnerClass, scalacpArg) ++ assembleScalacArgs(args)
- // Assembled
- val cmd = fromArgs(javaCmdAndOptions ++ createPropertyString() ++ scalaCmdAndOptions)
-
- def traceMsg = if (isVerbose) cmd else fromArgs(javaCmd :: args)
- trace("runScala: " + traceMsg)
-
- isDryRun || execAndLog(cmd)
- }
-
- def newReporter(settings: Settings) = new ConsoleReporter(settings, Console.in, logWriter)
-
- class PartestGlobal(settings: Settings, val creporter: ConsoleReporter) extends Global(settings, creporter) {
- def partestCompile(files: List[String], printSummary: Boolean): Boolean = {
- try { new Run compile files }
- catch {
- case FatalError(msg) => creporter.error(null, "fatal error: " + msg)
- case ae: AssertionError => creporter.error(null, ""+ae)
- case te: TypeError => creporter.error(null, ""+te)
- case ex =>
- creporter.error(null, ""+ex)
- throw ex
- }
-
- if (printSummary)
- creporter.printSummary
-
- creporter.flush()
- !creporter.hasErrors
- }
- }
-
- def newGlobal(args: List[String]): (PartestGlobal, List[String]) = {
- val settings = category createSettings self
- val command = new CompilerCommand(args, settings)
- val reporter = newReporter(settings)
-
- if (!command.ok)
- debug("Error parsing arguments: '%s'".format(args mkString ", "))
-
- (new PartestGlobal(command.settings, reporter), command.files)
- }
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Config.scala b/src/partest-alternative/scala/tools/partest/Config.scala
deleted file mode 100644
index ee1852f6ed..0000000000
--- a/src/partest-alternative/scala/tools/partest/Config.scala
+++ /dev/null
@@ -1,115 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import io._
-import nsc.io._
-import Properties._
-
-trait Config {
- universe: Universe =>
-
- lazy val src = absolutize(srcDir).toDirectory
- lazy val build = new TestBuild()
-
- def javaHomeEnv = envOrElse("JAVA_HOME", null)
- def javaCmd = envOrElse("JAVACMD", "java")
- def javacCmd = Option(javaHomeEnv) map (x => Path(x) / "bin" / "javac" path) getOrElse "javac"
-
- /** Values related to actors. The timeouts are in seconds. On a dry
- * run we only allocate one worker so the output isn't interspersed.
- */
- def workerTimeout = 3600 // 1 hour, probably overly generous
- def numWorkers = if (isDryRun) 1 else propOrElse("partest.actors", "8").toInt
- def expectedErrors = propOrElse("partest.errors", "0").toInt
- def poolSize = (wrapAccessControl(propOrNone("actors.corePoolSize")) getOrElse "16").toInt
-
- def allScalaFiles = src.deepFiles filter (_ hasExtension "scala")
- def allObjDirs = src.deepDirs filter (_ hasExtension "obj")
- def allLogFiles = src.deepFiles filter (_ hasExtension "log")
- def allClassFiles = src.deepFiles filter (_ hasExtension "class")
-
- class TestBuild() extends BuildContribution {
- import nsc.util.ClassPath
-
- /** Scala core libs.
- */
- val library = pathForComponent("library")
- val compiler = pathForComponent("compiler")
- val partest = pathForComponent("partest")
- val scalap = pathForComponent("scalap", "%s.jar")
-
- /** Scala supplementary libs - these are not all needed for all build targets,
- * and some of them are copied inside other jars in later targets. However quick
- * for instance cannot be run without some of these.
- */
- val fjbg = pathForLibrary("fjbg")
- val msil = pathForLibrary("msil")
- val forkjoin = pathForLibrary("forkjoin")
- val scalacheck = pathForLibrary("scalacheck")
-
- /** Other interesting paths.
- */
- val scalaBin = testBuildDir / "bin"
-
- /** A hack for now to get quick running.
- */
- def needsForkJoin = {
- val loader = nsc.util.ScalaClassLoader.fromURLs(List(library.toURL))
- val fjMarker = "scala.concurrent.forkjoin.ForkJoinTask"
- val clazz = loader.tryToLoadClass(fjMarker)
-
- if (clazz.isDefined) debug("Loaded ForkJoinTask OK, don't need jar.")
- else debug("Could not load ForkJoinTask, putting jar on classpath.")
-
- clazz.isEmpty
- }
- lazy val forkJoinPath: List[Path] = if (needsForkJoin) List(forkjoin) else Nil
-
- /** Internal **/
- private def repo = partestDir.parent.normalize
-
- private def pathForComponent(what: String, jarFormat: String = "scala-%s.jar"): Path = {
- def asDir = testBuildDir / "classes" / what
- def asJar = testBuildDir / "lib" / jarFormat.format(what)
-
- if (asDir.isDirectory) asDir
- else if (asJar.isFile) asJar
- else ""
- }
- private def pathForLibrary(what: String) = File(repo / "lib" / (what + ".jar"))
- }
-
- def printConfigBanner() = {
- debug("Java VM started with arguments: '%s'" format fromArgs(Process.javaVmArguments))
- debug("System Properties:\n" + util.allPropertiesString())
-
- normal(configBanner())
- }
-
- /** Treat an access control failure as None. */
- private def wrapAccessControl[T](body: => Option[T]): Option[T] =
- try body catch { case _: java.security.AccessControlException => None }
-
- private def configBanner() = {
- val javaBin = Path(javaHome) / "bin"
- val javaInfoString = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
-
- List(
- "Scala compiler classes in: " + testBuildDir,
- "Scala version is: " + nsc.Properties.versionMsg,
- "Scalac options are: " + universe.scalacOpts,
- "Java binaries in: " + javaBin,
- "Java runtime is: " + javaInfoString,
- "Java runtime options: " + (Process.javaVmArguments mkString " "),
- "Javac options are: " + universe.javacOpts,
- "Java options are: " + universe.javaOpts,
- "Source directory is: " + src,
- "Selected categories: " + (selectedCategories mkString " "),
- ""
- ) mkString "\n"
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Dispatcher.scala b/src/partest-alternative/scala/tools/partest/Dispatcher.scala
deleted file mode 100644
index 69efc353eb..0000000000
--- a/src/partest-alternative/scala/tools/partest/Dispatcher.scala
+++ /dev/null
@@ -1,162 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import scala.tools.nsc.io._
-import scala.actors.{ Actor, TIMEOUT }
-import scala.actors.Actor._
-import scala.collection.immutable
-import scala.util.control.Exception.ultimately
-
-/** The machinery for concurrent execution of tests. Each Worker
- * is given a bundle of tests, which it runs sequentially and then
- * sends a report back to the dispatcher.
- */
-trait Dispatcher {
- partest: Universe =>
-
- /** The public entry point. The given filter narrows down the list of
- * tests to run.
- */
- def runSelection(categories: List[TestCategory], filt: TestEntity => Boolean = _ => true): CombinedTestResults = {
- // Setting scala.home informs tests where to obtain their jars.
- setProp("scala.home", testBuildDir.path)
-
- val allTests = allCategories flatMap (_.enumerate)
- val selected = allTests filter filt
- val groups = selected groupBy (_.category)
- val count = selected.size
-
- if (count == 0) return CombinedTestResults(0, 0, 0, Nil)
- else if (count == allTests.size) verbose("Running all %d tests." format count)
- else verbose("Running %d/%d tests: %s".format(count, allTests.size, toStringTrunc(selected map (_.label) mkString ", ")))
-
- allCategories collect { case x if groups contains x => runCategory(x, groups(x)) } reduceLeft (_ ++ _)
- }
-
- private def parallelizeTests(tests: List[TestEntity]): immutable.Map[TestEntity, TestResult] = {
- // propagate verbosity
- if (isDebug) scala.actors.Debug.level = 3
-
- // "If elected, I guarantee a slice of tests for every worker!"
- val groups = tests grouped ((tests.size / numWorkers) + 1) toList
-
- // "Workers, line up for assignments!"
- val workers =
- for ((slice, workerNum) <- groups.zipWithIndex) yield {
- returning(new Worker(workerNum)) { worker =>
- worker.start()
- worker ! TestsToRun(slice)
- }
- }
-
- normal("Started %d workers with ~%d tests each.\n".format(groups.size, groups.head.size))
-
- /** Listening for news from the proletariat.
- */
- (workers map { w =>
- receiveWithin(workerTimeout * 1000) {
- case ResultsOfRun(resultMap) => resultMap
- case TIMEOUT =>
- warning("Worker %d timed out." format w.workerNum)
- // mark all the worker's tests as having timed out - should be hard to miss
- // immutable.Map[TestEntity, TestResult]()
- groups(w.workerNum) map (x => (x -> new Timeout(x))) toMap
- }
- }) reduceLeft (_ ++ _)
- }
-
- private def runCategory(category: TestCategory, tests: List[TestEntity]): CombinedTestResults = {
- val kind = category.kind
- normal("%s (%s tests in %s)\n".format(category.startMessage, tests.size, category))
-
- val (milliSeconds, resultMap) = timed2(parallelizeTests(tests))
- val (passed, failed) = resultsToStatistics(resultMap mapValues (_.state))
- val failures = resultMap.values filterNot (_.passed) toList
-
- CombinedTestResults(passed, failed, milliSeconds, failures)
- }
-
- /** A Worker is given a bundle of tests and runs them all sequentially.
- */
- class Worker(val workerNum: Int) extends Actor {
- def act() {
- react { case TestsToRun(tests) =>
- val master = sender
- runTests(tests)(results => master ! ResultsOfRun(results))
- }
- }
-
- /** Runs the tests. Passes the result Map to onCompletion when done.
- */
- private def runTests(tests: List[TestEntity])(onCompletion: immutable.Map[TestEntity, TestResult] => Unit) {
- var results = new immutable.HashMap[TestEntity, TestResult] // maps tests to results
- val numberOfTests = tests.size
- val testIterator = tests.iterator
- def processed = results.size
- def isComplete = testIterator.isEmpty
-
- def atThreshold(num: Double) = {
- require(num >= 0 && num <= 1.0)
- ((processed - 1).toDouble / numberOfTests <= num) && (processed.toDouble / numberOfTests >= num)
- }
-
- def extraMessage = {
- // for now quiet for normal people
- if (isVerbose || isTrace || isDebug) {
- if (isComplete) "(#%d 100%%)" format workerNum
- else if (isVerbose) "(#%d %d/%d)".format(workerNum, processed, numberOfTests)
- else if (isTrace && atThreshold(0.5)) "(#%d 50%%)" format workerNum
- else ""
- }
- else ""
- }
-
- def countAndReport(result: TestResult) {
- val TestResult(test, state) = result
- // refuse to count an entity twice
- if (results contains test)
- return warning("Received duplicate result for %s: was %s, now %s".format(test, results(test), state))
-
- // increment the counter for this result state
- results += (test -> result)
-
- // show on screen
- if (isDryRun) normal("\n") // blank line between dry run traces
- else result show extraMessage
-
- // remove log if successful
- if (result.passed)
- test.deleteLog()
-
- // Respond to master if this Worker is complete
- if (isComplete)
- onCompletion(results)
- }
-
- Actor.loopWhile(testIterator.hasNext) {
- val parent = self
- // pick a test and set some alarms
- val test = testIterator.next
- val alarmer = test startAlarms (parent ! new Timeout(test))
-
- actor {
- ultimately(alarmer.cancelAll()) {
- // Calling isSuccess forces the lazy val "process" inside the test, running it.
- val res = test.isSuccess
- // Cancel the alarms and alert the media.
- parent ! TestResult(test, res)
- }
- }
-
- react {
- case x: TestResult => countAndReport(x)
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/Entities.scala b/src/partest-alternative/scala/tools/partest/Entities.scala
deleted file mode 100644
index 301deb972b..0000000000
--- a/src/partest-alternative/scala/tools/partest/Entities.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-
-trait Entities {
- self: Universe =>
-
- abstract class TestEntity extends AbsTestEntity
- with TestContribution
- with TestHousekeeping
- with TestAlarms
- with EntityLogging
- with CompilableTest
- with ScriptableTest
- with DiffableTest {
- def location: Path
- def category: TestCategory
-
- lazy val label = location.stripExtension
- lazy val testClasspath = returning(createClasspathString())(x => vtrace("testClasspath: " + x))
-
- /** Was this test successful? Calling this for the first time forces
- * lazy val "process" which actually runs the test.
- */
- def isSuccess = process
-
- /** Some standard files, which may or may not be present.
- */
- def scalaOptsFile = withExtension("flags").toFile // opts to scalac
- def javaOptsFile = withExtension("javaopts").toFile // opts to java (but not javac)
- def commandFile = withExtension("cmds").toFile // sequence of commands to execute
- def logFile = withExtension("log").toFile // collected output
-
- /** Some standard directories.
- */
- def outDir = withExtension("obj").toDirectory // output dir, e.g. files/pos/t14.obj
- def categoryDir = location.parent.normalize // category dir, e.g. files/pos/
- def sourcesDir = location ifDirectory (_.normalize) getOrElse categoryDir
-
- /** Standard arguments for run, exec, diff.
- */
- def argumentsToRun = List("Test", "jvm")
- def argumentsToExec = List(location.path)
-
- /** Using a .cmds file for a custom test sequence.
- */
- def commandList = safeLines(commandFile)
- def testSequence =
- if (commandFile.isFile && commandList.nonEmpty) commandList map customTestStep
- else category.testSequence
-
- def run() = runScala(argumentsToRun)
- def exec() = runExec(argumentsToExec)
- def diff() = runDiff() // checkFile, logFile
-
- /** The memoized result of the test run.
- */
- private lazy val process = {
- val outcome = runWrappers(testSequence.actions forall (f => f(this)))
-
- // an empty outcome means we've been interrupted and are shutting down.
- outcome getOrElse false
- }
- }
-
- case class TestDirectory(category: TestCategory, location: Directory) extends TestEntity { }
- case class TestFile(category: TestCategory, location: File) extends TestEntity { }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Housekeeping.scala b/src/partest-alternative/scala/tools/partest/Housekeeping.scala
deleted file mode 100644
index cfdecee9c7..0000000000
--- a/src/partest-alternative/scala/tools/partest/Housekeeping.scala
+++ /dev/null
@@ -1,187 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.util.control.Exception.catching
-import util._
-import nsc.io._
-import Process.runtime
-import Properties._
-
-/** An agglomeration of code which is low on thrills. Hopefully
- * it operates so quietly in the background that you never have to
- * look at this file.
- */
-trait Housekeeping {
- self: Universe =>
-
- /** Orderly shutdown on ctrl-C. */
- @volatile private var _shuttingDown = false
- protected def setShuttingDown() = {
- /** Whatever we want to do as shutdown begins goes here. */
- if (!_shuttingDown) {
- warning("Received shutdown signal, partest is cleaning up...\n")
- _shuttingDown = true
- }
- }
- def isShuttingDown = _shuttingDown
-
- /** Execute some code with a shutdown hook in place. This is
- * motivated by the desire not to leave the filesystem full of
- * junk when someone ctrl-Cs a test run.
- */
- def withShutdownHook[T](hook: => Unit)(body: => T): Option[T] =
- /** Java doesn't like it if you keep adding and removing shutdown
- * hooks after shutdown has begun, so we trap the failure.
- */
- catching(classOf[IllegalStateException]) opt {
- val t = new Thread() {
- override def run() = {
- setShuttingDown()
- hook
- }
- }
- runtime addShutdownHook t
-
- try body
- finally runtime removeShutdownHook t
- }
-
- /** Search for a directory, possibly given only a name, by starting
- * at the current dir and walking upward looking for it at each level.
- */
- protected def searchForDir(name: String): Directory = {
- val result = Path(name) ifDirectory (x => x.normalize) orElse {
- val cwd = Directory.Current getOrElse error("user.dir property not set")
- val dirs = cwd :: cwd.parents map (_ / name)
-
- Path onlyDirs dirs map (_.normalize) headOption
- }
-
- result getOrElse error("Fatal: could not find directory '%s'" format name)
- }
-
- /** Paths we ignore for most purposes.
- */
- def ignorePath(x: Path) = {
- (x.name startsWith ".") ||
- (x.isDirectory && ((x.name == "lib") || x.hasExtension("obj", "svn")))
- }
- /** Make a possibly relative path absolute using partestDir as the base.
- */
- def absolutize(path: String) = Path(path) toAbsoluteWithRoot partestDir
-
- /** Go on a deleting binge.
- */
- def cleanupAll() {
- if (isNoCleanup)
- return
-
- val (dirCount, fileCount) = (cleanupObjDirs(), cleanupLogs() + cleanupJunk())
- if (dirCount + fileCount > 0)
- normal("Cleaned up %d directories and %d files.\n".format(dirCount, fileCount))
- }
-
- def cleanupObjDirs() = countTrue(allObjDirs collect { case x if x.exists => x.deleteRecursively() })
- def cleanupJunk() = countTrue(allClassFiles collect { case x if x.exists => x.delete() })
- def cleanupLogs() = countTrue(allLogFiles collect { case x if x.exists => x.delete() })
-
- /** Look through every file in the partest directory and ask around
- * to make sure someone knows him. Complain about strangers.
- */
- def validateAll() {
- def denotesTest(p: Path) = allCategories exists (_ denotesTest p)
- def isMSILcheck(p: Path) = p.name endsWith "-msil.check"
-
- def analyzeCategory(cat: DirBasedCategory) = {
- val allTests = cat.enumerate
- val otherPaths = cat.root walkFilter (x => !ignorePath(x)) filterNot (cat denotesTest _) filterNot isMSILcheck toList
- val count = otherPaths.size
-
- println("Validating %d non-test paths in %s.".format(count, cat.kind))
-
- for (path <- otherPaths) {
- (allTests find (_ acknowledges path)) match {
- case Some(test) => if (isVerbose) println(" OK: '%s' is claimed by '%s'".format(path, test.label))
- case _ => println(">> Unknown path '%s'" format path)
- }
- }
- }
-
- allCategories collect { case x: DirBasedCategory => analyzeCategory(x) }
- }
-
- trait TestHousekeeping {
- self: TestEntity =>
-
- /** Calculating derived files. Given a test like
- * files/run/foo.scala or files/run/foo/
- * This creates paths like foo.check, foo.flags, etc.
- */
- def withExtension(extension: String) = categoryDir / "%s.%s".format(label, extension)
-
- /** True for a path if this test acknowledges it belongs to this test.
- * Overridden by some categories.
- */
- def acknowledges(path: Path): Boolean = {
- val loc = location.normalize
- val knownPaths = List(scalaOptsFile, javaOptsFile, commandFile, logFile, checkFile) ++ jarsInTestDir
- def isContainedSource = location.isDirectory && isJavaOrScala(path) && (path.normalize startsWith loc)
-
- (knownPaths exists (_ isSame path)) || isContainedSource
- }
-
- /** This test "responds to" this String. This could mean anything -- it's a
- * way of specifying ad-hoc collections of tests to exercise only a subset of tests.
- * At present it looks for the given String in all the test sources.
- */
- def respondsToString(str: String) = containsString(str)
- def containsString(str: String) = {
- debug("Checking %s for \"%s\"".format(sourceFiles mkString ", ", str))
- sourceFiles map safeSlurp exists (_ contains str)
- }
-
- def possiblyTimed[T](body: => T): T = {
- if (isStats) timed(recordTestTiming(label, _))(body)
- else body
- }
-
- private def prepareForTestRun() = {
- // make sure we have a clean slate
- deleteLog(force = true)
- if (outDir.exists)
- outDir.deleteRecursively()
-
- // recreate object dir
- outDir createDirectory true
- }
- def deleteOutDir() = outDir.deleteRecursively()
- def deleteShutdownHook() = { debug("Shutdown hook deleting " + outDir) ; deleteOutDir() }
-
- protected def runWrappers[T](body: => T): Option[T] = {
- prepareForTestRun()
-
- withShutdownHook(deleteShutdownHook()) {
- loggingOutAndErr {
- val result = possiblyTimed { body }
- if (!isNoCleanup)
- deleteOutDir()
-
- result
- }
- }
- }
-
- override def toString = location.path
- override def equals(other: Any) = other match {
- case x: TestEntity => location.normalize == x.location.normalize
- case _ => false
- }
- override def hashCode = location.normalize.hashCode
- }
-
- private def countTrue(f: => Iterator[Boolean]) = f filter (_ == true) length
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/Partest.scala b/src/partest-alternative/scala/tools/partest/Partest.scala
deleted file mode 100644
index 74a3a6a19b..0000000000
--- a/src/partest-alternative/scala/tools/partest/Partest.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import nsc.util._
-import category.AllCategories
-
-/** Global object for a Partest run. It is completely configured by the list
- * of arguments passed to the constructor (although there are a few properties
- * and environment variables which can influence matters.) See PartestSpec.scala
- * for the complete list.
- */
-class Partest(args: List[String]) extends {
- val parsed = PartestSpec(args: _*)
-} with Universe with PartestSpec with cmd.Instance with AllCategories {
-
- if (parsed.propertyArgs.nonEmpty)
- debug("Partest property args: " + fromArgs(parsed.propertyArgs))
-
- debug("Partest created with args: " + fromArgs(args))
-
- def helpMsg = PartestSpec.helpMsg
-
- // The abstract values from Universe.
- lazy val testBuildDir = searchForDir(buildDir)
- lazy val partestDir = searchForDir(rootDir)
- lazy val allCategories = List(Pos, Neg, Run, Jvm, Res, Shootout, Scalap, Scalacheck, BuildManager, Script)
- lazy val selectedCategories = if (isAllImplied) allCategories else specifiedCats
-
- def specifiedTests = parsed.residualArgs map (x => Path(x).normalize)
- def specifiedKinds = testKinds filter (x => isSet(x) || (runSets contains x))
- def specifiedCats = specifiedKinds flatMap (x => allCategories find (_.kind == x))
- def isAllImplied = isAll || (specifiedTests.isEmpty && specifiedKinds.isEmpty)
-
- /** Assembles a filter based on command line options which restrict the test set
- * --grep limits to only matching tests
- * --failed limits to only recently failed tests (log file is present)
- * --<category> limits to only the given tests and categories (but --all overrides)
- * path/to/Test limits to only the given tests and categories
- */
- lazy val filter = {
- def indivFilter(test: TestEntity) = specifiedTests contains test.location.normalize
- def categoryFilter(test: TestEntity) = specifiedCats contains test.category
- def indivOrCat(test: TestEntity) = isAllImplied || indivFilter(test) || categoryFilter(test) // combines previous two
-
- def failedFilter(test: TestEntity) = !isFailed || (test.logFile exists)
- def grepFilter(test: TestEntity) = grepExpr.isEmpty || (test containsString grepExpr.get)
- def combinedFilter(x: TestEntity) = indivOrCat(x) && failedFilter(x) && grepFilter(x) // combines previous three
-
- combinedFilter _
- }
-
- def launchTestSuite() = {
- def onTimeout() = {
- warning("Partest test run timed out after " + timeout + " seconds.\n")
- System.exit(-1)
- }
- val alarm = new Alarmer(AlarmerAction(timeout, () => onTimeout()))
-
- try runSelection(selectedCategories, filter)
- finally alarm.cancelAll()
- }
-}
-
-object Partest {
- def fromBuild(dir: String, args: String*): Partest = apply("--builddir" +: dir +: args: _*)
- def apply(args: String*): Partest = new Partest(args.toList)
-
- // builds without partest jars won't actually work
- def starr() = fromBuild("")
- def locker() = fromBuild("build/locker")
- def quick() = fromBuild("build/quick")
- def pack() = fromBuild("build/pack")
- def strap() = fromBuild("build/strap")
- def dist() = fromBuild("dists/latest")
-}
-
diff --git a/src/partest-alternative/scala/tools/partest/PartestSpec.scala b/src/partest-alternative/scala/tools/partest/PartestSpec.scala
deleted file mode 100644
index 75d94bdb72..0000000000
--- a/src/partest-alternative/scala/tools/partest/PartestSpec.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import cmd._
-
-/** This takes advantage of bits of scala goodness to fully define a command
- * line program with a minimum of duplicated code. When the specification object
- * is created, the vals are evaluated in order and each of them side effects
- * a private accumulator. What emerges is a full list of the valid unary
- * and binary arguments, as well as autogenerated help.
- */
-trait PartestSpec extends Spec with Meta.StdOpts with Interpolation {
- def referenceSpec = PartestSpec
- def programInfo = Spec.Info("partest", "", "scala.tools.partest.Runner")
- private val kind = new Spec.Accumulator[String]()
- protected def testKinds = kind.get
-
- private implicit val tokenizeString = FromString.ArgumentsFromString // String => List[String]
-
- help("""
- |# Pro Tip! Instant bash completion: `partest --bash` (note backticks)
- |Usage: partest [<options>] [<test> <test> ...]
- | <test>: a path to a test designator, typically a .scala file or a directory.
- | Examples: files/pos/test1.scala, files/res/bug785
- |
- | Test categories:""".stripMargin)
-
- val isAll = ("all" / "run all tests (default, unless no options given)" --?)
- (kind("pos") / "Compile files that are expected to build" --?)
- (kind("neg") / "Compile files that are expected to fail" --?)
- (kind("run") / "Test JVM backend" --?)
- (kind("jvm") / "Test JVM backend" --?)
- (kind("res") / "Run resident compiler scenarii" --?)
- (kind("buildmanager") / "Run Build Manager scenarii" --?)
- (kind("scalacheck") / "Run Scalacheck tests" --?)
- (kind("script") / "Run script files" --?)
- (kind("shootout") / "Run shootout tests" --?)
- (kind("scalap") / "Run scalap tests" --?)
-
- heading ("""Test "smart" categories:""")
- val grepExpr = "grep" / "run all tests with a source file containing <expr>" --|
- val isFailed = "failed" / "run all tests which failed on the last run" --?
-
- heading ("Specifying paths and additional flags, ~ means repository root:")
-
- val rootDir = "rootdir" / "path from ~ to partest" defaultTo "test"
- val buildDir = "builddir" / "path from ~ to test build" defaultTo "build/pack"
- val srcDir = "srcdir" / "path from --rootdir to sources" defaultTo "files"
- val javaOpts = "javaopts" / "flags to java on all runs" defaultToEnv "JAVA_OPTS"
- val javacOpts = "javacopts" / "flags to javac on all runs" defaultToEnv "JAVAC_OPTS"
- val scalacOpts = "scalacopts" / "flags to scalac on all tests" defaultToEnv "SCALAC_OPTS"
-
- "pack" / "" expandTo ("--builddir", "build/pack")
- "quick" / "" expandTo ("--builddir", "build/quick")
-
- heading ("Options influencing output:")
- val isTrace = "trace" / "show the individual steps taken by each test" --?
- val isShowDiff = "show-diff" / "show diff between log and check file" --?
- val isShowLog = "show-log" / "show log on failures" --?
- val isDryRun = "dry-run" / "do not run tests, only show their traces." --?
- val isTerse = "terse" / "be less verbose (almost silent except for failures)" --?
- val isVerbose = "verbose" / "be more verbose (additive with --trace)" --?
- val isDebug = "debug" / "maximum debugging output" --?
- val isAnsi = "ansi" / "print output in color" --?
-
- heading ("Other options:")
- val timeout = "timeout" / "Overall timeout in seconds" defaultTo 7200
- val testWarning = "test-warning" / "Test warning in seconds" defaultTo 90
- val testTimeout = "test-timeout" / "Test timeout in seconds" defaultTo 900
- val isCleanup = "cleanup" / "delete all stale files and dirs before run" --?
- val isNoCleanup = "nocleanup" / "do not delete any logfiles or object dirs" --?
- val isStats = "stats" / "collect and print statistics about the tests" --?
- val isValidate = "validate" / "examine test filesystem for inconsistencies" --?
- val isUpdateCheck = "update-check" / "overwrite checkFile if diff fails" --?
-
- "version" / "print version" --> runAndExit(println(Properties.versionMsg))
-
- // no help for anything below this line - secret options
- // mostly intended for property configuration.
- val runSets = ("runsets" --^) getOrElse Nil
- val isNoAlarms = "noalarms" --?
- val isInsideAnt = "is-in-ant" --?
-}
-
-object PartestSpec extends PartestSpec with Property {
- lazy val propMapper = new PropertyMapper(PartestSpec) {
- override def isPassThrough(key: String) = key == "partest.options"
- }
-
- type ThisCommandLine = PartestCommandLine
- class PartestCommandLine(args: List[String]) extends SpecCommandLine(args) {
- override def errorFn(msg: String) = printAndExit("Error: " + msg)
-
- def propertyArgs = PartestSpec.propertyArgs
- }
-
- override def creator(args: List[String]): PartestCommandLine = new PartestCommandLine(args)
-}
diff --git a/src/partest-alternative/scala/tools/partest/Properties.scala b/src/partest-alternative/scala/tools/partest/Properties.scala
deleted file mode 100644
index 2d36f163c8..0000000000
--- a/src/partest-alternative/scala/tools/partest/Properties.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-package scala.tools
-package partest
-
-/** Loads partest.properties from the jar. */
-object Properties extends scala.util.PropertiesTrait {
- protected def propCategory = "partest"
- protected def pickJarBasedOn = classOf[Application]
-}
diff --git a/src/partest-alternative/scala/tools/partest/Results.scala b/src/partest-alternative/scala/tools/partest/Results.scala
deleted file mode 100644
index e0fceed17a..0000000000
--- a/src/partest-alternative/scala/tools/partest/Results.scala
+++ /dev/null
@@ -1,121 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.collection.immutable
-
-trait Results {
- self: Universe =>
-
- /** A collection of tests for a Worker.
- */
- case class TestsToRun(entities: List[TestEntity])
-
- /** The response from a Worker who has been given TestsToRun.
- */
- case class ResultsOfRun(results: immutable.Map[TestEntity, TestResult])
-
- /** The result of a single test. (0: OK, 1: FAILED, 2: TIMEOUT)
- */
- sealed abstract class TestResult(val state: Int, val description: String) {
- def entity: TestEntity
-
- def passed = state == 0
- def colorize(s: String): String
- def show(msg: String) =
- if (!isShuttingDown)
- showResult(colorize(description), msg)
-
- private def outputPrefix = if (isInsideAnt) "" else markNormal("partest: ")
- private def name = src relativize entity.location // e.g. "neg/test.scala"
- private def showResult(status: String, extraMsg: String) =
- normal(outputPrefix + "[...]/%-40s [%s] %s\n".format(name, status, extraMsg))
-
- override def equals(other: Any) = other match {
- case x: TestResult => entity == x.entity
- case _ => false
- }
- override def hashCode = entity.hashCode
- override def toString = "%s [%s]".format(entity, description)
- }
-
- class Success(val entity: TestEntity) extends TestResult(0, " OK ") {
- def colorize(s: String) = markSuccess(s)
- override def show(msg: String) = if (!isTerse) super.show(msg)
- }
- class Failure(val entity: TestEntity) extends TestResult(1, " FAILED ") {
- def colorize(s: String) = markFailure(s)
-
- override def show(msg: String) = {
- super.show(msg)
-
- if (isShowDiff || isTrace)
- normal(entity.diffOutput)
-
- if (isShowLog || isTrace)
- normal(toStringTrunc(entity.failureMessage(), 1600))
- }
- override def toString = List(super.toString, toStringTrunc(entity.failureMessage(), 400)) mkString "\n"
- }
- class Timeout(val entity: TestEntity) extends TestResult(2, "TIME OUT") {
- def colorize(s: String) = markFailure(s)
- }
-
- object TestResult {
- def apply(entity: TestEntity, success: Boolean) =
- if (success) new Success(entity)
- else new Failure(entity)
-
- def apply(entity: TestEntity, state: Int) = state match {
- case 0 => new Success(entity)
- case 1 => new Failure(entity)
- case 2 => new Timeout(entity)
- }
- def unapply(x: Any) = x match {
- case x: TestResult => Some((x.entity, x.state))
- case _ => None
- }
- }
-
- /** The combined results of any number of tests.
- */
- case class CombinedTestResults(
- passed: Int,
- failed: Int,
- elapsedMilliseconds: Long,
- failures: List[TestResult]
- ) {
- // housekeeping
- val elapsedSecs = elapsedMilliseconds / 1000
- val elapsedMins = elapsedSecs / 60
- val elapsedHrs = elapsedMins / 60
- val dispMins = elapsedMins - elapsedHrs * 60
- val dispSecs = elapsedSecs - elapsedMins * 60
-
- def total = passed + failed
- def hasFailures = failed > 0
- def exitCode = if (expectedErrors == failed) 0 else 1
-
- def ++(x: CombinedTestResults) = CombinedTestResults(
- passed + x.passed,
- failed + x.failed,
- elapsedMilliseconds + x.elapsedMilliseconds,
- failures ::: x.failures
- )
-
- def elapsedString = "%02d:%02d:%02d".format(elapsedHrs, dispMins, dispSecs)
- def failuresString = {
- if (failures.isEmpty) ""
- else "Summary of failures:" :: failures mkString ("\n", "\n", "")
- }
-
- override def toString =
- if (total == 0) "There were no tests to run."
- else if (isDryRun) "%d tests would be run." format total
- else if (hasFailures) "%d of %d tests failed (elapsed time: %s)".format(failed, total, elapsedString) + failuresString
- else "All %d tests were successful (elapsed time: %s)".format(total, elapsedString)
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/Runner.scala b/src/partest-alternative/scala/tools/partest/Runner.scala
deleted file mode 100644
index 7fe2c98d43..0000000000
--- a/src/partest-alternative/scala/tools/partest/Runner.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-
-object Runner {
- def main(args: Array[String]) {
- val runner = Partest(args: _*)
- import runner._
-
- if (args.isEmpty) return println(helpMsg)
- if (isValidate) return validateAll()
-
- printConfigBanner()
-
- if (isCleanup)
- cleanupAll()
-
- val result = launchTestSuite()
- val exitCode = result.exitCode
- val message = "\n" + result + "\n"
-
- if (exitCode == 0) success(message)
- else failure(message)
-
- if (isStats)
- showTestStatistics()
-
- System exit exitCode
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Statistics.scala b/src/partest-alternative/scala/tools/partest/Statistics.scala
deleted file mode 100644
index e90377cfa7..0000000000
--- a/src/partest-alternative/scala/tools/partest/Statistics.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import scala.collection.mutable
-
-trait Statistics {
- /** Only collected when --stats is given. */
- lazy val testStatistics = new mutable.HashMap[String, Long]
-
- /** Given function and block of code, evaluates code block,
- * calls function with milliseconds elapsed, and returns block result.
- */
- def timed[T](f: Long => Unit)(body: => T): T = {
- val start = System.currentTimeMillis
- val result = body
- val end = System.currentTimeMillis
-
- f(end - start)
- result
- }
- /** Times body and returns both values.
- */
- def timed2[T](body: => T): (Long, T) = {
- var milliSeconds = 0L
- val result = timed(x => milliSeconds = x)(body)
-
- (milliSeconds, result)
- }
-
- def resultsToStatistics(results: Iterable[(_, Int)]): (Int, Int) =
- (results partition (_._2 == 0)) match {
- case (winners, losers) => (winners.size, losers.size)
- }
-
- def recordTestTiming(name: String, milliseconds: Long) =
- synchronized { testStatistics(name) = milliseconds }
-
- def showTestStatistics() {
- testStatistics.toList sortBy (-_._2) foreach { case (k, v) => println("%s: %.2f seconds".format(k, (v.toDouble / 1000))) }
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/Universe.scala b/src/partest-alternative/scala/tools/partest/Universe.scala
deleted file mode 100644
index 3dd79e4791..0000000000
--- a/src/partest-alternative/scala/tools/partest/Universe.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import category.AllCategories
-import io.Logging
-
-/** The high level view of the partest infrastructure.
- */
-abstract class Universe
- extends Entities
- with BuildContributors
- with Logging
- with Dispatcher
- with Statistics
- with Housekeeping
- with Results
- with PartestCompilation
- with PartestSpec
- with Config
- with Alarms
- with Actions
- with Categories {
-
- /** The abstract values from which all else is derived. */
- def partestDir: Directory
- def testBuildDir: Directory
- def allCategories: List[TestCategory]
- def selectedCategories: List[TestCategory]
-
- /** Some plausibly abstract types. */
- type TestBuild <: BuildContributor // e.g. quick, pack
- type TestCategory <: AbsTestCategory // e.g. pos, neg, run
- type TestEntity <: AbsTestEntity // e.g. files/pos/test25.scala
- type TestSequence <: AbsTestSequence // e.g. compile, run, diff
-
- /** Although TestStep isn't much more than Function1 right now,
- * it exists this way so it can become more capable.
- */
- implicit def f1ToTestStep(f: TestEntity => Boolean): TestStep =
- new TestStep { def apply(test: TestEntity) = f(test) }
-
- abstract class TestStep extends (TestEntity => Boolean) {
- def apply(test: TestEntity): Boolean
- }
-
- /** An umbrella category of tests, such as "pos" or "run".
- */
- trait AbsTestCategory extends BuildContributor {
- type TestSettings
-
- def kind: String
- def testSequence: TestSequence
- def denotesTest(location: Path): Boolean
-
- def createTest(location: Path): TestEntity
- def createSettings(entity: TestEntity): TestSettings
- def enumerate: List[TestEntity]
- }
-
- /** A single test. It may involve multiple files, but only a
- * single path is used to designate it.
- */
- trait AbsTestEntity extends BuildContributor {
- def category: TestCategory
- def location: Path
- def onException(x: Throwable): Unit
- def testClasspath: String
-
- /** Most tests will use the sequence defined by the category,
- * but the test can override and define a custom sequence.
- */
- def testSequence: TestSequence
-
- /** True if this test recognizes the given path as a piece of it.
- * For validation purposes.
- */
- def acknowledges(path: Path): Boolean
- }
-
- /** Every TestEntity is partly characterized by a series of actions
- * which are applied to the TestEntity in the given order. The test
- * passes if all those actions return true, fails otherwise.
- */
- trait AbsTestSequence {
- def actions: List[TestStep]
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/ant/JavaTask.scala b/src/partest-alternative/scala/tools/partest/ant/JavaTask.scala
deleted file mode 100644
index f8c0133dc1..0000000000
--- a/src/partest-alternative/scala/tools/partest/ant/JavaTask.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package ant
-
-import org.apache.tools.ant.Task
-import org.apache.tools.ant.taskdefs.Java
-import org.apache.tools.ant.types.Environment
-
-import scala.tools.nsc.io._
-import scala.tools.nsc.util.ClassPath
-import cmd.Spec._
-
-class JavaTask extends Java {
- override def getTaskName() = "partest"
- private val scalaRunnerClass = "scala.tools.nsc.MainGenericRunner"
- private val partestRunnerClass = "scala.tools.partest.Runner"
- def defaultJvmArgs = "-Xms64M -Xmx768M -Xss768K -XX:MaxPermSize=96M"
-
- protected def rootDir = prop("partest.rootdir") getOrElse (baseDir / "test").path
- protected def partestJVMArgs = prop("partest.jvm.args") getOrElse defaultJvmArgs
- protected def runnerArgs = List("-usejavacp", partestRunnerClass, "--javaopts", partestJVMArgs)
-
- private def baseDir = Directory(getProject.getBaseDir)
- private def prop(s: String) = Option(getProject getProperty s)
- private def jvmline(s: String) = returning(createJvmarg())(_ setLine s)
- private def addArg(s: String) = returning(createArg())(_ setValue s)
-
- private def newKeyValue(key: String, value: String) =
- returning(new Environment.Variable)(x => { x setKey key ; x setValue value })
-
- def setDefaults() {
- setFork(true)
- setFailonerror(true)
- getProject.setSystemProperties()
- setClassname(scalaRunnerClass)
- addSysproperty(newKeyValue("partest.is-in-ant", "true"))
- jvmline(partestJVMArgs)
- runnerArgs foreach addArg
-
- // do we want basedir or rootDir to be the cwd?
- // setDir(Path(rootDir).jfile)
- }
-
- override def init() = {
- super.init()
- setDefaults()
- }
-}
-
diff --git a/src/partest-alternative/scala/tools/partest/antlib.xml b/src/partest-alternative/scala/tools/partest/antlib.xml
deleted file mode 100644
index af36f11368..0000000000
--- a/src/partest-alternative/scala/tools/partest/antlib.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<antlib>
- <taskdef name="partest" classname="scala.tools.partest.ant.JavaTask"/>
-</antlib>
diff --git a/src/partest-alternative/scala/tools/partest/category/AllCategories.scala b/src/partest-alternative/scala/tools/partest/category/AllCategories.scala
deleted file mode 100644
index 1c3f4c9899..0000000000
--- a/src/partest-alternative/scala/tools/partest/category/AllCategories.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package category
-
-trait AllCategories extends Compiler with Analysis with Runner {
- self: Universe =>
-
- object Pos extends DirBasedCategory("pos") { lazy val testSequence: TestSequence = List(compile) }
- object Neg extends DirBasedCategory("neg") { lazy val testSequence: TestSequence = List(checkFileRequired, not(compile), diff) }
- object Run extends DirBasedCategory("run") { lazy val testSequence: TestSequence = List(compile, run, diff) }
- object Jvm extends DirBasedCategory("jvm") { lazy val testSequence: TestSequence = List(compile, run, diff) }
-}
diff --git a/src/partest-alternative/scala/tools/partest/category/Analysis.scala b/src/partest-alternative/scala/tools/partest/category/Analysis.scala
deleted file mode 100644
index 944f8c691f..0000000000
--- a/src/partest-alternative/scala/tools/partest/category/Analysis.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package category
-
-import java.lang.{ ClassLoader => JavaClassLoader }
-import java.net.URL
-import nsc.util.ScalaClassLoader
-import nsc.io._
-
-class PartestClassLoader(urls: Array[URL], parent: JavaClassLoader) extends ScalaClassLoader.URLClassLoader(urls, parent) {
- def this(urls: Array[URL]) = this(urls, null)
- def bytes(path: String) = findBytesForClassName(path)
- def singleton(path: String) = tryToInitializeClass(path).get getField "MODULE$" get null
-
- /** Calls a method in an object via reflection.
- */
- def apply[T](className: String, methodName: String)(args: Any*): T = {
- def fail = error("Reflection failed on %s.%s".format(className, methodName))
- val clazz = tryToLoadClass(className) getOrElse fail
- val obj = singleton(className)
- val m = clazz.getMethods find (x => x.getName == methodName && x.getParameterTypes.size == args.size) getOrElse fail
-
- m.invoke(obj, args map (_.asInstanceOf[AnyRef]): _*).asInstanceOf[T]
- }
-}
-
-trait Analysis {
- self: Universe =>
-
- object Scalap extends DirBasedCategory("scalap") {
- val testSequence: TestSequence = List(checkFileRequired, compile, run, diff)
- override def denotesTest(p: Path) = p.isDirectory && (p.toDirectory.files exists (_.name == "result.test"))
- override def createTest(location: Path) = new ScalapTest(location)
-
- class ScalapTest(val location: Path) extends TestEntity {
- val category = Scalap
- val scalapMain = "scala.tools.scalap.Main$"
- val scalapMethod = "decompileScala"
-
- override def classpathPaths = super.classpathPaths :+ build.scalap
- override def checkFile = File(location / "result.test")
-
- private def runnerURLs = build.classpathPaths ::: classpathPaths map (_.toURL)
- private def createClassLoader = new PartestClassLoader(runnerURLs.toArray, this.getClass.getClassLoader)
-
- val isPackageObject = containsString("package object")
- val suffix = if (isPackageObject) ".package" else ""
- val className = location.name.capitalize + suffix
-
- override def run() = loggingResult {
- def loader = createClassLoader
- def bytes = loader.bytes(className)
-
- trace("scalap %s".format(className))
- if (isDryRun) ""
- else loader[String](scalapMain, scalapMethod)(bytes, isPackageObject)
- }
- }
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/category/Compiler.scala b/src/partest-alternative/scala/tools/partest/category/Compiler.scala
deleted file mode 100644
index 6b65072856..0000000000
--- a/src/partest-alternative/scala/tools/partest/category/Compiler.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package category
-
-import nsc.io._
-import nsc.reporters._
-import nsc.{ Settings, CompilerCommand }
-import scala.tools.nsc.interactive.RefinedBuildManager
-import util.copyPath
-
-trait Compiler {
- self: Universe =>
-
- /** Resident Compiler.
- * $SCALAC -d dir.obj -Xresident -sourcepath . "$@"
- */
- object Res extends DirBasedCategory("res") {
- lazy val testSequence: TestSequence = List(checkFileRequired, compile, diff)
-
- override def denotesTest(p: Path) = p.isDirectory && resFile(p).isFile
- override def createTest(location: Path) = new ResidentTest(location.toDirectory)
-
- override def createSettings(entity: TestEntity): TestSettings =
- returning(super.createSettings(entity)) { settings =>
- settings.resident.value = true
- settings.sourcepath.value = entity.sourcesDir.path
- }
-
- class ResidentTest(val location: Directory) extends TestEntity {
- val category = Res
- override def sourcesDir = categoryDir
-
- override def acknowledges(p: Path) =
- super.acknowledges(p) || (resFile(location) isSame p)
-
- private def residentCompilerCommands = safeLines(resFile(location))
- private def compileResident(global: PartestGlobal, lines: List[String]) = {
- def printPrompt = global inform "nsc> "
- val results =
- lines map { line =>
- printPrompt
- trace("compile " + line)
- isDryRun || global.partestCompile(toArgs(line) map (categoryDir / _ path), false)
- }
-
- printPrompt
-
- /** Note - some res tests are really "neg" style tests, so we can't
- * use the return value of the compile. The diff catches failures.
- */
- true // results forall (_ == true)
- }
-
- override def compile() = compileResident(newGlobal(Nil)._1, residentCompilerCommands)
- }
- private[Res] def resFile(p: Path) = p.toFile addExtension "res"
- }
-
- object BuildManager extends DirBasedCategory("buildmanager") {
- lazy val testSequence: TestSequence = List(checkFileRequired, compile, diff)
- override def denotesTest(p: Path) = p.isDirectory && testFile(p).isFile
- override def createTest(location: Path) = new BuildManagerTest(location.toDirectory)
-
- override def createSettings(entity: TestEntity): TestSettings =
- returning[TestSettings](super.createSettings(entity)) { settings =>
- settings.Ybuildmanagerdebug.value = true
- settings.sourcepath.value = entity.sourcesDir.path
- }
-
- class PartestBuildManager(settings: Settings, val reporter: ConsoleReporter) extends RefinedBuildManager(settings) {
- def errorFn(msg: String) = Console println msg
-
- override protected def newCompiler(newSettings: Settings) =
- new BuilderGlobal(newSettings, reporter)
-
- private def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
- fs flatMap (s => Option(AbstractFile getFile (Path(settings.sourcepath.value) / s path))) toSet
-
- def buildManagerCompile(line: String): Boolean = {
- val prompt = "builder > "
- reporter printMessage (prompt + line)
- val command = new CompilerCommand(toArgs(line), settings)
- val files = filesToSet(settings.sourcepath.value, command.files)
-
- update(files, Set.empty)
- true
- }
- }
-
- private[BuildManager] def testFile(p: Path) = (p / p.name addExtension "test").toFile
-
- class BuildManagerTest(val location: Directory) extends TestEntity {
- val category = BuildManager
-
- override def sourcesDir = outDir
- override def sourceFiles = Path onlyFiles (location walkFilter (_ != changesDir) filter isJavaOrScala toList)
- override def checkFile = File(location / location.name addExtension "check")
-
- override def acknowledges(p: Path) = super.acknowledges(p) || (p isSame testFile(location))
-
- def buildManagerCommands = safeLines(testFile(location))
- def changesDir = Directory(location / (location.name + ".changes"))
-
- override def compile() = {
- val settings = createSettings(this)
- val pbm = new PartestBuildManager(settings, newReporter(settings))
-
- // copy files
- for (source <- sourceFiles) {
- val target = outDir / (location.normalize relativize source)
- copyPath(source, target.toFile)
- }
-
- def runUpdate(line: String) = {
- val Array(srcName, replacement) = line split "=>"
- copyPath(File(changesDir / replacement), File(outDir / srcName))
- }
-
- def sendCommand(line: String): Boolean = {
- val compileRegex = """^>>compile (.*)$""".r
- val updateRegex = """^>>update\s+(.*)""".r
- trace("send: " + (line drop 2))
-
- isDryRun || (line match {
- case compileRegex(xs) => pbm.buildManagerCompile(xs)
- case updateRegex(line) => runUpdate(line)
- })
- }
-
- // send each line to the build manager
- buildManagerCommands forall sendCommand
- }
- }
- }
-}
-
diff --git a/src/partest-alternative/scala/tools/partest/category/Runner.scala b/src/partest-alternative/scala/tools/partest/category/Runner.scala
deleted file mode 100644
index add1c55feb..0000000000
--- a/src/partest-alternative/scala/tools/partest/category/Runner.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package category
-
-import nsc.io._
-
-trait Runner {
- self: Universe =>
-
- /** Shootout.
- */
- object Shootout extends DirBasedCategory("shootout") {
- lazy val testSequence: TestSequence = List(compile, run, diff)
-
- override def denotesTest(p: Path) = isScala(p) && runner(p).isFile
- override def createTest(location: Path) = new ShootoutTest(location.toFile)
-
- class ShootoutTest(val location: File) extends TestEntity {
- val category = Shootout
- // The files in shootout are very free form, so acknowledge anything close.
- override def acknowledges(p: Path) =
- (p.parent.normalize isSame Shootout.root) && (p.name startsWith label)
-
- private def generated = File(outDir / "test.scala")
- private def runnerFile = runner(location)
- override def sourceFiles = List(generated)
-
- override def compile() = {
- trace("generate %s from %s, %s".format(tracePath(generated), tracePath(location), tracePath(runnerFile)))
- // generate source file (even on dry run, we need the path)
- generated.writeAll(location.slurp(), runnerFile.slurp())
-
- // compile generated file
- super.compile()
- }
- }
-
- private[Shootout] def runner(p: Path) = p addExtension "runner" toFile
- }
-
- object Scalacheck extends DirBasedCategory("scalacheck") {
- lazy val testSequence: TestSequence = List(compile, run)
- override def createTest(location: Path) = new ScalacheckTest(location)
-
- class ScalacheckTest(val location: Path) extends TestEntity {
- val category = Scalacheck
-
- import build.{ scalacheck, forkjoin }
- import org.scalacheck.Properties
- import org.scalacheck.Test.{ checkProperties, defaultParams, Result }
-
- override def classpathPaths = super.classpathPaths ::: List(scalacheck, forkjoin)
- private def arrayURLs = Array(scalacheck, outDir) map (_.toURL)
-
- /** For reasons I'm not entirely clear on, I've written all this
- * to avoid a source dependency on scalacheck.
- */
- class ScalacheckClassLoader extends PartestClassLoader(arrayURLs, this.getClass.getClassLoader) {
- type ScalacheckResult = { def passed: Boolean }
-
- def propCallback(name: String, passed: Int, discarded: Int): Unit = ()
- def testCallback(name: String, result: AnyRef): Unit = ()
-
- val test = singleton("Test$")
- val params = apply[AnyRef]("org.scalacheck.Test$", "defaultParams")()
- val result = apply[Seq[(String, AnyRef)]]("org.scalacheck.Test$", "checkProperties")(test, params, propCallback _, testCallback _)
-
- def allResults() =
- for ((prop, res) <- result) yield {
- ScalacheckTest.this.trace("%s: %s".format(prop, res))
- res.asInstanceOf[ScalacheckResult].passed
- }
-
- def check() = allResults forall (_ == true)
- }
-
- override def run() = {
- trace("scalacheck runs via classloader with: %s".format(arrayURLs mkString ", "))
- isDryRun || (new ScalacheckClassLoader check)
- }
- }
- }
-
- object Script extends DirBasedCategory("script") {
- val testSequence: TestSequence = List(exec, diff)
- override def createTest(location: Path) = new ScriptTest(location)
-
- class ScriptTest(val location: Path) extends TestEntity {
- val category = Script
- val scriptFile = if (location.isDirectory) location / (label + ".scala") else location
- val argsFile = withExtension("args").toFile
- def batFile = scriptFile changeExtension "bat"
- def script = if (Properties.isWin) batFile else scriptFile
-
- override def acknowledges(p: Path) = super.acknowledges(p) || (List(argsFile, batFile) exists (_ isSame p))
- override def execCwd = Some(sourcesDir)
- override def argumentsToExec = script.path :: safeArgs(argsFile)
- }
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/io/ANSIWriter.scala b/src/partest-alternative/scala/tools/partest/io/ANSIWriter.scala
deleted file mode 100644
index 59216cf03b..0000000000
--- a/src/partest-alternative/scala/tools/partest/io/ANSIWriter.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-package io
-
-import java.io.{ Writer, PrintWriter, OutputStream, OutputStreamWriter }
-
-object ANSIWriter {
- val NONE = 0
- val SOME = 1
- val MANY = 2
-
- def apply(isAnsi: Boolean) = if (isAnsi) MANY else NONE
-}
-import ANSIWriter._
-
-class ANSIWriter(writer: Writer) extends PrintWriter(writer, true) {
- def this(out: OutputStream) = this(new OutputStreamWriter(out))
- def colorful: Int = NONE
-
- protected val manyColors = List(
- Console.BOLD + Console.BLACK,
- Console.BOLD + Console.GREEN,
- Console.BOLD + Console.RED,
- Console.BOLD + Console.YELLOW,
- Console.RESET
- )
- protected val someColors = List(
- Console.BOLD + Console.BLACK,
- Console.RESET,
- Console.BOLD + Console.BLACK,
- Console.BOLD + Console.BLACK,
- Console.RESET
- )
- protected val noColors = List("", "", "", "", "")
-
- lazy val List(_outline, _success, _failure, _warning, _default) = colorful match {
- case NONE => noColors
- case SOME => someColors
- case MANY => manyColors
- case _ => noColors
- }
-
- private def wrprint(msg: String): Unit = synchronized {
- print(msg)
- flush()
- }
-
- def outline(msg: String) = wrprint(_outline + msg + _default)
- def success(msg: String) = wrprint(_success + msg + _default)
- def failure(msg: String) = wrprint(_failure + msg + _default)
- def warning(msg: String) = wrprint(_warning + msg + _default)
- def normal(msg: String) = wrprint(_default + msg)
-}
diff --git a/src/partest-alternative/scala/tools/partest/io/Diff.java b/src/partest-alternative/scala/tools/partest/io/Diff.java
deleted file mode 100644
index 69428d7e7a..0000000000
--- a/src/partest-alternative/scala/tools/partest/io/Diff.java
+++ /dev/null
@@ -1,873 +0,0 @@
-
-package scala.tools.partest.io;
-
-import java.util.Hashtable;
-
-/** A class to compare IndexedSeqs of objects. The result of comparison
- is a list of <code>change</code> objects which form an
- edit script. The objects compared are traditionally lines
- of text from two files. Comparison options such as "ignore
- whitespace" are implemented by modifying the <code>equals</code>
- and <code>hashcode</code> methods for the objects compared.
-<p>
- The basic algorithm is described in: </br>
- "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
- Algorithmica Vol. 1 No. 2, 1986, p 251.
-<p>
- This class outputs different results from GNU diff 1.15 on some
- inputs. Our results are actually better (smaller change list, smaller
- total size of changes), but it would be nice to know why. Perhaps
- there is a memory overwrite bug in GNU diff 1.15.
-
- @author Stuart D. Gathman, translated from GNU diff 1.15
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the <a href=COPYING.txt>
- GNU General Public License</a>
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-public class Diff {
-
- /** Prepare to find differences between two arrays. Each element of
- the arrays is translated to an "equivalence number" based on
- the result of <code>equals</code>. The original Object arrays
- are no longer needed for computing the differences. They will
- be needed again later to print the results of the comparison as
- an edit script, if desired.
- */
- public Diff(Object[] a,Object[] b) {
- Hashtable h = new Hashtable(a.length + b.length);
- filevec[0] = new file_data(a,h);
- filevec[1] = new file_data(b,h);
- }
-
- /** 1 more than the maximum equivalence value used for this or its
- sibling file. */
- private int equiv_max = 1;
-
- /** When set to true, the comparison uses a heuristic to speed it up.
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
- public boolean heuristic = false;
-
- /** When set to true, the algorithm returns a guarranteed minimal
- set of changes. This makes things slower, sometimes much slower. */
- public boolean no_discards = false;
-
- private int[] xvec, yvec; /* IndexedSeqs being compared. */
- private int[] fdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the forward
- search of the edit matrix. */
- private int[] bdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the backward
- search of the edit matrix. */
- private int fdiagoff, bdiagoff;
- private final file_data[] filevec = new file_data[2];
- private int cost;
-
- /** Find the midpoint of the shortest edit script for a specified
- portion of the two files.
-
- We scan from the beginnings of the files, and simultaneously from the ends,
- doing a breadth-first search through the space of edit-sequence.
- When the two searches meet, we have found the midpoint of the shortest
- edit sequence.
-
- The value returned is the number of the diagonal on which the midpoint lies.
- The diagonal number equals the number of inserted lines minus the number
- of deleted lines (counting only lines before the midpoint).
- The edit cost is stored into COST; this is the total number of
- lines inserted or deleted (counting only lines before the midpoint).
-
- This function assumes that the first lines of the specified portions
- of the two files do not match, and likewise that the last lines do not
- match. The caller must trim matching lines from the beginning and end
- of the portions it is going to specify.
-
- Note that if we return the "wrong" diagonal value, or if
- the value of bdiag at that diagonal is "wrong",
- the worst this can do is cause suboptimal diff output.
- It cannot cause incorrect diff output. */
-
- private int diag (int xoff, int xlim, int yoff, int ylim) {
- final int[] fd = fdiag; // Give the compiler a chance.
- final int[] bd = bdiag; // Additional help for the compiler.
- final int[] xv = xvec; // Still more help for the compiler.
- final int[] yv = yvec; // And more and more . . .
- final int dmin = xoff - ylim; // Minimum valid diagonal.
- final int dmax = xlim - yoff; // Maximum valid diagonal.
- final int fmid = xoff - yoff; // Center diagonal of top-down search.
- final int bmid = xlim - ylim; // Center diagonal of bottom-up search.
- int fmin = fmid, fmax = fmid; // Limits of top-down search.
- int bmin = bmid, bmax = bmid; // Limits of bottom-up search.
- /* True if southeast corner is on an odd
- diagonal with respect to the northwest. */
- final boolean odd = (fmid - bmid & 1) != 0;
-
- fd[fdiagoff + fmid] = xoff;
- bd[bdiagoff + bmid] = xlim;
-
- for (int c = 1;; ++c)
- {
- int d; /* Active diagonal. */
- boolean big_snake = false;
-
- /* Extend the top-down search by an edit step in each diagonal. */
- if (fmin > dmin)
- fd[fdiagoff + --fmin - 1] = -1;
- else
- ++fmin;
- if (fmax < dmax)
- fd[fdiagoff + ++fmax + 1] = -1;
- else
- --fmax;
- for (d = fmax; d >= fmin; d -= 2)
- {
- int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1];
-
- if (tlo >= thi)
- x = tlo + 1;
- else
- x = thi;
- oldx = x;
- y = x - d;
- while (x < xlim && y < ylim && xv[x] == yv[y]) {
- ++x; ++y;
- }
- if (x - oldx > 20)
- big_snake = true;
- fd[fdiagoff + d] = x;
- if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c - 1;
- return d;
- }
- }
-
- /* Similar extend the bottom-up search. */
- if (bmin > dmin)
- bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE;
- else
- ++bmin;
- if (bmax < dmax)
- bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE;
- else
- --bmax;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1];
-
- if (tlo < thi)
- x = tlo;
- else
- x = thi - 1;
- oldx = x;
- y = x - d;
- while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) {
- --x; --y;
- }
- if (oldx - x > 20)
- big_snake = true;
- bd[bdiagoff + d] = x;
- if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c;
- return d;
- }
- }
-
- /* Heuristic: check occasionally for a diagonal that has made
- lots of progress compared with the edit distance.
- If we have any such, find the one that has made the most
- progress and return it as if it had succeeded.
-
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
-
- if (c > 200 && big_snake && heuristic)
- {
- int best = 0;
- int bestpos = -1;
-
- for (d = fmax; d >= fmin; d -= 2)
- {
- int dd = d - fmid;
- if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if (fd[fdiagoff + d] * 2 - dd > best
- && fd[fdiagoff + d] - xoff > 20
- && fd[fdiagoff + d] - d - yoff > 20)
- {
- int k;
- int x = fd[fdiagoff + d];
-
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- for (k = 1; k <= 20; k++)
- if (xvec[x - k] != yvec[x - d - k])
- break;
-
- if (k == 21)
- {
- best = fd[fdiagoff + d] * 2 - dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
-
- best = 0;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int dd = d - bmid;
- if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if ((xlim - bd[bdiagoff + d]) * 2 + dd > best
- && xlim - bd[bdiagoff + d] > 20
- && ylim - (bd[bdiagoff + d] - d) > 20)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
- int x = bd[bdiagoff + d];
-
- for (k = 0; k < 20; k++)
- if (xvec[x + k] != yvec[x - d + k])
- break;
- if (k == 20)
- {
- best = (xlim - bd[bdiagoff + d]) * 2 + dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
- }
- }
- }
-
- /** Compare in detail contiguous subsequences of the two files
- which are known, as a whole, to match each other.
-
- The results are recorded in the IndexedSeqs filevec[N].changed_flag, by
- storing a 1 in the element for each line that is an insertion or deletion.
-
- The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
-
- Note that XLIM, YLIM are exclusive bounds.
- All line numbers are origin-0 and discarded lines are not counted. */
-
- private void compareseq (int xoff, int xlim, int yoff, int ylim) {
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) {
- ++xoff; ++yoff;
- }
- /* Slide up the top initial diagonal. */
- while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) {
- --xlim; --ylim;
- }
-
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true;
- else if (yoff == ylim)
- while (xoff < xlim)
- filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true;
- else
- {
- /* Find a point of correspondence in the middle of the files. */
-
- int d = diag (xoff, xlim, yoff, ylim);
- int c = cost;
- int f = fdiag[fdiagoff + d];
- int b = bdiag[bdiagoff + d];
-
- if (c == 1)
- {
- /* This should be impossible, because it implies that
- one of the two subsequences is empty,
- and that case was handled above without calling `diag'.
- Let's verify that this is true. */
- throw new IllegalArgumentException("Empty subsequence");
- }
- else
- {
- /* Use that point to split this problem into two subproblems. */
- compareseq (xoff, b, yoff, b - d);
- /* This used to use f instead of b,
- but that is incorrect!
- It is not necessarily the case that diagonal d
- has a snake from b to f. */
- compareseq (b, xlim, b - d, ylim);
- }
- }
- }
-
- /** Discard lines from one file that have no matches in the other file.
- */
-
- private void discard_confusing_lines() {
- filevec[0].discard_confusing_lines(filevec[1]);
- filevec[1].discard_confusing_lines(filevec[0]);
- }
-
- private boolean inhibit = false;
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
- */
-
- private void shift_boundaries() {
- if (inhibit)
- return;
- filevec[0].shift_boundaries(filevec[1]);
- filevec[1].shift_boundaries(filevec[0]);
- }
-
- public interface ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script.
- @param changed0 true for lines in first file which do not match 2nd
- @param len0 number of lines in first file
- @param changed1 true for lines in 2nd file which do not match 1st
- @param len1 number of lines in 2nd file
- @return a linked list of changes - or null
- */
- public change build_script(
- boolean[] changed0,int len0,
- boolean[] changed1,int len1
- );
- }
-
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in reverse order. */
-
- static class ReverseScript implements ScriptBuilder {
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = 0, i1 = 0;
- while (i0 < len0 || i1 < len1) {
- if (changed0[1+i0] || changed1[1+i1]) {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[1+i0]) ++i0;
- while (changed1[1+i1]) ++i1;
-
- /* Record this change. */
- script = new change(line0, line1, i0 - line0, i1 - line1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0++; i1++;
- }
-
- return script;
- }
- }
-
- static class ForwardScript implements ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in forward order. */
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = len0, i1 = len1;
-
- while (i0 >= 0 || i1 >= 0)
- {
- if (changed0[i0] || changed1[i1])
- {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[i0]) --i0;
- while (changed1[i1]) --i1;
-
- /* Record this change. */
- script = new change(i0, i1, line0 - i0, line1 - i1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0--; i1--;
- }
-
- return script;
- }
- }
-
- /** Standard ScriptBuilders. */
- public final static ScriptBuilder
- forwardScript = new ForwardScript(),
- reverseScript = new ReverseScript();
-
- /* Report the differences of two files. DEPTH is the current directory
- depth. */
- public final change diff_2(final boolean reverse) {
- return diff(reverse ? reverseScript : forwardScript);
- }
-
- /** Get the results of comparison as an edit script. The script
- is described by a list of changes. The standard ScriptBuilder
- implementations provide for forward and reverse edit scripts.
- Alternate implementations could, for instance, list common elements
- instead of differences.
- @param bld an object to build the script from change flags
- @return the head of a list of changes
- */
- public change diff(final ScriptBuilder bld) {
-
- /* Some lines are obviously insertions or deletions
- because they don't match anything. Detect them now,
- and avoid even thinking about them in the main comparison algorithm. */
-
- discard_confusing_lines ();
-
- /* Now do the main comparison algorithm, considering just the
- undiscarded lines. */
-
- xvec = filevec[0].undiscarded;
- yvec = filevec[1].undiscarded;
-
- int diags =
- filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3;
- fdiag = new int[diags];
- fdiagoff = filevec[1].nondiscarded_lines + 1;
- bdiag = new int[diags];
- bdiagoff = filevec[1].nondiscarded_lines + 1;
-
- compareseq (0, filevec[0].nondiscarded_lines,
- 0, filevec[1].nondiscarded_lines);
- fdiag = null;
- bdiag = null;
-
- /* Modify the results slightly to make them prettier
- in cases where that can validly be done. */
-
- shift_boundaries ();
-
- /* Get the results of comparison in the form of a chain
- of `struct change's -- an edit script. */
- return bld.build_script(
- filevec[0].changed_flag,
- filevec[0].buffered_lines,
- filevec[1].changed_flag,
- filevec[1].buffered_lines
- );
-
- }
-
- /** The result of comparison is an "edit script": a chain of change objects.
- Each change represents one place where some lines are deleted
- and some are inserted.
-
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
-
- public static class change {
- /** Previous or next edit command. */
- public change link;
- /** # lines of file 1 changed here. */
- public final int inserted;
- /** # lines of file 0 changed here. */
- public final int deleted;
- /** Line number of 1st deleted line. */
- public final int line0;
- /** Line number of 1st inserted line. */
- public final int line1;
-
- /** Cons an additional entry onto the front of an edit script OLD.
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
- public change(int line0, int line1, int deleted, int inserted, change old) {
- this.line0 = line0;
- this.line1 = line1;
- this.inserted = inserted;
- this.deleted = deleted;
- this.link = old;
- //System.err.println(line0+","+line1+","+inserted+","+deleted);
- }
- }
-
- /** Data on one input file being compared.
- */
-
- class file_data {
-
- /** Allocate changed array for the results of comparison. */
- void clear() {
- /* Allocate a flag for each line of each file, saying whether that line
- is an insertion or deletion.
- Allocate an extra element, always zero, at each end of each IndexedSeq.
- */
- changed_flag = new boolean[buffered_lines + 2];
- }
-
- /** Return equiv_count[I] as the number of lines in this file
- that fall in equivalence class I.
- @return the array of equivalence class counts.
- */
- int[] equivCount() {
- int[] equiv_count = new int[equiv_max];
- for (int i = 0; i < buffered_lines; ++i)
- ++equiv_count[equivs[i]];
- return equiv_count;
- }
-
- /** Discard lines that have no matches in another file.
-
- A line which is discarded will not be considered by the actual
- comparison algorithm; it will be as if that line were not in the file.
- The file's `realindexes' table maps virtual line numbers
- (which don't count the discarded lines) into real line numbers;
- this is how the actual comparison algorithm produces results
- that are comprehensible when the discarded lines are counted.
-<p>
- When we discard a line, we also mark it as a deletion or insertion
- so that it will be printed in the output.
- @param f the other file
- */
- void discard_confusing_lines(file_data f) {
- clear();
- /* Set up table of which lines are going to be discarded. */
- final byte[] discarded = discardable(f.equivCount());
-
- /* Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
- filterDiscards(discarded);
-
- /* Actually discard the lines. */
- discard(discarded);
- }
-
- /** Mark to be discarded each line that matches no line of another file.
- If a line matches many lines, mark it as provisionally discardable.
- @see equivCount()
- @param counts The count of each equivalence number for the other file.
- @return 0=nondiscardable, 1=discardable or 2=provisionally discardable
- for each line
- */
-
- private byte[] discardable(final int[] counts) {
- final int end = buffered_lines;
- final byte[] discards = new byte[end];
- final int[] equivs = this.equivs;
- int many = 5;
- int tem = end / 64;
-
- /* Multiply MANY by approximate square root of number of lines.
- That is the threshold for provisionally discardable lines. */
- while ((tem = tem >> 2) > 0)
- many *= 2;
-
- for (int i = 0; i < end; i++)
- {
- int nmatch;
- if (equivs[i] == 0)
- continue;
- nmatch = counts[equivs[i]];
- if (nmatch == 0)
- discards[i] = 1;
- else if (nmatch > many)
- discards[i] = 2;
- }
- return discards;
- }
-
- /** Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
-
- private void filterDiscards(final byte[] discards) {
- final int end = buffered_lines;
-
- for (int i = 0; i < end; i++)
- {
- /* Cancel provisional discards not in middle of run of discards. */
- if (discards[i] == 2)
- discards[i] = 0;
- else if (discards[i] != 0)
- {
- /* We have found a nonprovisional discard. */
- int j;
- int length;
- int provisional = 0;
-
- /* Find end of this run of discardable lines.
- Count how many are provisionally discardable. */
- for (j = i; j < end; j++)
- {
- if (discards[j] == 0)
- break;
- if (discards[j] == 2)
- ++provisional;
- }
-
- /* Cancel provisional discards at end, and shrink the run. */
- while (j > i && discards[j - 1] == 2) {
- discards[--j] = 0; --provisional;
- }
-
- /* Now we have the length of a run of discardable lines
- whose first and last are not provisional. */
- length = j - i;
-
- /* If 1/4 of the lines in the run are provisional,
- cancel discarding of all provisional lines in the run. */
- if (provisional * 4 > length)
- {
- while (j > i)
- if (discards[--j] == 2)
- discards[j] = 0;
- }
- else
- {
- int consec;
- int minimum = 1;
- int tem = length / 4;
-
- /* MINIMUM is approximate square root of LENGTH/4.
- A subrun of two or more provisionals can stand
- when LENGTH is at least 16.
- A subrun of 4 or more can stand when LENGTH >= 64. */
- while ((tem = tem >> 2) > 0)
- minimum *= 2;
- minimum++;
-
- /* Cancel any subrun of MINIMUM or more provisionals
- within the larger run. */
- for (j = 0, consec = 0; j < length; j++)
- if (discards[i + j] != 2)
- consec = 0;
- else if (minimum == ++consec)
- /* Back up to start of subrun, to cancel it all. */
- j -= consec;
- else if (minimum < consec)
- discards[i + j] = 0;
-
- /* Scan from beginning of run
- until we find 3 or more nonprovisionals in a row
- or until the first nonprovisional at least 8 lines in.
- Until that point, cancel any provisionals. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i + j] == 1)
- break;
- if (discards[i + j] == 2) {
- consec = 0; discards[i + j] = 0;
- }
- else if (discards[i + j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
-
- /* I advances to the last line of the run. */
- i += length - 1;
-
- /* Same thing, from end. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i - j] == 1)
- break;
- if (discards[i - j] == 2) {
- consec = 0; discards[i - j] = 0;
- }
- else if (discards[i - j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
- }
- }
- }
- }
-
- /** Actually discard the lines.
- @param discards flags lines to be discarded
- */
- private void discard(final byte[] discards) {
- final int end = buffered_lines;
- int j = 0;
- for (int i = 0; i < end; ++i)
- if (no_discards || discards[i] == 0)
- {
- undiscarded[j] = equivs[i];
- realindexes[j++] = i;
- }
- else
- changed_flag[1+i] = true;
- nondiscarded_lines = j;
- }
-
- file_data(Object[] data,Hashtable h) {
- buffered_lines = data.length;
-
- equivs = new int[buffered_lines];
- undiscarded = new int[buffered_lines];
- realindexes = new int[buffered_lines];
-
- for (int i = 0; i < data.length; ++i) {
- Integer ir = (Integer)h.get(data[i]);
- if (ir == null)
- h.put(data[i],new Integer(equivs[i] = equiv_max++));
- else
- equivs[i] = ir.intValue();
- }
- }
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
-
- We do something when a run of changed lines include a blank
- line at one end and have an excluded blank line at the other.
- We are free to choose which blank line is included.
- `compareseq' always chooses the one at the beginning,
- but usually it is cleaner to consider the following blank line
- to be the "change". The only exception is if the preceding blank line
- would join this change to other changes.
- @param f the file being compared against
- */
-
- void shift_boundaries(file_data f) {
- final boolean[] changed = changed_flag;
- final boolean[] other_changed = f.changed_flag;
- int i = 0;
- int j = 0;
- int i_end = buffered_lines;
- int preceding = -1;
- int other_preceding = -1;
-
- for (;;)
- {
- int start, end, other_start;
-
- /* Scan forwards to find beginning of another run of changes.
- Also keep track of the corresponding point in the other file. */
-
- while (i < i_end && !changed[1+i])
- {
- while (other_changed[1+j++])
- /* Non-corresponding lines in the other file
- will count as the preceding batch of changes. */
- other_preceding = j;
- i++;
- }
-
- if (i == i_end)
- break;
-
- start = i;
- other_start = j;
-
- for (;;)
- {
- /* Now find the end of this run of changes. */
-
- while (i < i_end && changed[1+i]) i++;
- end = i;
-
- /* If the first changed line matches the following unchanged one,
- and this run does not follow right after a previous run,
- and there are no lines deleted from the other file here,
- then classify the first changed line as unchanged
- and the following line as changed in its place. */
-
- /* You might ask, how could this run follow right after another?
- Only because the previous run was shifted here. */
-
- if (end != i_end
- && equivs[start] == equivs[end]
- && !other_changed[1+j]
- && end != i_end
- && !((preceding >= 0 && start == preceding)
- || (other_preceding >= 0
- && other_start == other_preceding)))
- {
- changed[1+end++] = true;
- changed[1+start++] = false;
- ++i;
- /* Since one line-that-matches is now before this run
- instead of after, we must advance in the other file
- to keep in synch. */
- ++j;
- }
- else
- break;
- }
-
- preceding = i;
- other_preceding = j;
- }
- }
-
- /** Number of elements (lines) in this file. */
- final int buffered_lines;
-
- /** IndexedSeq, indexed by line number, containing an equivalence code for
- each line. It is this IndexedSeq that is actually compared with that
- of another file to generate differences. */
- private final int[] equivs;
-
- /** IndexedSeq, like the previous one except that
- the elements for discarded lines have been squeezed out. */
- final int[] undiscarded;
-
- /** IndexedSeq mapping virtual line numbers (not counting discarded lines)
- to real ones (counting those lines). Both are origin-0. */
- final int[] realindexes;
-
- /** Total number of nondiscarded lines. */
- int nondiscarded_lines;
-
- /** Array, indexed by real origin-1 line number,
- containing true for a line that is an insertion or a deletion.
- The results of comparison are stored here. */
- boolean[] changed_flag;
-
- }
-}
diff --git a/src/partest-alternative/scala/tools/partest/io/DiffPrint.java b/src/partest-alternative/scala/tools/partest/io/DiffPrint.java
deleted file mode 100644
index 273b6cba52..0000000000
--- a/src/partest-alternative/scala/tools/partest/io/DiffPrint.java
+++ /dev/null
@@ -1,606 +0,0 @@
-
-package scala.tools.partest.io;
-
-import java.io.*;
-import java.util.Vector;
-import java.util.Date;
-//import com.objectspace.jgl.predicates.UnaryPredicate;
-
-interface UnaryPredicate {
- boolean execute(Object obj);
-}
-
-/** A simple framework for printing change lists produced by <code>Diff</code>.
- @see bmsi.util.Diff
- @author Stuart D. Gathman
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-public class DiffPrint {
- /** A Base class for printing edit scripts produced by Diff.
- This class divides the change list into "hunks", and calls
- <code>print_hunk</code> for each hunk. Various utility methods
- are provided as well.
- */
- public static abstract class Base {
- protected Base(Object[] a,Object[] b, Writer w) {
- outfile = new PrintWriter(w);
- file0 = a;
- file1 = b;
- }
- /** Set to ignore certain kinds of lines when printing
- an edit script. For example, ignoring blank lines or comments.
- */
- protected UnaryPredicate ignore = null;
-
- /** Set to the lines of the files being compared.
- */
- protected Object[] file0, file1;
-
- /** Divide SCRIPT into pieces by calling HUNKFUN and
- print each piece with PRINTFUN.
- Both functions take one arg, an edit script.
-
- PRINTFUN takes a subscript which belongs together (with a null
- link at the end) and prints it. */
- public void print_script(Diff.change script) {
- Diff.change next = script;
-
- while (next != null)
- {
- Diff.change t, end;
-
- /* Find a set of changes that belong together. */
- t = next;
- end = hunkfun(next);
-
- /* Disconnect them from the rest of the changes,
- making them a hunk, and remember the rest for next iteration. */
- next = end.link;
- end.link = null;
- //if (DEBUG)
- // debug_script(t);
-
- /* Print this hunk. */
- print_hunk(t);
-
- /* Reconnect the script so it will all be freed properly. */
- end.link = next;
- }
- outfile.flush();
- }
-
- /** Called with the tail of the script
- and returns the last link that belongs together with the start
- of the tail. */
-
- protected Diff.change hunkfun(Diff.change hunk) {
- return hunk;
- }
-
- protected int first0, last0, first1, last1, deletes, inserts;
- protected PrintWriter outfile;
-
- /** Look at a hunk of edit script and report the range of lines in each file
- that it applies to. HUNK is the start of the hunk, which is a chain
- of `struct change'. The first and last line numbers of file 0 are stored
- in *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
- Note that these are internal line numbers that count from 0.
-
- If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
-
- Also set *DELETES nonzero if any lines of file 0 are deleted
- and set *INSERTS nonzero if any lines of file 1 are inserted.
- If only ignorable lines are inserted or deleted, both are
- set to 0. */
-
- protected void analyze_hunk(Diff.change hunk) {
- int f0, l0 = 0, f1, l1 = 0, show_from = 0, show_to = 0;
- int i;
- Diff.change next;
- boolean nontrivial = (ignore == null);
-
- show_from = show_to = 0;
-
- f0 = hunk.line0;
- f1 = hunk.line1;
-
- for (next = hunk; next != null; next = next.link)
- {
- l0 = next.line0 + next.deleted - 1;
- l1 = next.line1 + next.inserted - 1;
- show_from += next.deleted;
- show_to += next.inserted;
- for (i = next.line0; i <= l0 && ! nontrivial; i++)
- if (!ignore.execute(file0[i]))
- nontrivial = true;
- for (i = next.line1; i <= l1 && ! nontrivial; i++)
- if (!ignore.execute(file1[i]))
- nontrivial = true;
- }
-
- first0 = f0;
- last0 = l0;
- first1 = f1;
- last1 = l1;
-
- /* If all inserted or deleted lines are ignorable,
- tell the caller to ignore this hunk. */
-
- if (!nontrivial)
- show_from = show_to = 0;
-
- deletes = show_from;
- inserts = show_to;
- }
-
- /** Print the script header which identifies the files compared. */
- protected void print_header(String filea, String fileb) { }
-
- protected abstract void print_hunk(Diff.change hunk);
-
- protected void print_1_line(String pre,Object linbuf) {
- outfile.println(pre + linbuf.toString());
- }
-
- /** Print a pair of line numbers with SEPCHAR, translated for file FILE.
- If the two numbers are identical, print just one number.
-
- Args A and B are internal line numbers.
- We print the translated (real) line numbers. */
-
- protected void print_number_range (char sepchar, int a, int b) {
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (++b > ++a)
- outfile.print("" + a + sepchar + b);
- else
- outfile.print(b);
- }
-
- public static char change_letter(int inserts, int deletes) {
- if (inserts == 0)
- return 'd';
- else if (deletes == 0)
- return 'a';
- else
- return 'c';
- }
- }
-
- /** Print a change list in the standard diff format.
- */
- public static class NormalPrint extends Base {
-
- public NormalPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of a normal diff.
- This is a contiguous portion of a complete edit script,
- describing changes in consecutive lines. */
-
- protected void print_hunk (Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk(hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.print(change_letter(inserts, deletes));
- print_number_range (',', first1, last1);
- outfile.println();
-
- /* Print the lines that the first file has. */
- if (deletes != 0)
- for (int i = first0; i <= last0; i++)
- print_1_line ("< ", file0[i]);
-
- if (inserts != 0 && deletes != 0)
- outfile.println("---");
-
- /* Print the lines that the second file has. */
- if (inserts != 0)
- for (int i = first1; i <= last1; i++)
- print_1_line ("> ", file1[i]);
- }
- }
-
- /** Prints an edit script in a format suitable for input to <code>ed</code>.
- The edit script must be generated with the reverse option to
- be useful as actual <code>ed</code> input.
- */
- public static class EdPrint extends Base {
-
- public EdPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of an ed diff */
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.println(change_letter(inserts, deletes));
-
- /* Print new/changed lines from second file, if needed */
- if (inserts != 0)
- {
- boolean inserting = true;
- for (int i = first1; i <= last1; i++)
- {
- /* Resume the insert, if we stopped. */
- if (! inserting)
- outfile.println(i - first1 + first0 + "a");
- inserting = true;
-
- /* If the file's line is just a dot, it would confuse `ed'.
- So output it with a double dot, and set the flag LEADING_DOT
- so that we will output another ed-command later
- to change the double dot into a single dot. */
-
- if (".".equals(file1[i]))
- {
- outfile.println("..");
- outfile.println(".");
- /* Now change that double dot to the desired single dot. */
- outfile.println(i - first1 + first0 + 1 + "s/^\\.\\././");
- inserting = false;
- }
- else
- /* Line is not `.', so output it unmodified. */
- print_1_line ("", file1[i]);
- }
-
- /* End insert mode, if we are still in it. */
- if (inserting)
- outfile.println(".");
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class ContextPrint extends Base {
-
- protected int context = 3;
-
- public ContextPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- protected void print_context_label (String mark, File inf, String label) {
- if (label != null)
- outfile.println(mark + ' ' + label);
- else if (inf.lastModified() > 0)
- // FIXME: use DateFormat to get precise format needed.
- outfile.println(
- mark + ' ' + inf.getPath() + '\t' + new Date(inf.lastModified())
- );
- else
- /* Don't pretend that standard input is ancient. */
- outfile.println(mark + ' ' + inf.getPath());
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("***", new File(filea), filea);
- print_context_label ("---", new File(fileb), fileb);
- }
-
- /** If function_regexp defined, search for start of function. */
- private String find_function(Object[] lines, int start) {
- return null;
- }
-
- protected void print_function(Object[] file,int start) {
- String function = find_function (file0, first0);
- if (function != null) {
- outfile.print(" ");
- outfile.print(
- (function.length() < 40) ? function : function.substring(0,40)
- );
- }
- }
-
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
-
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
- outfile.print("***************");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function (file0, first0);
-
- outfile.println();
- outfile.print("*** ");
- print_number_range (',', first0, last0);
- outfile.println(" ****");
-
- if (deletes != 0) {
- Diff.change next = hunk;
-
- for (int i = first0; i <= last0; i++) {
- /* Skip past changes that apply (in file 0)
- only to lines before line I. */
-
- while (next != null && next.line0 + next.deleted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line0 <= i)
- /* The change NEXT covers this line.
- If lines were inserted here in file 1, this is "changed".
- Otherwise it is "deleted". */
- prefix = (next.inserted > 0) ? "!" : "-";
-
- print_1_line (prefix, file0[i]);
- }
- }
-
- outfile.print("--- ");
- print_number_range (',', first1, last1);
- outfile.println(" ----");
-
- if (inserts != 0) {
- Diff.change next = hunk;
-
- for (int i = first1; i <= last1; i++) {
- /* Skip past changes that apply (in file 1)
- only to lines before line I. */
-
- while (next != null && next.line1 + next.inserted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line1 <= i)
- /* The change NEXT covers this line.
- If lines were deleted here in file 0, this is "changed".
- Otherwise it is "inserted". */
- prefix = (next.deleted > 0) ? "!" : "+";
-
- print_1_line (prefix, file1[i]);
- }
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class UnifiedPrint extends ContextPrint {
-
- public UnifiedPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("---", new File(filea), filea);
- print_context_label ("+++", new File(fileb), fileb);
- }
-
- private void print_number_range (int a, int b) {
- //translate_range (file, a, b, &trans_a, &trans_b);
-
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (b < a)
- outfile.print(b + ",0");
- else
- super.print_number_range(',',a,b);
- }
-
- protected void print_hunk(Diff.change hunk) {
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
-
- outfile.print("@@ -");
- print_number_range (first0, last0);
- outfile.print(" +");
- print_number_range (first1, last1);
- outfile.print(" @@");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function(file0,first0);
-
- outfile.println();
-
- Diff.change next = hunk;
- int i = first0;
- int j = first1;
-
- while (i <= last0 || j <= last1) {
-
- /* If the line isn't a difference, output the context from file 0. */
-
- if (next == null || i < next.line0) {
- outfile.print(' ');
- print_1_line ("", file0[i++]);
- j++;
- }
- else {
- /* For each difference, first output the deleted part. */
-
- int k = next.deleted;
- while (k-- > 0) {
- outfile.print('-');
- print_1_line ("", file0[i++]);
- }
-
- /* Then output the inserted part. */
-
- k = next.inserted;
- while (k-- > 0) {
- outfile.print('+');
- print_1_line ("", file1[j++]);
- }
-
- /* We're done with this hunk, so on to the next! */
-
- next = next.link;
- }
- }
- }
- }
-
-
- /** Read a text file into an array of String. This provides basic diff
- functionality. A more advanced diff utility will use specialized
- objects to represent the text lines, with options to, for example,
- convert sequences of whitespace to a single space for comparison
- purposes.
- */
- static String[] slurp(String file) throws IOException {
- BufferedReader rdr = new BufferedReader(new FileReader(file));
- Vector s = new Vector();
- for (;;) {
- String line = rdr.readLine();
- if (line == null) break;
- s.addElement(line);
- }
- String[] a = new String[s.size()];
- s.copyInto(a);
- return a;
- }
-
- public static void main(String[] argv) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- System.err.println("No differences");
- else {
- Base p;
- Writer w = new OutputStreamWriter(System.out);
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
- public static void doDiff(String[] argv, Writer w) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- w.write("No differences\n");
- else {
- Base p;
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
-}
diff --git a/src/partest-alternative/scala/tools/partest/io/JUnitReport.scala b/src/partest-alternative/scala/tools/partest/io/JUnitReport.scala
deleted file mode 100644
index ddb3bc23fd..0000000000
--- a/src/partest-alternative/scala/tools/partest/io/JUnitReport.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package io
-
-/** This is disabled for the moment but I can fix it up if anyone
- * is using it.
- */
-class JUnitReport {
- // create JUnit Report xml files if directory was specified
- // def junitReport(dir: Directory) = {
- // dir.mkdir()
- // val report = testReport(set.kind, results, succs, fails)
- // XML.save("%s/%s.xml".format(d.toAbsolute.path, set.kind), report)
- // }
-
- // def oneResult(res: (TestEntity, Int)) =
- // <testcase name={res._1.path}>{
- // res._2 match {
- // case 0 => scala.xml.NodeSeq.Empty
- // case 1 => <failure message="Test failed"/>
- // case 2 => <failure message="Test timed out"/>
- // }
- // }</testcase>
- //
- // def testReport(kind: String, results: Iterable[(TestEntity, Int)], succs: Int, fails: Int) = {
- // <testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
- // <properties/>
- // {
- // results.map(oneResult(_))
- // }
- // </testsuite>
- // }
- //
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/io/Logging.scala b/src/partest-alternative/scala/tools/partest/io/Logging.scala
deleted file mode 100644
index 52239ffb2c..0000000000
--- a/src/partest-alternative/scala/tools/partest/io/Logging.scala
+++ /dev/null
@@ -1,137 +0,0 @@
-package scala.tools
-package partest
-package io
-
-import java.io.{ StringWriter, PrintWriter, Writer }
-import scala.tools.nsc.io._
-import scala.util.control.ControlThrowable
-
-trait Logging {
- universe: Universe =>
-
- class PartestANSIWriter extends ANSIWriter(Console.out) {
- override def colorful: Int = ANSIWriter(universe.isAnsi)
- private def printIf(cond: Boolean, msg: String) =
- if (cond) { outline("debug: ") ; println(msg) }
-
- val verbose = printIf(isVerbose || isDebug, _: String)
- val debug = printIf(isDebug, _: String)
- }
-
- lazy val NestUI = new PartestANSIWriter()
-
- import NestUI.{ _outline, _success, _failure, _warning, _default }
-
- def markOutline(msg: String) = _outline + msg + _default
- def markSuccess(msg: String) = _success + msg + _default
- def markFailure(msg: String) = _failure + msg + _default
- def markWarning(msg: String) = _warning + msg + _default
- def markNormal(msg: String) = _default + msg
-
- def outline(msg: String) = NestUI outline msg
- def success(msg: String) = NestUI success msg
- def failure(msg: String) = NestUI failure msg
- def warning(msg: String) = NestUI warning msg
- def normal(msg: String) = NestUI normal msg
-
- def verbose(msg: String) = NestUI verbose msg
- def debug(msg: String) = NestUI debug msg
-
- trait EntityLogging {
- self: TestEntity =>
-
- lazy val logWriter = new LogWriter(logFile)
-
- /** Redirect stdout and stderr to logFile, run body, return result.
- */
- def loggingOutAndErr[T](body: => T): T = {
- val log = logFile.printStream(append = true)
-
- try Console.withOut(log) {
- Console.withErr(log) {
- body
- }
- }
- finally log.close()
- }
-
- /** What to print in a failure summary.
- */
- def failureMessage() = if (diffOutput != "") diffOutput else safeSlurp(logFile)
-
- /** For tracing. Outputs a line describing the next action. tracePath
- * is a path wrapper which prints name or full path depending on verbosity.
- */
- def trace(msg: String) = if (isTrace || isDryRun) System.err.println(">> [%s] %s".format(label, msg))
-
- def tracePath(path: Path): String = if (isVerbose) path.path else path.name
- def tracePath(path: String): String = tracePath(Path(path))
-
- /** v == verbose.
- */
- def vtrace(msg: String) = if (isVerbose) trace(msg)
-
- /** Run body, writes result to logFile. Any throwable is
- * caught, stringified, and written to the log.
- */
- def loggingResult(body: => String) =
- try returning(true)(_ => logFile writeAll body)
- catch {
- case x: ControlThrowable => throw x
- case x: InterruptedException => debug(this + " received interrupt, failing.\n") ; false
- case x: Throwable => logException(x)
- }
-
- def throwableToString(x: Throwable): String = {
- val w = new StringWriter
- x.printStackTrace(new PrintWriter(w))
- w.toString
- }
-
- def warnAndLog(str: String) = {
- warning(toStringTrunc(str, 800))
- logWriter append str
- }
-
- def warnAndLogException(msg: String, ex: Throwable) =
- warnAndLog(msg + throwableToString(ex))
-
- def deleteLog(force: Boolean = false) =
- if (universe.isNoCleanup && !force) debug("Not cleaning up " + logFile)
- else logFile.deleteIfExists()
-
- def onException(x: Throwable) { logException(x) }
- def logException(x: Throwable) = {
- val msg = throwableToString(x)
- if (!isTerse)
- normal(msg)
-
- logWriter append msg
- false
- }
- }
-
- /** A writer which doesn't create the file until a write comes in.
- */
- class LazilyCreatedWriter(log: File) extends Writer {
- @volatile private var isCreated = false
- private lazy val underlying = {
- isCreated = true
- log.bufferedWriter()
- }
-
- def flush() = if (isCreated) underlying.flush()
- def close() = if (isCreated) underlying.close()
- def write(chars: Array[Char], off: Int, len: Int) = {
- underlying.write(chars, off, len)
- underlying.flush()
- }
- }
-
- class LogWriter(log: File) extends PrintWriter(new LazilyCreatedWriter(log), true) {
- override def print(s: String) = {
- super.print(s)
- flush()
- }
- }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/package.scala b/src/partest-alternative/scala/tools/partest/package.scala
deleted file mode 100644
index 9c515aa2f4..0000000000
--- a/src/partest-alternative/scala/tools/partest/package.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-
-import nsc.io.{ File, Path, Process, Directory }
-import java.nio.charset.CharacterCodingException
-
-package object partest {
- /** The CharacterCodingExceptions are thrown at least on windows trying
- * to read a file like script/utf-8.scala
- */
- private[partest] def safeSlurp(f: File) =
- try if (f.exists) f.slurp() else ""
- catch { case _: CharacterCodingException => "" }
-
- private[partest] def safeLines(f: File) = safeSlurp(f) split """\r\n|\r|\n""" toList
- private[partest] def safeArgs(f: File) = toArgs(safeSlurp(f))
- private[partest] def isJava(f: Path) = f.isFile && (f hasExtension "java")
- private[partest] def isScala(f: Path) = f.isFile && (f hasExtension "scala")
- private[partest] def isJavaOrScala(f: Path) = isJava(f) || isScala(f)
-
- private[partest] def toArgs(line: String) = cmd toArgs line
- private[partest] def fromArgs(args: List[String]) = cmd fromArgs args
-
- /** Strings, argument lists, etc. */
-
- private[partest] def fromAnyArgs(args: List[Any]) = args mkString " " // separate to avoid accidents
- private[partest] def toStringTrunc(x: Any, max: Int = 240) = {
- val s = x.toString
- if (s.length < max) s
- else (s take max) + " [...]"
- }
- private[partest] def setProp(k: String, v: String) = scala.util.Properties.setProp(k, v)
-
- /** Pretty self explanatory. */
- def printAndExit(msg: String): Unit = {
- println(msg)
- exit(1)
- }
-
- /** Apply a function and return the passed value */
- def returning[T](x: T)(f: T => Unit): T = { f(x) ; x }
-} \ No newline at end of file
diff --git a/src/partest-alternative/scala/tools/partest/util/package.scala b/src/partest-alternative/scala/tools/partest/util/package.scala
deleted file mode 100644
index c34d641db1..0000000000
--- a/src/partest-alternative/scala/tools/partest/util/package.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2011 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import java.util.{ Timer, TimerTask }
-import java.io.StringWriter
-import nsc.io._
-
-/** Misc code still looking for a good home.
- */
-package object util {
-
- def allPropertiesString() = javaHashtableToString(System.getProperties)
-
- private def javaHashtableToString(table: java.util.Hashtable[_,_]) = {
- import collection.JavaConversions._
- (table.toList map { case (k, v) => "%s -> %s\n".format(k, v) }).sorted mkString
- }
-
- def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
- fs flatMap (x => Option(AbstractFile getFile (Path(pre) / x).path)) toSet
-
- /** Copies one Path to another Path, trying to be sensible when one or the
- * other is a Directory. Returns true if it believes it succeeded.
- */
- def copyPath(from: Path, to: Path): Boolean = {
- if (!to.parent.isDirectory)
- to.parent.createDirectory(force = true)
-
- def copyDir = {
- val sub = to / from.name createDirectory true
- from.toDirectory.list forall (x => copyPath(x, sub))
- }
- (from.isDirectory, to.isDirectory) match {
- case (true, true) => copyDir
- case (true, false) => false
- case (false, true) => from.toFile copyTo (to / from.name)
- case (false, false) => from.toFile copyTo to
- }
- }
-
- /**
- * Compares two files using a Java implementation of the GNU diff
- * available at http://www.bmsi.com/java/#diff.
- *
- * @param f1 the first file to be compared
- * @param f2 the second file to be compared
- * @return the text difference between the compared files
- */
- def diffFiles(f1: File, f2: File): String = {
- val diffWriter = new StringWriter
- val args = Array(f1.toAbsolute.path, f2.toAbsolute.path)
-
- io.DiffPrint.doDiff(args, diffWriter)
- val result = diffWriter.toString
- if (result == "No differences") "" else result
- }
-}
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
index a08100a33f..a90a61a9aa 100644
--- a/src/partest/scala/tools/partest/PartestTask.scala
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -281,6 +281,26 @@ class PartestTask extends Task with CompilationPathProperty {
}
} getOrElse sys.error("Provided classpath does not contain a Scala library.")
+ val scalaCompiler = {
+ (classpath.list map { fs => new File(fs) }) find { f =>
+ f.getName match {
+ case "scala-compiler.jar" => true
+ case "compiler" if (f.getParentFile.getName == "classes") => true
+ case _ => false
+ }
+ }
+ } getOrElse sys.error("Provided classpath does not contain a Scala compiler.")
+
+ val scalaPartest = {
+ (classpath.list map { fs => new File(fs) }) find { f =>
+ f.getName match {
+ case "scala-partest.jar" => true
+ case "partest" if (f.getParentFile.getName == "classes") => true
+ case _ => false
+ }
+ }
+ } getOrElse sys.error("Provided classpath does not contain a Scala partest.")
+
def scalacArgsFlat: Option[Seq[String]] = scalacArgs map (_ flatMap { a =>
val parts = a.getParts
if(parts eq null) Seq[String]() else parts.toSeq
@@ -294,6 +314,8 @@ class PartestTask extends Task with CompilationPathProperty {
antFileManager.failed = runFailed
antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*)
antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath
+ antFileManager.LATEST_COMP = scalaCompiler.getAbsolutePath
+ antFileManager.LATEST_PARTEST = scalaPartest.getAbsolutePath
javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath)
javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath)
@@ -361,18 +383,18 @@ class PartestTask extends Task with CompilationPathProperty {
private def oneResult(res: (String, Int)) =
<testcase name={res._1}>{
- res._2 match {
- case 0 => scala.xml.NodeSeq.Empty
+ res._2 match {
+ case 0 => scala.xml.NodeSeq.Empty
case 1 => <failure message="Test failed"/>
case 2 => <failure message="Test timed out"/>
- }
- }</testcase>
+ }
+ }</testcase>
private def testReport(kind: String, results: Iterable[(String, Int)], succs: Int, fails: Int) =
<testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
- <properties/>
- {
- results.map(oneResult(_))
- }
+ <properties/>
+ {
+ results.map(oneResult(_))
+ }
</testsuite>
}
diff --git a/src/partest/scala/tools/partest/nest/AntRunner.scala b/src/partest/scala/tools/partest/nest/AntRunner.scala
index 002e454b7b..4795e5551a 100644
--- a/src/partest/scala/tools/partest/nest/AntRunner.scala
+++ b/src/partest/scala/tools/partest/nest/AntRunner.scala
@@ -20,6 +20,8 @@ class AntRunner extends DirectRunner {
var JAVAC_CMD: String = "javac"
var CLASSPATH: String = _
var LATEST_LIB: String = _
+ var LATEST_COMP: String = _
+ var LATEST_PARTEST: String = _
val testRootPath: String = "test"
val testRootDir: Directory = Directory(testRootPath)
}
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 68688ff949..6604bc551d 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -26,7 +26,7 @@ class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
deprecation.value = true
nowarnings.value = false
- encoding.value = "ISO-8859-1"
+ encoding.value = "UTF-8"
classpath.value = cp
}
@@ -111,6 +111,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
try {
NestUI.verbose("compiling "+toCompile)
+ NestUI.verbose("with classpath: "+global.classPath.toString)
try new global.Run compile toCompile
catch {
case FatalError(msg) =>
diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
index b9b371d6cb..3d72227b04 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -157,9 +157,13 @@ class ConsoleFileManager extends FileManager {
}
LATEST_LIB = latestLibFile.getAbsolutePath
+ LATEST_COMP = latestCompFile.getAbsolutePath
+ LATEST_PARTEST = latestPartestFile.getAbsolutePath
}
var LATEST_LIB: String = ""
+ var LATEST_COMP: String = ""
+ var LATEST_PARTEST: String = ""
var latestFile: File = _
var latestLibFile: File = _
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
index 78184664c2..d3d50ca58c 100644
--- a/src/partest/scala/tools/partest/nest/DirectRunner.scala
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -52,8 +52,15 @@ trait DirectRunner {
val kindFiles = onlyValidTestPaths(_kindFiles)
val groupSize = (kindFiles.length / numActors) + 1
- val consFM = new ConsoleFileManager
- import consFM.{ latestCompFile, latestLibFile, latestPartestFile }
+ // @partest maintainer: we cannot create a fresh file manager here
+ // since the FM must respect --buildpath and --classpath from the command line
+ // for example, see how it's done in ReflectiveRunner
+ //val consFM = new ConsoleFileManager
+ //import consFM.{ latestCompFile, latestLibFile, latestPartestFile }
+ val latestCompFile = new File(fileManager.LATEST_COMP);
+ val latestLibFile = new File(fileManager.LATEST_LIB);
+ val latestPartestFile = new File(fileManager.LATEST_PARTEST);
+
val scalacheckURL = PathSettings.scalaCheck.toURL
val scalaCheckParentClassLoader = ScalaClassLoader.fromURLs(
List(scalacheckURL, latestCompFile.toURI.toURL, latestLibFile.toURI.toURL, latestPartestFile.toURI.toURL)
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
index 780f7a35e5..a4a94fe93e 100644
--- a/src/partest/scala/tools/partest/nest/FileManager.scala
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -60,6 +60,8 @@ trait FileManager extends FileUtil {
var CLASSPATH: String
var LATEST_LIB: String
+ var LATEST_COMP: String
+ var LATEST_PARTEST: String
var showDiff = false
var updateCheck = false
diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala
index 0c176e4b06..4c6f417df5 100644
--- a/src/partest/scala/tools/partest/nest/SBTRunner.scala
+++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala
@@ -7,16 +7,18 @@ import scala.util.Properties.setProp
object SBTRunner extends DirectRunner {
-
+
val fileManager = new FileManager {
var JAVACMD: String = "java"
var JAVAC_CMD: String = "javac"
var CLASSPATH: String = _
var LATEST_LIB: String = _
+ var LATEST_COMP: String = _
+ var LATEST_PARTEST: String = _
val testRootPath: String = "test"
val testRootDir: Directory = Directory(testRootPath)
}
-
+
def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String):java.util.HashMap[String,Int] = {
def convert(scalaM:scala.collection.immutable.Map[String,Int]):java.util.HashMap[String,Int] = {
val javaM = new java.util.HashMap[String,Int]()
@@ -25,9 +27,9 @@ object SBTRunner extends DirectRunner {
}
def failedOnlyIfRequired(files:List[File]):List[File]={
- if (fileManager.failed) files filter (x => fileManager.logFileExists(x, kind)) else files
+ if (fileManager.failed) files filter (x => fileManager.logFileExists(x, kind)) else files
}
- convert(runTestsForFiles(failedOnlyIfRequired(kindFiles.toList), kind))
+ convert(runTestsForFiles(failedOnlyIfRequired(kindFiles.toList), kind))
}
case class CommandLineOptions(classpath: Option[String] = None,
@@ -38,7 +40,7 @@ object SBTRunner extends DirectRunner {
def mainReflect(args: Array[String]): java.util.Map[String,Int] = {
setProp("partest.debug", "true")
setProperties()
-
+
val Argument = new scala.util.matching.Regex("-(.*)")
def parseArgs(args: Seq[String], data: CommandLineOptions): CommandLineOptions = args match {
case Seq("--failed", rest @ _*) => parseArgs(rest, data.copy(justFailedTests = true))
@@ -50,10 +52,14 @@ object SBTRunner extends DirectRunner {
}
val config = parseArgs(args, CommandLineOptions())
fileManager.SCALAC_OPTS = config.scalacOptions
- fileManager.CLASSPATH = config.classpath getOrElse error("No classpath set")
+ fileManager.CLASSPATH = config.classpath getOrElse sys.error("No classpath set")
// 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 error("No scala-library found! Classpath = " + fileManager.CLASSPATH)
+ 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)
// TODO - Do something useful here!!!
fileManager.JAVAC_CMD = "javac"
fileManager.failed = config.justFailedTests
@@ -63,7 +69,7 @@ object SBTRunner extends DirectRunner {
val runs = config.tests.filterNot(_._2.isEmpty)
// This next bit uses java maps...
import collection.JavaConverters._
- (for {
+ (for {
(testType, files) <- runs
(path, result) <- reflectiveRunTestsForFiles(files,testType).asScala
} yield (path, result)).seq asJava
@@ -80,4 +86,3 @@ object SBTRunner extends DirectRunner {
if(!failures.isEmpty) sys.exit(1)
}
}
-
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
index 9c61097cb0..3e5fe35f9e 100644
--- a/src/partest/scala/tools/partest/nest/TestFile.scala
+++ b/src/partest/scala/tools/partest/nest/TestFile.scala
@@ -12,6 +12,7 @@ import java.io.{ File => JFile }
import scala.tools.nsc.Settings
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.io._
+import scala.util.Properties.{ propIsSet, propOrElse, setProp }
trait TestFileCommon {
def file: JFile
@@ -61,6 +62,10 @@ case class SpecializedTestFile(file: JFile, fileManager: FileManager) extends Te
super.defineSettings(settings, setOutDir) && {
// add the instrumented library version to classpath
settings.classpath prepend PathSettings.srcSpecLib.toString
+ // @partest maintainer: if we use a custom Scala build (specified via --classpath)
+ // then the classes provided by it will come earlier than instrumented.jar in the resulting classpath
+ // this entire classpath business needs a thorough solution
+ if (propIsSet("java.class.path")) setProp("java.class.path", PathSettings.srcSpecLib.toString + ";" + propOrElse("java.class.path", ""))
true
}
}
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
index f74182e81c..952d99c318 100644
--- a/src/partest/scala/tools/partest/nest/Worker.scala
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -53,6 +53,8 @@ class ScalaCheckFileManager(val origmanager: FileManager) extends FileManager {
var CLASSPATH: String = join(origmanager.CLASSPATH, PathSettings.scalaCheck.path)
var LATEST_LIB: String = origmanager.LATEST_LIB
+ var LATEST_COMP: String = origmanager.LATEST_COMP
+ var LATEST_PARTEST: String = origmanager.LATEST_PARTEST
}
object Output {
diff --git a/test/files/buildmanager/t2790/t2790.check b/test/files/buildmanager/t2790/t2790.check
index 4e41db4e49..13d61dac42 100644
--- a/test/files/buildmanager/t2790/t2790.check
+++ b/test/files/buildmanager/t2790/t2790.check
@@ -9,6 +9,5 @@ compiling Set(B.scala)
B.scala:2: error: type mismatch;
found : Int(5)
required: String
-Error occurred in an application involving default arguments.
val y = A.x(5)
^
diff --git a/test/files/neg/nopredefs.check b/test/files/neg/nopredefs.check
index e6c1af78a0..0a0ab34482 100644
--- a/test/files/neg/nopredefs.check
+++ b/test/files/neg/nopredefs.check
@@ -1,4 +1,4 @@
-nopredefs.scala:5: error: not found: value Set (similar: Seq)
+nopredefs.scala:5: error: not found: value Set
val y = Set(3)
^
one error found
diff --git a/test/files/neg/sensitive2.check b/test/files/neg/sensitive2.check
new file mode 100644
index 0000000000..19152fe188
--- /dev/null
+++ b/test/files/neg/sensitive2.check
@@ -0,0 +1,10 @@
+sensitive2.scala:6: error: type mismatch;
+ found : String("abc")
+ required: Test.Foo[_]
+Note that implicit conversions are not applicable because they are ambiguous:
+ both method foo1 in object Test of type [A](a: A)Test.Foo[A]
+ and method foo2 in object Test of type (a: Any)Test.Foo[String]
+ are possible conversion functions from String("abc") to Test.Foo[_]
+ val a: Foo[_] = "abc"
+ ^
+one error found
diff --git a/test/files/neg/sensitive2.scala b/test/files/neg/sensitive2.scala
new file mode 100644
index 0000000000..92b91bef20
--- /dev/null
+++ b/test/files/neg/sensitive2.scala
@@ -0,0 +1,8 @@
+object Test {
+ class Foo[A](z: A)
+ implicit def foo1[A](a: A): Foo[A] = new Foo(a)
+ implicit def foo2(a: Any): Foo[String] = new Foo("123")
+
+ val a: Foo[_] = "abc"
+
+} \ No newline at end of file
diff --git a/test/files/neg/suggest-similar.check b/test/files/neg/suggest-similar.check
index 0a858aaf2e..057aa8b250 100644
--- a/test/files/neg/suggest-similar.check
+++ b/test/files/neg/suggest-similar.check
@@ -1,10 +1,10 @@
-suggest-similar.scala:8: error: not found: value flippitx (similar: flippity)
+suggest-similar.scala:8: error: not found: value flippitx
flippitx = 123
^
-suggest-similar.scala:9: error: not found: value identiyt (similar: identity)
+suggest-similar.scala:9: error: not found: value identiyt
Nil map identiyt
^
-suggest-similar.scala:10: error: not found: type Bingus (similar: Dingus)
+suggest-similar.scala:10: error: not found: type Bingus
new Bingus
^
three errors found
diff --git a/test/files/neg/t1878.check b/test/files/neg/t1878.check
index f3a6701d41..128741a022 100644
--- a/test/files/neg/t1878.check
+++ b/test/files/neg/t1878.check
@@ -6,10 +6,13 @@ t1878.scala:3: error: scrutinee is incompatible with pattern type;
required: String
val err1 = "" match { case Seq(f @ _*, ',') => f }
^
+t1878.scala:3: error: not found: value f
+ val err1 = "" match { case Seq(f @ _*, ',') => f }
+ ^
t1878.scala:9: error: _* may only come last
val List(List(_*, arg2), _) = List(List(1,2,3), List(4,5,6))
^
t1878.scala:13: error: _* may only come last
case <p> { _* } </p> =>
^
-four errors found
+5 errors found
diff --git a/test/files/neg/t2641.check b/test/files/neg/t2641.check
index 2056a1b9ab..9e2f02ac47 100644
--- a/test/files/neg/t2641.check
+++ b/test/files/neg/t2641.check
@@ -1,4 +1,4 @@
-t2641.scala:18: error: illegal cyclic reference involving trait ManagedSeq
+t2641.scala:18: error: wrong number of type arguments for ManagedSeq, should be 2
with TraversableViewLike[A, ManagedSeqStrict[A], ManagedSeq[A]]
^
t2641.scala:16: error: illegal inheritance;
@@ -13,23 +13,7 @@ t2641.scala:16: error: illegal inheritance;
self-type ManagedSeq does not conform to ScalaObject's selftype ScalaObject
extends ManagedSeqStrict[A]
^
-t2641.scala:24: error: something is wrong (wrong class file?): trait ManagedSeq with type parameters [A,Coll] gets applied to arguments [], phase = typer
- trait Transformed[+B] extends ManagedSeq[B, Coll] with super.Transformed[B]
- ^
-t2641.scala:26: error: something is wrong (wrong class file?): trait ManagedSeq with type parameters [A,Coll] gets applied to arguments [], phase = namer
- trait Sliced extends Transformed[A] with super.Sliced {
- ^
-t2641.scala:26: error: illegal inheritance; superclass Any
- is not a subclass of the superclass ManagedSeqStrict
- of the mixin trait Transformed
- trait Sliced extends Transformed[A] with super.Sliced {
- ^
-t2641.scala:26: error: illegal inheritance; superclass Any
- is not a subclass of the superclass Object
- of the mixin trait Sliced
- trait Sliced extends Transformed[A] with super.Sliced {
- ^
t2641.scala:27: error: value managedIterator is not a member of ManagedSeq
override def managedIterator = self.managedIterator slice (from, until)
^
-9 errors found
+5 errors found
diff --git a/test/files/neg/t2870.check b/test/files/neg/t2870.check
index ab962d48c8..99522eca65 100644
--- a/test/files/neg/t2870.check
+++ b/test/files/neg/t2870.check
@@ -1,4 +1,4 @@
-t2870.scala:1: error: not found: type Jar (similar: Jars)
+t2870.scala:1: error: not found: type Jar
class Jars(jar: Jar)
^
t2870.scala:4: error: encountered unrecoverable cycle resolving import.
diff --git a/test/files/neg/t2918.check b/test/files/neg/t2918.check
index 263beab518..aae3045e8a 100644
--- a/test/files/neg/t2918.check
+++ b/test/files/neg/t2918.check
@@ -1,10 +1,10 @@
t2918.scala:2: error: illegal cyclic reference involving type A
- def g[X, A[X] <: A[X]](x: A[X]) = x
+ def g[X, A[X] <: A[X]](x: A[X]) = x
^
t2918.scala:2: error: cyclic aliasing or subtyping involving type A
- def g[X, A[X] <: A[X]](x: A[X]) = x
+ def g[X, A[X] <: A[X]](x: A[X]) = x
^
t2918.scala:2: error: A does not take type parameters
- def g[X, A[X] <: A[X]](x: A[X]) = x
+ def g[X, A[X] <: A[X]](x: A[X]) = x
^
three errors found
diff --git a/test/files/neg/t2918.scala b/test/files/neg/t2918.scala
index 03477ccfbf..ff2be39ae0 100755
--- a/test/files/neg/t2918.scala
+++ b/test/files/neg/t2918.scala
@@ -1,3 +1,3 @@
object Test {
- def g[X, A[X] <: A[X]](x: A[X]) = x
+ def g[X, A[X] <: A[X]](x: A[X]) = x
}
diff --git a/test/files/neg/t3015.check b/test/files/neg/t3015.check
index 0b394e23d6..53221b7ca0 100644
--- a/test/files/neg/t3015.check
+++ b/test/files/neg/t3015.check
@@ -3,9 +3,4 @@ t3015.scala:7: error: scrutinee is incompatible with pattern type;
required: String
val b(foo) = "foo"
^
-t3015.scala:7: error: type mismatch;
- found : String with _$1(in object Test) where type +_$1(in object Test)
- required: (some other)_$1(in object Test) where type +(some other)_$1(in object Test)
- val b(foo) = "foo"
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t3854.check b/test/files/neg/t3854.check
new file mode 100644
index 0000000000..c478481a6f
--- /dev/null
+++ b/test/files/neg/t3854.check
@@ -0,0 +1,5 @@
+t3854.scala:1: error: class Bar needs to be abstract, since method foo in trait Foo of type [G[_]](implicit n: N[G,F])X[F] is not defined
+(Note that N[G,F] does not match M[G])
+class Bar[F[_]] extends Foo[F] {
+ ^
+one error found
diff --git a/test/files/neg/t3854.scala b/test/files/neg/t3854.scala
new file mode 100644
index 0000000000..e8db76c0a5
--- /dev/null
+++ b/test/files/neg/t3854.scala
@@ -0,0 +1,15 @@
+class Bar[F[_]] extends Foo[F] {
+ def foo[G[_[_], _]](implicit M: M[G]): X[({type λ[α] = G[F, α] })#λ] = null
+}
+// vim: set ts=4 sw=4 et:
+
+trait M[F[_[_], _]]
+trait N[F[_], G[_]]
+
+trait X[F[_]] {
+ def apply[A]: F[A]
+}
+
+trait Foo[F[_]] {
+ def foo[G[_]](implicit n: N[G, F]): X[F]
+}
diff --git a/test/files/neg/t4515.check b/test/files/neg/t4515.check
new file mode 100644
index 0000000000..ce5350b35f
--- /dev/null
+++ b/test/files/neg/t4515.check
@@ -0,0 +1,6 @@
+t4515.scala:37: error: type mismatch;
+ found : _0(in value $anonfun) where type _0(in value $anonfun)
+ required: (some other)_0(in value $anonfun) where type +(some other)_0(in value $anonfun)
+ handler.onEvent(target, ctx.getEvent, node, ctx)
+ ^
+one error found
diff --git a/test/files/neg/t4515.scala b/test/files/neg/t4515.scala
new file mode 100644
index 0000000000..63049f201d
--- /dev/null
+++ b/test/files/neg/t4515.scala
@@ -0,0 +1,41 @@
+import scala.collection.mutable.HashMap
+
+object Main {
+ trait Target { }
+
+ trait PushEventContext[EventType] {
+ def getEvent: EventType
+ }
+ trait PushNode[EventType] { }
+ trait DerivedPushNode[EventType] extends PushNode[EventType] { }
+
+ trait HandlerBase[EventType] {
+ def onEvent(target: Target,
+ event: EventType,
+ node: PushNode[EventType],
+ ctx: PushEventContext[EventType]): Unit
+ }
+ val handlers = new HashMap[DerivedPushNode[_], HandlerBase[_]]
+
+ object TimerPushService {
+ private val INSTANCE: TimerPushService = new TimerPushService
+ def get: TimerPushService = INSTANCE
+ }
+
+ class TimerPushService {
+ def add[EventType](node: DerivedPushNode[EventType],
+ context: PushEventContext[EventType]): Unit = {}
+
+ def pollEvents[EventType](node: DerivedPushNode[EventType]): List[PushEventContext[EventType]] =
+ Nil
+ }
+
+ def onTimer(target: Target) {
+ val pushService = TimerPushService.get
+ for ((node, handler) <- handlers) {
+ for (ctx <- pushService.pollEvents(node)) {
+ handler.onEvent(target, ctx.getEvent, node, ctx)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/t649.check b/test/files/neg/t649.check
index 5a270d4751..a6670886b5 100644
--- a/test/files/neg/t649.check
+++ b/test/files/neg/t649.check
@@ -1,4 +1,4 @@
t649.scala:3: error: overloaded method foo needs result type
def foo[A] = foo[A]
- ^
+ ^
one error found
diff --git a/test/files/pos/t3999b.scala b/test/files/pos/t3999b.scala
new file mode 100644
index 0000000000..d3fe108479
--- /dev/null
+++ b/test/files/pos/t3999b.scala
@@ -0,0 +1,20 @@
+object `package` {
+ trait Score { def toString : String }
+ trait Test[+T <: Score] { def apply(s : String) : T }
+
+ case class FT(f : Float) extends Score
+ implicit object FT extends Test[FT] { def apply(s : String) : FT = new FT(s.toFloat) }
+
+ case class IT(i : Int) extends Score
+ implicit object IT extends Test[IT] { def apply(s : String) : IT = new IT(s.toInt) }
+}
+
+class TT[+T <: Score](implicit val tb : Test[T]) {
+ def read(s : String) : T = tb(s)
+}
+
+object Tester {
+ val tt = new TT[FT]
+ val r = tt.read("1.0")
+ r.toString
+} \ No newline at end of file
diff --git a/test/files/pos/trait-force-info.flags b/test/files/pos/trait-force-info.flags
new file mode 100644
index 0000000000..eb4d19bcb9
--- /dev/null
+++ b/test/files/pos/trait-force-info.flags
@@ -0,0 +1 @@
+-optimise \ No newline at end of file
diff --git a/test/files/pos/trait-force-info.scala b/test/files/pos/trait-force-info.scala
new file mode 100644
index 0000000000..e01d225c84
--- /dev/null
+++ b/test/files/pos/trait-force-info.scala
@@ -0,0 +1,18 @@
+/** This does NOT crash unless it's in the interactive package.
+ */
+
+package scala.tools.nsc
+package interactive
+
+trait MyContextTrees {
+ val self: Global
+ val NoContext = self.analyzer.NoContext
+}
+//
+// error: java.lang.AssertionError: assertion failed: trait Contexts.NoContext$ linkedModule: <none>List()
+// at scala.Predef$.assert(Predef.scala:160)
+// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.innerSymbol$1(ClassfileParser.scala:1211)
+// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.classSymbol(ClassfileParser.scala:1223)
+// at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:489)
+// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:757)
+// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:789)
diff --git a/test/files/run/macro-range/macro_range_1.scala b/test/files/run/macro-range/macro_range_1.scala
index 15a018fcff..fdfe7169ad 100644
--- a/test/files/run/macro-range/macro_range_1.scala
+++ b/test/files/run/macro-range/macro_range_1.scala
@@ -29,12 +29,13 @@ abstract class Utils {
}
}
def makeApply(fn: Tree, args: List[Tree]): Tree = fn match {
- case Function(vparams, body) =>
+ case Function(vparams, body) =>
new TreeSubstituter(vparams map (_.symbol), args) transform body
case Block(stats, expr) =>
Block(stats, makeApply(expr, args))
- case _ =>
- println("no beta on "+fn+" "+fn.getClass)
+ case _ =>
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("no beta on "+fn+" "+fn.getClass)
Apply(fn, args)
}
def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
@@ -48,7 +49,8 @@ abstract class Utils {
class Range(val from: Int, val to: Int) extends RangeDefault {
override def macro foreach(f: Int => Unit): Unit = {
- println("macro-expand, _this = "+ _this)
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("macro-expand, _this = "+ _this)
import _context._
object utils extends Utils {
val context: _context.type = _context
@@ -71,12 +73,15 @@ class Range(val from: Int, val to: Int) extends RangeDefault {
val body = Block(
List(makeApply(f, List(iref))),
Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
- tools.nsc.util.trace("generated: ")(
+ val generated =
Block(
List(
ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
ValDef(Modifiers(), hname, TypeTree(), hi)),
- makeWhile(labelname, cond, body)))
+ makeWhile(labelname, cond, body))
+ // todo. read the compiler config and print if -Ydebug is set
+ //tools.nsc.util.trace("generated: ")(generated)
+ generated
case _ =>
Apply(
Select(
diff --git a/test/files/run/macro-range/macro_range_2.scala b/test/files/run/macro-range/macro_range_2.scala
index 15a018fcff..fdfe7169ad 100644
--- a/test/files/run/macro-range/macro_range_2.scala
+++ b/test/files/run/macro-range/macro_range_2.scala
@@ -29,12 +29,13 @@ abstract class Utils {
}
}
def makeApply(fn: Tree, args: List[Tree]): Tree = fn match {
- case Function(vparams, body) =>
+ case Function(vparams, body) =>
new TreeSubstituter(vparams map (_.symbol), args) transform body
case Block(stats, expr) =>
Block(stats, makeApply(expr, args))
- case _ =>
- println("no beta on "+fn+" "+fn.getClass)
+ case _ =>
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("no beta on "+fn+" "+fn.getClass)
Apply(fn, args)
}
def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
@@ -48,7 +49,8 @@ abstract class Utils {
class Range(val from: Int, val to: Int) extends RangeDefault {
override def macro foreach(f: Int => Unit): Unit = {
- println("macro-expand, _this = "+ _this)
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("macro-expand, _this = "+ _this)
import _context._
object utils extends Utils {
val context: _context.type = _context
@@ -71,12 +73,15 @@ class Range(val from: Int, val to: Int) extends RangeDefault {
val body = Block(
List(makeApply(f, List(iref))),
Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
- tools.nsc.util.trace("generated: ")(
+ val generated =
Block(
List(
ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
ValDef(Modifiers(), hname, TypeTree(), hi)),
- makeWhile(labelname, cond, body)))
+ makeWhile(labelname, cond, body))
+ // todo. read the compiler config and print if -Ydebug is set
+ //tools.nsc.util.trace("generated: ")(generated)
+ generated
case _ =>
Apply(
Select(
diff --git a/test/files/run/range-unit.check b/test/files/run/range-unit.check
new file mode 100644
index 0000000000..3daf91cd64
--- /dev/null
+++ b/test/files/run/range-unit.check
@@ -0,0 +1,4178 @@
+>>> Range.inclusive <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 0 -1 1/0/0
+0 0 1 1/0/0
+0 0 -2 1/0/0
+0 0 2 1/0/0
+0 0 -3 1/0/0
+0 0 3 1/0/0
+0 0 17 1/0/0
+0 0 127 1/0/0
+0 0 MIN+1 1/0/0
+0 0 MAX 1/0/0
+0 0 MIN 1/0/0
+0 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 -1 -1 2/0/-1
+0 -1 1 0
+0 -1 -2 1/0/0
+0 -1 2 0
+0 -1 -3 1/0/0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 1/0/0
+0 -1 MAX 0
+0 -1 MIN 1/0/0
+0 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 1 -1 0
+0 1 1 2/0/1
+0 1 -2 0
+0 1 2 1/0/0
+0 1 -3 0
+0 1 3 1/0/0
+0 1 17 1/0/0
+0 1 127 1/0/0
+0 1 MIN+1 0
+0 1 MAX 1/0/0
+0 1 MIN 0
+0 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 3 -1 0
+0 3 1 4/0/3
+0 3 -2 0
+0 3 2 2/0/2
+0 3 -3 0
+0 3 3 2/0/3
+0 3 17 1/0/0
+0 3 127 1/0/0
+0 3 MIN+1 0
+0 3 MAX 1/0/0
+0 3 MIN 0
+0 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 0 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN+1 1 0
+0 MIN+1 -2 1073741824/0/MIN+2
+0 MIN+1 2 0
+0 MIN+1 -3 715827883/0/MIN+2
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 2/0/MIN+1
+0 MIN+1 MAX 0
+0 MIN+1 MIN 1/0/0
+0 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MAX -1 0
+0 MAX 1 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX -2 0
+0 MAX 2 1073741824/0/MAX-1
+0 MAX -3 0
+0 MAX 3 715827883/0/MAX-1
+0 MAX 17 126322568/0/MAX-8
+0 MAX 127 16909321/0/MAX-7
+0 MAX MIN+1 0
+0 MAX MAX 2/0/MAX
+0 MAX MIN 0
+0 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN -1 ---
+ java.lang.IllegalArgumentException: 0 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN 1 0
+0 MIN -2 1073741825/0/MIN
+0 MIN 2 0
+0 MIN -3 715827883/0/MIN+2
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 2/0/MIN+1
+0 MIN MAX 0
+0 MIN MIN 2/0/MIN
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 0 -1 0
+-1 0 1 2/-1/0
+-1 0 -2 0
+-1 0 2 1/-1/-1
+-1 0 -3 0
+-1 0 3 1/-1/-1
+-1 0 17 1/-1/-1
+-1 0 127 1/-1/-1
+-1 0 MIN+1 0
+-1 0 MAX 1/-1/-1
+-1 0 MIN 0
+-1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 -1 -1 1/-1/-1
+-1 -1 1 1/-1/-1
+-1 -1 -2 1/-1/-1
+-1 -1 2 1/-1/-1
+-1 -1 -3 1/-1/-1
+-1 -1 3 1/-1/-1
+-1 -1 17 1/-1/-1
+-1 -1 127 1/-1/-1
+-1 -1 MIN+1 1/-1/-1
+-1 -1 MAX 1/-1/-1
+-1 -1 MIN 1/-1/-1
+-1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 1 -1 0
+-1 1 1 3/-1/1
+-1 1 -2 0
+-1 1 2 2/-1/1
+-1 1 -3 0
+-1 1 3 1/-1/-1
+-1 1 17 1/-1/-1
+-1 1 127 1/-1/-1
+-1 1 MIN+1 0
+-1 1 MAX 1/-1/-1
+-1 1 MIN 0
+-1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 3 -1 0
+-1 3 1 5/-1/3
+-1 3 -2 0
+-1 3 2 3/-1/3
+-1 3 -3 0
+-1 3 3 2/-1/2
+-1 3 17 1/-1/-1
+-1 3 127 1/-1/-1
+-1 3 MIN+1 0
+-1 3 MAX 1/-1/-1
+-1 3 MIN 0
+-1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN+1 -1 MAX/-1/MIN+1
+-1 MIN+1 1 0
+-1 MIN+1 -2 1073741824/-1/MIN+1
+-1 MIN+1 2 0
+-1 MIN+1 -3 715827883/-1/MIN+1
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 1/-1/-1
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 1/-1/-1
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MAX -1 0
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 0
+-1 MAX 2 1073741825/-1/MAX
+-1 MAX -3 0
+-1 MAX 3 715827883/-1/MAX-2
+-1 MAX 17 126322568/-1/MAX-9
+-1 MAX 127 16909321/-1/MAX-8
+-1 MAX MIN+1 0
+-1 MAX MAX 2/-1/MAX-1
+-1 MAX MIN 0
+-1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN -1 ---
+ java.lang.IllegalArgumentException: -1 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+-1 MIN 1 0
+-1 MIN -2 1073741824/-1/MIN+1
+-1 MIN 2 0
+-1 MIN -3 715827883/-1/MIN+1
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 2/-1/MIN
+-1 MIN MAX 0
+-1 MIN MIN 1/-1/-1
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 0 -1 2/1/0
+1 0 1 0
+1 0 -2 1/1/1
+1 0 2 0
+1 0 -3 1/1/1
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 1/1/1
+1 0 MAX 0
+1 0 MIN 1/1/1
+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 -1 -1 3/1/-1
+1 -1 1 0
+1 -1 -2 2/1/-1
+1 -1 2 0
+1 -1 -3 1/1/1
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 1/1/1
+1 -1 MAX 0
+1 -1 MIN 1/1/1
+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 1 -1 1/1/1
+1 1 1 1/1/1
+1 1 -2 1/1/1
+1 1 2 1/1/1
+1 1 -3 1/1/1
+1 1 3 1/1/1
+1 1 17 1/1/1
+1 1 127 1/1/1
+1 1 MIN+1 1/1/1
+1 1 MAX 1/1/1
+1 1 MIN 1/1/1
+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 3 -1 0
+1 3 1 3/1/3
+1 3 -2 0
+1 3 2 2/1/3
+1 3 -3 0
+1 3 3 1/1/1
+1 3 17 1/1/1
+1 3 127 1/1/1
+1 3 MIN+1 0
+1 3 MAX 1/1/1
+1 3 MIN 0
+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 1 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN+1 1 0
+1 MIN+1 -2 1073741825/1/MIN+1
+1 MIN+1 2 0
+1 MIN+1 -3 715827883/1/MIN+3
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 2/1/MIN+2
+1 MIN+1 MAX 0
+1 MIN+1 MIN 2/1/MIN+1
+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MAX -1 0
+1 MAX 1 MAX/1/MAX
+1 MAX -2 0
+1 MAX 2 1073741824/1/MAX
+1 MAX -3 0
+1 MAX 3 715827883/1/MAX
+1 MAX 17 126322568/1/MAX-7
+1 MAX 127 16909321/1/MAX-6
+1 MAX MIN+1 0
+1 MAX MAX 1/1/1
+1 MAX MIN 0
+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN -1 ---
+ java.lang.IllegalArgumentException: 1 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN 1 0
+1 MIN -2 1073741825/1/MIN+1
+1 MIN 2 0
+1 MIN -3 715827884/1/MIN
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 2/1/MIN+2
+1 MIN MAX 0
+1 MIN MIN 2/1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 0 -1 4/3/0
+3 0 1 0
+3 0 -2 2/3/1
+3 0 2 0
+3 0 -3 2/3/0
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 1/3/3
+3 0 MAX 0
+3 0 MIN 1/3/3
+3 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 -1 -1 5/3/-1
+3 -1 1 0
+3 -1 -2 3/3/-1
+3 -1 2 0
+3 -1 -3 2/3/0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 1/3/3
+3 -1 MAX 0
+3 -1 MIN 1/3/3
+3 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 1 -1 3/3/1
+3 1 1 0
+3 1 -2 2/3/1
+3 1 2 0
+3 1 -3 1/3/3
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 1/3/3
+3 1 MAX 0
+3 1 MIN 1/3/3
+3 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 3 -1 1/3/3
+3 3 1 1/3/3
+3 3 -2 1/3/3
+3 3 2 1/3/3
+3 3 -3 1/3/3
+3 3 3 1/3/3
+3 3 17 1/3/3
+3 3 127 1/3/3
+3 3 MIN+1 1/3/3
+3 3 MAX 1/3/3
+3 3 MIN 1/3/3
+3 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 3 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN+1 1 0
+3 MIN+1 -2 1073741826/3/MIN+1
+3 MIN+1 2 0
+3 MIN+1 -3 715827884/3/MIN+2
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 2/3/MIN+4
+3 MIN+1 MAX 0
+3 MIN+1 MIN 2/3/MIN+3
+3 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MAX -1 0
+3 MAX 1 MAX-2/3/MAX
+3 MAX -2 0
+3 MAX 2 1073741823/3/MAX
+3 MAX -3 0
+3 MAX 3 715827882/3/MAX-1
+3 MAX 17 126322568/3/MAX-5
+3 MAX 127 16909321/3/MAX-4
+3 MAX MIN+1 0
+3 MAX MAX 1/3/3
+3 MAX MIN 0
+3 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN -1 ---
+ java.lang.IllegalArgumentException: 3 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN 1 0
+3 MIN -2 1073741826/3/MIN+1
+3 MIN 2 0
+3 MIN -3 715827884/3/MIN+2
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 2/3/MIN+4
+3 MIN MAX 0
+3 MIN MIN 2/3/MIN+3
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 0 -1 0
+MIN+1 0 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 -2 0
+MIN+1 0 2 1073741824/MIN+1/-1
+MIN+1 0 -3 0
+MIN+1 0 3 715827883/MIN+1/-1
+MIN+1 0 17 126322568/MIN+1/-8
+MIN+1 0 127 16909321/MIN+1/-7
+MIN+1 0 MIN+1 0
+MIN+1 0 MAX 2/MIN+1/0
+MIN+1 0 MIN 0
+MIN+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 -1 -1 0
+MIN+1 -1 1 MAX/MIN+1/-1
+MIN+1 -1 -2 0
+MIN+1 -1 2 1073741824/MIN+1/-1
+MIN+1 -1 -3 0
+MIN+1 -1 3 715827883/MIN+1/-1
+MIN+1 -1 17 126322568/MIN+1/-8
+MIN+1 -1 127 16909321/MIN+1/-7
+MIN+1 -1 MIN+1 0
+MIN+1 -1 MAX 1/MIN+1/MIN+1
+MIN+1 -1 MIN 0
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 1 -1 0
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 0
+MIN+1 1 2 1073741825/MIN+1/1
+MIN+1 1 -3 0
+MIN+1 1 3 715827883/MIN+1/-1
+MIN+1 1 17 126322568/MIN+1/-8
+MIN+1 1 127 16909321/MIN+1/-7
+MIN+1 1 MIN+1 0
+MIN+1 1 MAX 2/MIN+1/0
+MIN+1 1 MIN 0
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 3 -1 0
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 0
+MIN+1 3 2 1073741826/MIN+1/3
+MIN+1 3 -3 0
+MIN+1 3 3 715827884/MIN+1/2
+MIN+1 3 17 126322568/MIN+1/-8
+MIN+1 3 127 16909321/MIN+1/-7
+MIN+1 3 MIN+1 0
+MIN+1 3 MAX 2/MIN+1/0
+MIN+1 3 MIN 0
+MIN+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN+1 -1 1/MIN+1/MIN+1
+MIN+1 MIN+1 1 1/MIN+1/MIN+1
+MIN+1 MIN+1 -2 1/MIN+1/MIN+1
+MIN+1 MIN+1 2 1/MIN+1/MIN+1
+MIN+1 MIN+1 -3 1/MIN+1/MIN+1
+MIN+1 MIN+1 3 1/MIN+1/MIN+1
+MIN+1 MIN+1 17 1/MIN+1/MIN+1
+MIN+1 MIN+1 127 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN+1 MAX 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN 1/MIN+1/MIN+1
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MAX -1 0
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 0
+MIN+1 MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -3 0
+MIN+1 MAX 3 1431655765/MIN+1/MAX-2
+MIN+1 MAX 17 252645135/MIN+1/MAX-16
+MIN+1 MAX 127 33818641/MIN+1/MAX-14
+MIN+1 MAX MIN+1 0
+MIN+1 MAX MAX 3/MIN+1/MAX
+MIN+1 MAX MIN 0
+MIN+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN -1 2/MIN+1/MIN
+MIN+1 MIN 1 0
+MIN+1 MIN -2 1/MIN+1/MIN+1
+MIN+1 MIN 2 0
+MIN+1 MIN -3 1/MIN+1/MIN+1
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 1/MIN+1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 0 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to 0 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX 0 1 0
+MAX 0 -2 1073741824/MAX/1
+MAX 0 2 0
+MAX 0 -3 715827883/MAX/1
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 2/MAX/0
+MAX 0 MAX 0
+MAX 0 MIN 1/MAX/MAX
+MAX -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX -1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -1 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX -1 1 0
+MAX -1 -2 1073741825/MAX/-1
+MAX -1 2 0
+MAX -1 -3 715827883/MAX/1
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 2/MAX/0
+MAX -1 MAX 0
+MAX -1 MIN 2/MAX/-1
+MAX 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 1 -1 MAX/MAX/1
+MAX 1 1 0
+MAX 1 -2 1073741824/MAX/1
+MAX 1 2 0
+MAX 1 -3 715827883/MAX/1
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 1/MAX/MAX
+MAX 1 MAX 0
+MAX 1 MIN 1/MAX/MAX
+MAX 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 3 -1 MAX-2/MAX/3
+MAX 3 1 0
+MAX 3 -2 1073741823/MAX/3
+MAX 3 2 0
+MAX 3 -3 715827882/MAX/4
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 1/MAX/MAX
+MAX 3 MAX 0
+MAX 3 MIN 1/MAX/MAX
+MAX MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 1 0
+MAX MIN+1 -2 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483647 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 2 0
+MAX MIN+1 -3 1431655765/MAX/MIN+3
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 3/MAX/MIN+1
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 2/MAX/-1
+MAX MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MAX -1 1/MAX/MAX
+MAX MAX 1 1/MAX/MAX
+MAX MAX -2 1/MAX/MAX
+MAX MAX 2 1/MAX/MAX
+MAX MAX -3 1/MAX/MAX
+MAX MAX 3 1/MAX/MAX
+MAX MAX 17 1/MAX/MAX
+MAX MAX 127 1/MAX/MAX
+MAX MAX MIN+1 1/MAX/MAX
+MAX MAX MAX 1/MAX/MAX
+MAX MAX MIN 1/MAX/MAX
+MAX MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 1 0
+MAX MIN -2 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483648 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 2 0
+MAX MIN -3 1431655766/MAX/MIN
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 3/MAX/MIN+1
+MAX MIN MAX 0
+MAX MIN MIN 2/MAX/-1
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 0 -1 0
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 0
+MIN 0 2 1073741825/MIN/0
+MIN 0 -3 0
+MIN 0 3 715827883/MIN/-2
+MIN 0 17 126322568/MIN/-9
+MIN 0 127 16909321/MIN/-8
+MIN 0 MIN+1 0
+MIN 0 MAX 2/MIN/-1
+MIN 0 MIN 0
+MIN -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN -1 -1 0
+MIN -1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 -2 0
+MIN -1 2 1073741824/MIN/-2
+MIN -1 -3 0
+MIN -1 3 715827883/MIN/-2
+MIN -1 17 126322568/MIN/-9
+MIN -1 127 16909321/MIN/-8
+MIN -1 MIN+1 0
+MIN -1 MAX 2/MIN/-1
+MIN -1 MIN 0
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 1 -1 0
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 0
+MIN 1 2 1073741825/MIN/0
+MIN 1 -3 0
+MIN 1 3 715827884/MIN/1
+MIN 1 17 126322568/MIN/-9
+MIN 1 127 16909321/MIN/-8
+MIN 1 MIN+1 0
+MIN 1 MAX 2/MIN/-1
+MIN 1 MIN 0
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 3 -1 0
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 0
+MIN 3 2 1073741826/MIN/2
+MIN 3 -3 0
+MIN 3 3 715827884/MIN/1
+MIN 3 17 126322568/MIN/-9
+MIN 3 127 16909321/MIN/-8
+MIN 3 MIN+1 0
+MIN 3 MAX 2/MIN/-1
+MIN 3 MIN 0
+MIN MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN+1 -1 0
+MIN MIN+1 1 2/MIN/MIN+1
+MIN MIN+1 -2 0
+MIN MIN+1 2 1/MIN/MIN
+MIN MIN+1 -3 0
+MIN MIN+1 3 1/MIN/MIN
+MIN MIN+1 17 1/MIN/MIN
+MIN MIN+1 127 1/MIN/MIN
+MIN MIN+1 MIN+1 0
+MIN MIN+1 MAX 1/MIN/MIN
+MIN MIN+1 MIN 0
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MAX -1 0
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 0
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 0
+MIN MAX 3 1431655766/MIN/MAX
+MIN MAX 17 252645136/MIN/MAX
+MIN MAX 127 33818641/MIN/MAX-15
+MIN MAX MIN+1 0
+MIN MAX MAX 3/MIN/MAX-1
+MIN MAX MIN 0
+MIN MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN -1 1/MIN/MIN
+MIN MIN 1 1/MIN/MIN
+MIN MIN -2 1/MIN/MIN
+MIN MIN 2 1/MIN/MIN
+MIN MIN -3 1/MIN/MIN
+MIN MIN 3 1/MIN/MIN
+MIN MIN 17 1/MIN/MIN
+MIN MIN 127 1/MIN/MIN
+MIN MIN MIN+1 1/MIN/MIN
+MIN MIN MAX 1/MIN/MIN
+MIN MIN MIN 1/MIN/MIN
+
+>>> Range.apply <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 0 -1 0
+0 0 1 0
+0 0 -2 0
+0 0 2 0
+0 0 -3 0
+0 0 3 0
+0 0 17 0
+0 0 127 0
+0 0 MIN+1 0
+0 0 MAX 0
+0 0 MIN 0
+0 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 -1 -1 1/0/0
+0 -1 1 0
+0 -1 -2 1/0/0
+0 -1 2 0
+0 -1 -3 1/0/0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 1/0/0
+0 -1 MAX 0
+0 -1 MIN 1/0/0
+0 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 1 -1 0
+0 1 1 1/0/0
+0 1 -2 0
+0 1 2 1/0/0
+0 1 -3 0
+0 1 3 1/0/0
+0 1 17 1/0/0
+0 1 127 1/0/0
+0 1 MIN+1 0
+0 1 MAX 1/0/0
+0 1 MIN 0
+0 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 3 -1 0
+0 3 1 3/0/2
+0 3 -2 0
+0 3 2 2/0/2
+0 3 -3 0
+0 3 3 1/0/0
+0 3 17 1/0/0
+0 3 127 1/0/0
+0 3 MIN+1 0
+0 3 MAX 1/0/0
+0 3 MIN 0
+0 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN+1 -1 MAX/0/MIN+2
+0 MIN+1 1 0
+0 MIN+1 -2 1073741824/0/MIN+2
+0 MIN+1 2 0
+0 MIN+1 -3 715827883/0/MIN+2
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 1/0/0
+0 MIN+1 MAX 0
+0 MIN+1 MIN 1/0/0
+0 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MAX -1 0
+0 MAX 1 MAX/0/MAX-1
+0 MAX -2 0
+0 MAX 2 1073741824/0/MAX-1
+0 MAX -3 0
+0 MAX 3 715827883/0/MAX-1
+0 MAX 17 126322568/0/MAX-8
+0 MAX 127 16909321/0/MAX-7
+0 MAX MIN+1 0
+0 MAX MAX 1/0/0
+0 MAX MIN 0
+0 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN -1 ---
+ java.lang.IllegalArgumentException: 0 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN 1 0
+0 MIN -2 1073741824/0/MIN+2
+0 MIN 2 0
+0 MIN -3 715827883/0/MIN+2
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 2/0/MIN+1
+0 MIN MAX 0
+0 MIN MIN 1/0/0
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 0 -1 0
+-1 0 1 1/-1/-1
+-1 0 -2 0
+-1 0 2 1/-1/-1
+-1 0 -3 0
+-1 0 3 1/-1/-1
+-1 0 17 1/-1/-1
+-1 0 127 1/-1/-1
+-1 0 MIN+1 0
+-1 0 MAX 1/-1/-1
+-1 0 MIN 0
+-1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 -1 -1 0
+-1 -1 1 0
+-1 -1 -2 0
+-1 -1 2 0
+-1 -1 -3 0
+-1 -1 3 0
+-1 -1 17 0
+-1 -1 127 0
+-1 -1 MIN+1 0
+-1 -1 MAX 0
+-1 -1 MIN 0
+-1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 1 -1 0
+-1 1 1 2/-1/0
+-1 1 -2 0
+-1 1 2 1/-1/-1
+-1 1 -3 0
+-1 1 3 1/-1/-1
+-1 1 17 1/-1/-1
+-1 1 127 1/-1/-1
+-1 1 MIN+1 0
+-1 1 MAX 1/-1/-1
+-1 1 MIN 0
+-1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 3 -1 0
+-1 3 1 4/-1/2
+-1 3 -2 0
+-1 3 2 2/-1/1
+-1 3 -3 0
+-1 3 3 2/-1/2
+-1 3 17 1/-1/-1
+-1 3 127 1/-1/-1
+-1 3 MIN+1 0
+-1 3 MAX 1/-1/-1
+-1 3 MIN 0
+-1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN+1 -1 MAX-1/-1/MIN+2
+-1 MIN+1 1 0
+-1 MIN+1 -2 1073741823/-1/MIN+3
+-1 MIN+1 2 0
+-1 MIN+1 -3 715827882/-1/MIN+4
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 1/-1/-1
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 1/-1/-1
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MAX -1 0
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 0
+-1 MAX 2 1073741824/-1/MAX-2
+-1 MAX -3 0
+-1 MAX 3 715827883/-1/MAX-2
+-1 MAX 17 126322568/-1/MAX-9
+-1 MAX 127 16909321/-1/MAX-8
+-1 MAX MIN+1 0
+-1 MAX MAX 2/-1/MAX-1
+-1 MAX MIN 0
+-1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN -1 MAX/-1/MIN+1
+-1 MIN 1 0
+-1 MIN -2 1073741824/-1/MIN+1
+-1 MIN 2 0
+-1 MIN -3 715827883/-1/MIN+1
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 1/-1/-1
+-1 MIN MAX 0
+-1 MIN MIN 1/-1/-1
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 0 -1 1/1/1
+1 0 1 0
+1 0 -2 1/1/1
+1 0 2 0
+1 0 -3 1/1/1
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 1/1/1
+1 0 MAX 0
+1 0 MIN 1/1/1
+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 -1 -1 2/1/0
+1 -1 1 0
+1 -1 -2 1/1/1
+1 -1 2 0
+1 -1 -3 1/1/1
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 1/1/1
+1 -1 MAX 0
+1 -1 MIN 1/1/1
+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 1 -1 0
+1 1 1 0
+1 1 -2 0
+1 1 2 0
+1 1 -3 0
+1 1 3 0
+1 1 17 0
+1 1 127 0
+1 1 MIN+1 0
+1 1 MAX 0
+1 1 MIN 0
+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 3 -1 0
+1 3 1 2/1/2
+1 3 -2 0
+1 3 2 1/1/1
+1 3 -3 0
+1 3 3 1/1/1
+1 3 17 1/1/1
+1 3 127 1/1/1
+1 3 MIN+1 0
+1 3 MAX 1/1/1
+1 3 MIN 0
+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 1 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN+1 1 0
+1 MIN+1 -2 1073741824/1/MIN+3
+1 MIN+1 2 0
+1 MIN+1 -3 715827883/1/MIN+3
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 2/1/MIN+2
+1 MIN+1 MAX 0
+1 MIN+1 MIN 1/1/1
+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MAX -1 0
+1 MAX 1 MAX-1/1/MAX-1
+1 MAX -2 0
+1 MAX 2 1073741823/1/MAX-2
+1 MAX -3 0
+1 MAX 3 715827882/1/MAX-3
+1 MAX 17 126322568/1/MAX-7
+1 MAX 127 16909321/1/MAX-6
+1 MAX MIN+1 0
+1 MAX MAX 1/1/1
+1 MAX MIN 0
+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN -1 ---
+ java.lang.IllegalArgumentException: 1 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN 1 0
+1 MIN -2 1073741825/1/MIN+1
+1 MIN 2 0
+1 MIN -3 715827883/1/MIN+3
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 2/1/MIN+2
+1 MIN MAX 0
+1 MIN MIN 2/1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 0 -1 3/3/1
+3 0 1 0
+3 0 -2 2/3/1
+3 0 2 0
+3 0 -3 1/3/3
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 1/3/3
+3 0 MAX 0
+3 0 MIN 1/3/3
+3 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 -1 -1 4/3/0
+3 -1 1 0
+3 -1 -2 2/3/1
+3 -1 2 0
+3 -1 -3 2/3/0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 1/3/3
+3 -1 MAX 0
+3 -1 MIN 1/3/3
+3 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 1 -1 2/3/2
+3 1 1 0
+3 1 -2 1/3/3
+3 1 2 0
+3 1 -3 1/3/3
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 1/3/3
+3 1 MAX 0
+3 1 MIN 1/3/3
+3 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 3 -1 0
+3 3 1 0
+3 3 -2 0
+3 3 2 0
+3 3 -3 0
+3 3 3 0
+3 3 17 0
+3 3 127 0
+3 3 MIN+1 0
+3 3 MAX 0
+3 3 MIN 0
+3 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 3 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN+1 1 0
+3 MIN+1 -2 1073741825/3/MIN+3
+3 MIN+1 2 0
+3 MIN+1 -3 715827884/3/MIN+2
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 2/3/MIN+4
+3 MIN+1 MAX 0
+3 MIN+1 MIN 2/3/MIN+3
+3 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MAX -1 0
+3 MAX 1 MAX-3/3/MAX-1
+3 MAX -2 0
+3 MAX 2 1073741822/3/MAX-2
+3 MAX -3 0
+3 MAX 3 715827882/3/MAX-1
+3 MAX 17 126322568/3/MAX-5
+3 MAX 127 16909321/3/MAX-4
+3 MAX MIN+1 0
+3 MAX MAX 1/3/3
+3 MAX MIN 0
+3 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN -1 ---
+ java.lang.IllegalArgumentException: 3 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN 1 0
+3 MIN -2 1073741826/3/MIN+1
+3 MIN 2 0
+3 MIN -3 715827884/3/MIN+2
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 2/3/MIN+4
+3 MIN MAX 0
+3 MIN MIN 2/3/MIN+3
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 0 -1 0
+MIN+1 0 1 MAX/MIN+1/-1
+MIN+1 0 -2 0
+MIN+1 0 2 1073741824/MIN+1/-1
+MIN+1 0 -3 0
+MIN+1 0 3 715827883/MIN+1/-1
+MIN+1 0 17 126322568/MIN+1/-8
+MIN+1 0 127 16909321/MIN+1/-7
+MIN+1 0 MIN+1 0
+MIN+1 0 MAX 1/MIN+1/MIN+1
+MIN+1 0 MIN 0
+MIN+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 -1 -1 0
+MIN+1 -1 1 MAX-1/MIN+1/-2
+MIN+1 -1 -2 0
+MIN+1 -1 2 1073741823/MIN+1/-3
+MIN+1 -1 -3 0
+MIN+1 -1 3 715827882/MIN+1/-4
+MIN+1 -1 17 126322568/MIN+1/-8
+MIN+1 -1 127 16909321/MIN+1/-7
+MIN+1 -1 MIN+1 0
+MIN+1 -1 MAX 1/MIN+1/MIN+1
+MIN+1 -1 MIN 0
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 1 -1 0
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 0
+MIN+1 1 2 1073741824/MIN+1/-1
+MIN+1 1 -3 0
+MIN+1 1 3 715827883/MIN+1/-1
+MIN+1 1 17 126322568/MIN+1/-8
+MIN+1 1 127 16909321/MIN+1/-7
+MIN+1 1 MIN+1 0
+MIN+1 1 MAX 2/MIN+1/0
+MIN+1 1 MIN 0
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 3 -1 0
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 0
+MIN+1 3 2 1073741825/MIN+1/1
+MIN+1 3 -3 0
+MIN+1 3 3 715827884/MIN+1/2
+MIN+1 3 17 126322568/MIN+1/-8
+MIN+1 3 127 16909321/MIN+1/-7
+MIN+1 3 MIN+1 0
+MIN+1 3 MAX 2/MIN+1/0
+MIN+1 3 MIN 0
+MIN+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN+1 -1 0
+MIN+1 MIN+1 1 0
+MIN+1 MIN+1 -2 0
+MIN+1 MIN+1 2 0
+MIN+1 MIN+1 -3 0
+MIN+1 MIN+1 3 0
+MIN+1 MIN+1 17 0
+MIN+1 MIN+1 127 0
+MIN+1 MIN+1 MIN+1 0
+MIN+1 MIN+1 MAX 0
+MIN+1 MIN+1 MIN 0
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MAX -1 0
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 0
+MIN+1 MAX 2 MAX/MIN+1/MAX-2
+MIN+1 MAX -3 0
+MIN+1 MAX 3 1431655765/MIN+1/MAX-2
+MIN+1 MAX 17 252645135/MIN+1/MAX-16
+MIN+1 MAX 127 33818641/MIN+1/MAX-14
+MIN+1 MAX MIN+1 0
+MIN+1 MAX MAX 2/MIN+1/0
+MIN+1 MAX MIN 0
+MIN+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN -1 1/MIN+1/MIN+1
+MIN+1 MIN 1 0
+MIN+1 MIN -2 1/MIN+1/MIN+1
+MIN+1 MIN 2 0
+MIN+1 MIN -3 1/MIN+1/MIN+1
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 1/MIN+1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 0 -1 MAX/MAX/1
+MAX 0 1 0
+MAX 0 -2 1073741824/MAX/1
+MAX 0 2 0
+MAX 0 -3 715827883/MAX/1
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 1/MAX/MAX
+MAX 0 MAX 0
+MAX 0 MIN 1/MAX/MAX
+MAX -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX -1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -1 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX -1 1 0
+MAX -1 -2 1073741824/MAX/1
+MAX -1 2 0
+MAX -1 -3 715827883/MAX/1
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 2/MAX/0
+MAX -1 MAX 0
+MAX -1 MIN 1/MAX/MAX
+MAX 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 1 -1 MAX-1/MAX/2
+MAX 1 1 0
+MAX 1 -2 1073741823/MAX/3
+MAX 1 2 0
+MAX 1 -3 715827882/MAX/4
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 1/MAX/MAX
+MAX 1 MAX 0
+MAX 1 MIN 1/MAX/MAX
+MAX 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 3 -1 MAX-3/MAX/4
+MAX 3 1 0
+MAX 3 -2 1073741822/MAX/5
+MAX 3 2 0
+MAX 3 -3 715827882/MAX/4
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 1/MAX/MAX
+MAX 3 MAX 0
+MAX 3 MIN 1/MAX/MAX
+MAX MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 1 0
+MAX MIN+1 -2 MAX/MAX/MIN+3
+MAX MIN+1 2 0
+MAX MIN+1 -3 1431655765/MAX/MIN+3
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 2/MAX/0
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 2/MAX/-1
+MAX MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MAX -1 0
+MAX MAX 1 0
+MAX MAX -2 0
+MAX MAX 2 0
+MAX MAX -3 0
+MAX MAX 3 0
+MAX MAX 17 0
+MAX MAX 127 0
+MAX MAX MIN+1 0
+MAX MAX MAX 0
+MAX MAX MIN 0
+MAX MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 1 0
+MAX MIN -2 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483648 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 2 0
+MAX MIN -3 1431655765/MAX/MIN+3
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 3/MAX/MIN+1
+MAX MIN MAX 0
+MAX MIN MIN 2/MAX/-1
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 0 -1 0
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 0
+MIN 0 2 1073741824/MIN/-2
+MIN 0 -3 0
+MIN 0 3 715827883/MIN/-2
+MIN 0 17 126322568/MIN/-9
+MIN 0 127 16909321/MIN/-8
+MIN 0 MIN+1 0
+MIN 0 MAX 2/MIN/-1
+MIN 0 MIN 0
+MIN -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN -1 -1 0
+MIN -1 1 MAX/MIN/-2
+MIN -1 -2 0
+MIN -1 2 1073741824/MIN/-2
+MIN -1 -3 0
+MIN -1 3 715827883/MIN/-2
+MIN -1 17 126322568/MIN/-9
+MIN -1 127 16909321/MIN/-8
+MIN -1 MIN+1 0
+MIN -1 MAX 1/MIN/MIN
+MIN -1 MIN 0
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 1 -1 0
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 0
+MIN 1 2 1073741825/MIN/0
+MIN 1 -3 0
+MIN 1 3 715827883/MIN/-2
+MIN 1 17 126322568/MIN/-9
+MIN 1 127 16909321/MIN/-8
+MIN 1 MIN+1 0
+MIN 1 MAX 2/MIN/-1
+MIN 1 MIN 0
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 3 -1 0
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 0
+MIN 3 2 1073741826/MIN/2
+MIN 3 -3 0
+MIN 3 3 715827884/MIN/1
+MIN 3 17 126322568/MIN/-9
+MIN 3 127 16909321/MIN/-8
+MIN 3 MIN+1 0
+MIN 3 MAX 2/MIN/-1
+MIN 3 MIN 0
+MIN MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN+1 -1 0
+MIN MIN+1 1 1/MIN/MIN
+MIN MIN+1 -2 0
+MIN MIN+1 2 1/MIN/MIN
+MIN MIN+1 -3 0
+MIN MIN+1 3 1/MIN/MIN
+MIN MIN+1 17 1/MIN/MIN
+MIN MIN+1 127 1/MIN/MIN
+MIN MIN+1 MIN+1 0
+MIN MIN+1 MAX 1/MIN/MIN
+MIN MIN+1 MIN 0
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MAX -1 0
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 0
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 0
+MIN MAX 3 1431655765/MIN/MAX-3
+MIN MAX 17 252645135/MIN/MAX-17
+MIN MAX 127 33818641/MIN/MAX-15
+MIN MAX MIN+1 0
+MIN MAX MAX 3/MIN/MAX-1
+MIN MAX MIN 0
+MIN MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN -1 0
+MIN MIN 1 0
+MIN MIN -2 0
+MIN MIN 2 0
+MIN MIN -3 0
+MIN MIN 3 0
+MIN MIN 17 0
+MIN MIN 127 0
+MIN MIN MIN+1 0
+MIN MIN MAX 0
+MIN MIN MIN 0
+
+>>> start to end <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 1/0/0
+0 0 -1 1/0/0
+0 0 1 1/0/0
+0 0 -2 1/0/0
+0 0 2 1/0/0
+0 0 -3 1/0/0
+0 0 3 1/0/0
+0 0 17 1/0/0
+0 0 127 1/0/0
+0 0 MIN+1 1/0/0
+0 0 MAX 1/0/0
+0 0 MIN 1/0/0
+0 -1 0 0
+0 -1 -1 0
+0 -1 1 0
+0 -1 -2 0
+0 -1 2 0
+0 -1 -3 0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 0
+0 -1 MAX 0
+0 -1 MIN 0
+0 1 0 2/0/1
+0 1 -1 2/0/1
+0 1 1 2/0/1
+0 1 -2 2/0/1
+0 1 2 2/0/1
+0 1 -3 2/0/1
+0 1 3 2/0/1
+0 1 17 2/0/1
+0 1 127 2/0/1
+0 1 MIN+1 2/0/1
+0 1 MAX 2/0/1
+0 1 MIN 2/0/1
+0 3 0 4/0/3
+0 3 -1 4/0/3
+0 3 1 4/0/3
+0 3 -2 4/0/3
+0 3 2 4/0/3
+0 3 -3 4/0/3
+0 3 3 4/0/3
+0 3 17 4/0/3
+0 3 127 4/0/3
+0 3 MIN+1 4/0/3
+0 3 MAX 4/0/3
+0 3 MIN 4/0/3
+0 MIN+1 0 0
+0 MIN+1 -1 0
+0 MIN+1 1 0
+0 MIN+1 -2 0
+0 MIN+1 2 0
+0 MIN+1 -3 0
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 0
+0 MIN+1 MAX 0
+0 MIN+1 MIN 0
+0 MAX 0 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX -1 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX 1 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX -2 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX 2 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX -3 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX 3 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX 17 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX 127 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX MIN+1 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX MAX ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX MIN ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN 0 0
+0 MIN -1 0
+0 MIN 1 0
+0 MIN -2 0
+0 MIN 2 0
+0 MIN -3 0
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 0
+0 MIN MAX 0
+0 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 2/-1/0
+-1 0 -1 2/-1/0
+-1 0 1 2/-1/0
+-1 0 -2 2/-1/0
+-1 0 2 2/-1/0
+-1 0 -3 2/-1/0
+-1 0 3 2/-1/0
+-1 0 17 2/-1/0
+-1 0 127 2/-1/0
+-1 0 MIN+1 2/-1/0
+-1 0 MAX 2/-1/0
+-1 0 MIN 2/-1/0
+-1 -1 0 1/-1/-1
+-1 -1 -1 1/-1/-1
+-1 -1 1 1/-1/-1
+-1 -1 -2 1/-1/-1
+-1 -1 2 1/-1/-1
+-1 -1 -3 1/-1/-1
+-1 -1 3 1/-1/-1
+-1 -1 17 1/-1/-1
+-1 -1 127 1/-1/-1
+-1 -1 MIN+1 1/-1/-1
+-1 -1 MAX 1/-1/-1
+-1 -1 MIN 1/-1/-1
+-1 1 0 3/-1/1
+-1 1 -1 3/-1/1
+-1 1 1 3/-1/1
+-1 1 -2 3/-1/1
+-1 1 2 3/-1/1
+-1 1 -3 3/-1/1
+-1 1 3 3/-1/1
+-1 1 17 3/-1/1
+-1 1 127 3/-1/1
+-1 1 MIN+1 3/-1/1
+-1 1 MAX 3/-1/1
+-1 1 MIN 3/-1/1
+-1 3 0 5/-1/3
+-1 3 -1 5/-1/3
+-1 3 1 5/-1/3
+-1 3 -2 5/-1/3
+-1 3 2 5/-1/3
+-1 3 -3 5/-1/3
+-1 3 3 5/-1/3
+-1 3 17 5/-1/3
+-1 3 127 5/-1/3
+-1 3 MIN+1 5/-1/3
+-1 3 MAX 5/-1/3
+-1 3 MIN 5/-1/3
+-1 MIN+1 0 0
+-1 MIN+1 -1 0
+-1 MIN+1 1 0
+-1 MIN+1 -2 0
+-1 MIN+1 2 0
+-1 MIN+1 -3 0
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 0
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 0
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -1 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 2 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -3 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 3 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 17 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 127 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MAX ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MIN ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MIN 0 0
+-1 MIN -1 0
+-1 MIN 1 0
+-1 MIN -2 0
+-1 MIN 2 0
+-1 MIN -3 0
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 0
+-1 MIN MAX 0
+-1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 0
+1 0 -1 0
+1 0 1 0
+1 0 -2 0
+1 0 2 0
+1 0 -3 0
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 0
+1 0 MAX 0
+1 0 MIN 0
+1 -1 0 0
+1 -1 -1 0
+1 -1 1 0
+1 -1 -2 0
+1 -1 2 0
+1 -1 -3 0
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 0
+1 -1 MAX 0
+1 -1 MIN 0
+1 1 0 1/1/1
+1 1 -1 1/1/1
+1 1 1 1/1/1
+1 1 -2 1/1/1
+1 1 2 1/1/1
+1 1 -3 1/1/1
+1 1 3 1/1/1
+1 1 17 1/1/1
+1 1 127 1/1/1
+1 1 MIN+1 1/1/1
+1 1 MAX 1/1/1
+1 1 MIN 1/1/1
+1 3 0 3/1/3
+1 3 -1 3/1/3
+1 3 1 3/1/3
+1 3 -2 3/1/3
+1 3 2 3/1/3
+1 3 -3 3/1/3
+1 3 3 3/1/3
+1 3 17 3/1/3
+1 3 127 3/1/3
+1 3 MIN+1 3/1/3
+1 3 MAX 3/1/3
+1 3 MIN 3/1/3
+1 MIN+1 0 0
+1 MIN+1 -1 0
+1 MIN+1 1 0
+1 MIN+1 -2 0
+1 MIN+1 2 0
+1 MIN+1 -3 0
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 0
+1 MIN+1 MAX 0
+1 MIN+1 MIN 0
+1 MAX 0 MAX/1/MAX
+1 MAX -1 MAX/1/MAX
+1 MAX 1 MAX/1/MAX
+1 MAX -2 MAX/1/MAX
+1 MAX 2 MAX/1/MAX
+1 MAX -3 MAX/1/MAX
+1 MAX 3 MAX/1/MAX
+1 MAX 17 MAX/1/MAX
+1 MAX 127 MAX/1/MAX
+1 MAX MIN+1 MAX/1/MAX
+1 MAX MAX MAX/1/MAX
+1 MAX MIN MAX/1/MAX
+1 MIN 0 0
+1 MIN -1 0
+1 MIN 1 0
+1 MIN -2 0
+1 MIN 2 0
+1 MIN -3 0
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 0
+1 MIN MAX 0
+1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 0
+3 0 -1 0
+3 0 1 0
+3 0 -2 0
+3 0 2 0
+3 0 -3 0
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 0
+3 0 MAX 0
+3 0 MIN 0
+3 -1 0 0
+3 -1 -1 0
+3 -1 1 0
+3 -1 -2 0
+3 -1 2 0
+3 -1 -3 0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 0
+3 -1 MAX 0
+3 -1 MIN 0
+3 1 0 0
+3 1 -1 0
+3 1 1 0
+3 1 -2 0
+3 1 2 0
+3 1 -3 0
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 0
+3 1 MAX 0
+3 1 MIN 0
+3 3 0 1/3/3
+3 3 -1 1/3/3
+3 3 1 1/3/3
+3 3 -2 1/3/3
+3 3 2 1/3/3
+3 3 -3 1/3/3
+3 3 3 1/3/3
+3 3 17 1/3/3
+3 3 127 1/3/3
+3 3 MIN+1 1/3/3
+3 3 MAX 1/3/3
+3 3 MIN 1/3/3
+3 MIN+1 0 0
+3 MIN+1 -1 0
+3 MIN+1 1 0
+3 MIN+1 -2 0
+3 MIN+1 2 0
+3 MIN+1 -3 0
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 0
+3 MIN+1 MAX 0
+3 MIN+1 MIN 0
+3 MAX 0 MAX-2/3/MAX
+3 MAX -1 MAX-2/3/MAX
+3 MAX 1 MAX-2/3/MAX
+3 MAX -2 MAX-2/3/MAX
+3 MAX 2 MAX-2/3/MAX
+3 MAX -3 MAX-2/3/MAX
+3 MAX 3 MAX-2/3/MAX
+3 MAX 17 MAX-2/3/MAX
+3 MAX 127 MAX-2/3/MAX
+3 MAX MIN+1 MAX-2/3/MAX
+3 MAX MAX MAX-2/3/MAX
+3 MAX MIN MAX-2/3/MAX
+3 MIN 0 0
+3 MIN -1 0
+3 MIN 1 0
+3 MIN -2 0
+3 MIN 2 0
+3 MIN -3 0
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 0
+3 MIN MAX 0
+3 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 -1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 -2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 -3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 17 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 127 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 MAX ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 MIN ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 -1 0 MAX/MIN+1/-1
+MIN+1 -1 -1 MAX/MIN+1/-1
+MIN+1 -1 1 MAX/MIN+1/-1
+MIN+1 -1 -2 MAX/MIN+1/-1
+MIN+1 -1 2 MAX/MIN+1/-1
+MIN+1 -1 -3 MAX/MIN+1/-1
+MIN+1 -1 3 MAX/MIN+1/-1
+MIN+1 -1 17 MAX/MIN+1/-1
+MIN+1 -1 127 MAX/MIN+1/-1
+MIN+1 -1 MIN+1 MAX/MIN+1/-1
+MIN+1 -1 MAX MAX/MIN+1/-1
+MIN+1 -1 MIN MAX/MIN+1/-1
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 17 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 127 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MAX ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MIN ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 17 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 127 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MAX ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MIN ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MIN+1 0 1/MIN+1/MIN+1
+MIN+1 MIN+1 -1 1/MIN+1/MIN+1
+MIN+1 MIN+1 1 1/MIN+1/MIN+1
+MIN+1 MIN+1 -2 1/MIN+1/MIN+1
+MIN+1 MIN+1 2 1/MIN+1/MIN+1
+MIN+1 MIN+1 -3 1/MIN+1/MIN+1
+MIN+1 MIN+1 3 1/MIN+1/MIN+1
+MIN+1 MIN+1 17 1/MIN+1/MIN+1
+MIN+1 MIN+1 127 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN+1 MAX 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN 1/MIN+1/MIN+1
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 3 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 17 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 127 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MAX ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MIN ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MIN 0 0
+MIN+1 MIN -1 0
+MIN+1 MIN 1 0
+MIN+1 MIN -2 0
+MIN+1 MIN 2 0
+MIN+1 MIN -3 0
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 0
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 0
+MAX 0 -1 0
+MAX 0 1 0
+MAX 0 -2 0
+MAX 0 2 0
+MAX 0 -3 0
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 0
+MAX 0 MAX 0
+MAX 0 MIN 0
+MAX -1 0 0
+MAX -1 -1 0
+MAX -1 1 0
+MAX -1 -2 0
+MAX -1 2 0
+MAX -1 -3 0
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 0
+MAX -1 MAX 0
+MAX -1 MIN 0
+MAX 1 0 0
+MAX 1 -1 0
+MAX 1 1 0
+MAX 1 -2 0
+MAX 1 2 0
+MAX 1 -3 0
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 0
+MAX 1 MAX 0
+MAX 1 MIN 0
+MAX 3 0 0
+MAX 3 -1 0
+MAX 3 1 0
+MAX 3 -2 0
+MAX 3 2 0
+MAX 3 -3 0
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 0
+MAX 3 MAX 0
+MAX 3 MIN 0
+MAX MIN+1 0 0
+MAX MIN+1 -1 0
+MAX MIN+1 1 0
+MAX MIN+1 -2 0
+MAX MIN+1 2 0
+MAX MIN+1 -3 0
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 0
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 0
+MAX MAX 0 1/MAX/MAX
+MAX MAX -1 1/MAX/MAX
+MAX MAX 1 1/MAX/MAX
+MAX MAX -2 1/MAX/MAX
+MAX MAX 2 1/MAX/MAX
+MAX MAX -3 1/MAX/MAX
+MAX MAX 3 1/MAX/MAX
+MAX MAX 17 1/MAX/MAX
+MAX MAX 127 1/MAX/MAX
+MAX MAX MIN+1 1/MAX/MAX
+MAX MAX MAX 1/MAX/MAX
+MAX MAX MIN 1/MAX/MAX
+MAX MIN 0 0
+MAX MIN -1 0
+MAX MIN 1 0
+MAX MIN -2 0
+MAX MIN 2 0
+MAX MIN -3 0
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 0
+MAX MIN MAX 0
+MAX MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 17 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 127 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 0 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 3 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 17 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 127 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 17 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 127 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 17 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 127 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MIN+1 0 2/MIN/MIN+1
+MIN MIN+1 -1 2/MIN/MIN+1
+MIN MIN+1 1 2/MIN/MIN+1
+MIN MIN+1 -2 2/MIN/MIN+1
+MIN MIN+1 2 2/MIN/MIN+1
+MIN MIN+1 -3 2/MIN/MIN+1
+MIN MIN+1 3 2/MIN/MIN+1
+MIN MIN+1 17 2/MIN/MIN+1
+MIN MIN+1 127 2/MIN/MIN+1
+MIN MIN+1 MIN+1 2/MIN/MIN+1
+MIN MIN+1 MAX 2/MIN/MIN+1
+MIN MIN+1 MIN 2/MIN/MIN+1
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 3 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 17 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 127 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MAX ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MIN ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MIN 0 1/MIN/MIN
+MIN MIN -1 1/MIN/MIN
+MIN MIN 1 1/MIN/MIN
+MIN MIN -2 1/MIN/MIN
+MIN MIN 2 1/MIN/MIN
+MIN MIN -3 1/MIN/MIN
+MIN MIN 3 1/MIN/MIN
+MIN MIN 17 1/MIN/MIN
+MIN MIN 127 1/MIN/MIN
+MIN MIN MIN+1 1/MIN/MIN
+MIN MIN MAX 1/MIN/MIN
+MIN MIN MIN 1/MIN/MIN
+
+>>> start to end by step <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 0 -1 1/0/0
+0 0 1 1/0/0
+0 0 -2 1/0/0
+0 0 2 1/0/0
+0 0 -3 1/0/0
+0 0 3 1/0/0
+0 0 17 1/0/0
+0 0 127 1/0/0
+0 0 MIN+1 1/0/0
+0 0 MAX 1/0/0
+0 0 MIN 1/0/0
+0 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 -1 -1 2/0/-1
+0 -1 1 0
+0 -1 -2 1/0/0
+0 -1 2 0
+0 -1 -3 1/0/0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 1/0/0
+0 -1 MAX 0
+0 -1 MIN 1/0/0
+0 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 1 -1 0
+0 1 1 2/0/1
+0 1 -2 0
+0 1 2 1/0/0
+0 1 -3 0
+0 1 3 1/0/0
+0 1 17 1/0/0
+0 1 127 1/0/0
+0 1 MIN+1 0
+0 1 MAX 1/0/0
+0 1 MIN 0
+0 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 3 -1 0
+0 3 1 4/0/3
+0 3 -2 0
+0 3 2 2/0/2
+0 3 -3 0
+0 3 3 2/0/3
+0 3 17 1/0/0
+0 3 127 1/0/0
+0 3 MIN+1 0
+0 3 MAX 1/0/0
+0 3 MIN 0
+0 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 0 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN+1 1 0
+0 MIN+1 -2 1073741824/0/MIN+2
+0 MIN+1 2 0
+0 MIN+1 -3 715827883/0/MIN+2
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 2/0/MIN+1
+0 MIN+1 MAX 0
+0 MIN+1 MIN 1/0/0
+0 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MAX -1 0
+0 MAX 1 ---
+ java.lang.IllegalArgumentException: 0 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+0 MAX -2 0
+0 MAX 2 1073741824/0/MAX-1
+0 MAX -3 0
+0 MAX 3 715827883/0/MAX-1
+0 MAX 17 126322568/0/MAX-8
+0 MAX 127 16909321/0/MAX-7
+0 MAX MIN+1 0
+0 MAX MAX 2/0/MAX
+0 MAX MIN 0
+0 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN -1 ---
+ java.lang.IllegalArgumentException: 0 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN 1 0
+0 MIN -2 1073741825/0/MIN
+0 MIN 2 0
+0 MIN -3 715827883/0/MIN+2
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 2/0/MIN+1
+0 MIN MAX 0
+0 MIN MIN 2/0/MIN
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 0 -1 0
+-1 0 1 2/-1/0
+-1 0 -2 0
+-1 0 2 1/-1/-1
+-1 0 -3 0
+-1 0 3 1/-1/-1
+-1 0 17 1/-1/-1
+-1 0 127 1/-1/-1
+-1 0 MIN+1 0
+-1 0 MAX 1/-1/-1
+-1 0 MIN 0
+-1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 -1 -1 1/-1/-1
+-1 -1 1 1/-1/-1
+-1 -1 -2 1/-1/-1
+-1 -1 2 1/-1/-1
+-1 -1 -3 1/-1/-1
+-1 -1 3 1/-1/-1
+-1 -1 17 1/-1/-1
+-1 -1 127 1/-1/-1
+-1 -1 MIN+1 1/-1/-1
+-1 -1 MAX 1/-1/-1
+-1 -1 MIN 1/-1/-1
+-1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 1 -1 0
+-1 1 1 3/-1/1
+-1 1 -2 0
+-1 1 2 2/-1/1
+-1 1 -3 0
+-1 1 3 1/-1/-1
+-1 1 17 1/-1/-1
+-1 1 127 1/-1/-1
+-1 1 MIN+1 0
+-1 1 MAX 1/-1/-1
+-1 1 MIN 0
+-1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 3 -1 0
+-1 3 1 5/-1/3
+-1 3 -2 0
+-1 3 2 3/-1/3
+-1 3 -3 0
+-1 3 3 2/-1/2
+-1 3 17 1/-1/-1
+-1 3 127 1/-1/-1
+-1 3 MIN+1 0
+-1 3 MAX 1/-1/-1
+-1 3 MIN 0
+-1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN+1 -1 MAX/-1/MIN+1
+-1 MIN+1 1 0
+-1 MIN+1 -2 1073741824/-1/MIN+1
+-1 MIN+1 2 0
+-1 MIN+1 -3 715827883/-1/MIN+1
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 1/-1/-1
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 1/-1/-1
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MAX -1 0
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 0
+-1 MAX 2 1073741825/-1/MAX
+-1 MAX -3 0
+-1 MAX 3 715827883/-1/MAX-2
+-1 MAX 17 126322568/-1/MAX-9
+-1 MAX 127 16909321/-1/MAX-8
+-1 MAX MIN+1 0
+-1 MAX MAX 2/-1/MAX-1
+-1 MAX MIN 0
+-1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN -1 ---
+ java.lang.IllegalArgumentException: -1 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+-1 MIN 1 0
+-1 MIN -2 1073741824/-1/MIN+1
+-1 MIN 2 0
+-1 MIN -3 715827883/-1/MIN+1
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 2/-1/MIN
+-1 MIN MAX 0
+-1 MIN MIN 1/-1/-1
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 0 -1 2/1/0
+1 0 1 0
+1 0 -2 1/1/1
+1 0 2 0
+1 0 -3 1/1/1
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 1/1/1
+1 0 MAX 0
+1 0 MIN 1/1/1
+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 -1 -1 3/1/-1
+1 -1 1 0
+1 -1 -2 2/1/-1
+1 -1 2 0
+1 -1 -3 1/1/1
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 1/1/1
+1 -1 MAX 0
+1 -1 MIN 1/1/1
+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 1 -1 1/1/1
+1 1 1 1/1/1
+1 1 -2 1/1/1
+1 1 2 1/1/1
+1 1 -3 1/1/1
+1 1 3 1/1/1
+1 1 17 1/1/1
+1 1 127 1/1/1
+1 1 MIN+1 1/1/1
+1 1 MAX 1/1/1
+1 1 MIN 1/1/1
+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 3 -1 0
+1 3 1 3/1/3
+1 3 -2 0
+1 3 2 2/1/3
+1 3 -3 0
+1 3 3 1/1/1
+1 3 17 1/1/1
+1 3 127 1/1/1
+1 3 MIN+1 0
+1 3 MAX 1/1/1
+1 3 MIN 0
+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 1 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN+1 1 0
+1 MIN+1 -2 1073741825/1/MIN+1
+1 MIN+1 2 0
+1 MIN+1 -3 715827883/1/MIN+3
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 2/1/MIN+2
+1 MIN+1 MAX 0
+1 MIN+1 MIN 2/1/MIN+1
+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MAX -1 0
+1 MAX 1 MAX/1/MAX
+1 MAX -2 0
+1 MAX 2 1073741824/1/MAX
+1 MAX -3 0
+1 MAX 3 715827883/1/MAX
+1 MAX 17 126322568/1/MAX-7
+1 MAX 127 16909321/1/MAX-6
+1 MAX MIN+1 0
+1 MAX MAX 1/1/1
+1 MAX MIN 0
+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN -1 ---
+ java.lang.IllegalArgumentException: 1 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN 1 0
+1 MIN -2 1073741825/1/MIN+1
+1 MIN 2 0
+1 MIN -3 715827884/1/MIN
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 2/1/MIN+2
+1 MIN MAX 0
+1 MIN MIN 2/1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 0 -1 4/3/0
+3 0 1 0
+3 0 -2 2/3/1
+3 0 2 0
+3 0 -3 2/3/0
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 1/3/3
+3 0 MAX 0
+3 0 MIN 1/3/3
+3 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 -1 -1 5/3/-1
+3 -1 1 0
+3 -1 -2 3/3/-1
+3 -1 2 0
+3 -1 -3 2/3/0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 1/3/3
+3 -1 MAX 0
+3 -1 MIN 1/3/3
+3 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 1 -1 3/3/1
+3 1 1 0
+3 1 -2 2/3/1
+3 1 2 0
+3 1 -3 1/3/3
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 1/3/3
+3 1 MAX 0
+3 1 MIN 1/3/3
+3 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 3 -1 1/3/3
+3 3 1 1/3/3
+3 3 -2 1/3/3
+3 3 2 1/3/3
+3 3 -3 1/3/3
+3 3 3 1/3/3
+3 3 17 1/3/3
+3 3 127 1/3/3
+3 3 MIN+1 1/3/3
+3 3 MAX 1/3/3
+3 3 MIN 1/3/3
+3 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 3 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN+1 1 0
+3 MIN+1 -2 1073741826/3/MIN+1
+3 MIN+1 2 0
+3 MIN+1 -3 715827884/3/MIN+2
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 2/3/MIN+4
+3 MIN+1 MAX 0
+3 MIN+1 MIN 2/3/MIN+3
+3 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MAX -1 0
+3 MAX 1 MAX-2/3/MAX
+3 MAX -2 0
+3 MAX 2 1073741823/3/MAX
+3 MAX -3 0
+3 MAX 3 715827882/3/MAX-1
+3 MAX 17 126322568/3/MAX-5
+3 MAX 127 16909321/3/MAX-4
+3 MAX MIN+1 0
+3 MAX MAX 1/3/3
+3 MAX MIN 0
+3 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN -1 ---
+ java.lang.IllegalArgumentException: 3 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN 1 0
+3 MIN -2 1073741826/3/MIN+1
+3 MIN 2 0
+3 MIN -3 715827884/3/MIN+2
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 2/3/MIN+4
+3 MIN MAX 0
+3 MIN MIN 2/3/MIN+3
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 0 -1 0
+MIN+1 0 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 0 -2 0
+MIN+1 0 2 1073741824/MIN+1/-1
+MIN+1 0 -3 0
+MIN+1 0 3 715827883/MIN+1/-1
+MIN+1 0 17 126322568/MIN+1/-8
+MIN+1 0 127 16909321/MIN+1/-7
+MIN+1 0 MIN+1 0
+MIN+1 0 MAX 2/MIN+1/0
+MIN+1 0 MIN 0
+MIN+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 -1 -1 0
+MIN+1 -1 1 MAX/MIN+1/-1
+MIN+1 -1 -2 0
+MIN+1 -1 2 1073741824/MIN+1/-1
+MIN+1 -1 -3 0
+MIN+1 -1 3 715827883/MIN+1/-1
+MIN+1 -1 17 126322568/MIN+1/-8
+MIN+1 -1 127 16909321/MIN+1/-7
+MIN+1 -1 MIN+1 0
+MIN+1 -1 MAX 1/MIN+1/MIN+1
+MIN+1 -1 MIN 0
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 1 -1 0
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 0
+MIN+1 1 2 1073741825/MIN+1/1
+MIN+1 1 -3 0
+MIN+1 1 3 715827883/MIN+1/-1
+MIN+1 1 17 126322568/MIN+1/-8
+MIN+1 1 127 16909321/MIN+1/-7
+MIN+1 1 MIN+1 0
+MIN+1 1 MAX 2/MIN+1/0
+MIN+1 1 MIN 0
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 3 -1 0
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 0
+MIN+1 3 2 1073741826/MIN+1/3
+MIN+1 3 -3 0
+MIN+1 3 3 715827884/MIN+1/2
+MIN+1 3 17 126322568/MIN+1/-8
+MIN+1 3 127 16909321/MIN+1/-7
+MIN+1 3 MIN+1 0
+MIN+1 3 MAX 2/MIN+1/0
+MIN+1 3 MIN 0
+MIN+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN+1 -1 1/MIN+1/MIN+1
+MIN+1 MIN+1 1 1/MIN+1/MIN+1
+MIN+1 MIN+1 -2 1/MIN+1/MIN+1
+MIN+1 MIN+1 2 1/MIN+1/MIN+1
+MIN+1 MIN+1 -3 1/MIN+1/MIN+1
+MIN+1 MIN+1 3 1/MIN+1/MIN+1
+MIN+1 MIN+1 17 1/MIN+1/MIN+1
+MIN+1 MIN+1 127 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN+1 MAX 1/MIN+1/MIN+1
+MIN+1 MIN+1 MIN 1/MIN+1/MIN+1
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MAX -1 0
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 0
+MIN+1 MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483647 to 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -3 0
+MIN+1 MAX 3 1431655765/MIN+1/MAX-2
+MIN+1 MAX 17 252645135/MIN+1/MAX-16
+MIN+1 MAX 127 33818641/MIN+1/MAX-14
+MIN+1 MAX MIN+1 0
+MIN+1 MAX MAX 3/MIN+1/MAX
+MIN+1 MAX MIN 0
+MIN+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN -1 2/MIN+1/MIN
+MIN+1 MIN 1 0
+MIN+1 MIN -2 1/MIN+1/MIN+1
+MIN+1 MIN 2 0
+MIN+1 MIN -3 1/MIN+1/MIN+1
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 1/MIN+1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 0 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to 0 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX 0 1 0
+MAX 0 -2 1073741824/MAX/1
+MAX 0 2 0
+MAX 0 -3 715827883/MAX/1
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 2/MAX/0
+MAX 0 MAX 0
+MAX 0 MIN 1/MAX/MAX
+MAX -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX -1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -1 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX -1 1 0
+MAX -1 -2 1073741825/MAX/-1
+MAX -1 2 0
+MAX -1 -3 715827883/MAX/1
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 2/MAX/0
+MAX -1 MAX 0
+MAX -1 MIN 2/MAX/-1
+MAX 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 1 -1 MAX/MAX/1
+MAX 1 1 0
+MAX 1 -2 1073741824/MAX/1
+MAX 1 2 0
+MAX 1 -3 715827883/MAX/1
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 1/MAX/MAX
+MAX 1 MAX 0
+MAX 1 MIN 1/MAX/MAX
+MAX 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 3 -1 MAX-2/MAX/3
+MAX 3 1 0
+MAX 3 -2 1073741823/MAX/3
+MAX 3 2 0
+MAX 3 -3 715827882/MAX/4
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 1/MAX/MAX
+MAX 3 MAX 0
+MAX 3 MIN 1/MAX/MAX
+MAX MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 1 0
+MAX MIN+1 -2 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483647 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 2 0
+MAX MIN+1 -3 1431655765/MAX/MIN+3
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 3/MAX/MIN+1
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 2/MAX/-1
+MAX MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MAX -1 1/MAX/MAX
+MAX MAX 1 1/MAX/MAX
+MAX MAX -2 1/MAX/MAX
+MAX MAX 2 1/MAX/MAX
+MAX MAX -3 1/MAX/MAX
+MAX MAX 3 1/MAX/MAX
+MAX MAX 17 1/MAX/MAX
+MAX MAX 127 1/MAX/MAX
+MAX MAX MIN+1 1/MAX/MAX
+MAX MAX MAX 1/MAX/MAX
+MAX MAX MIN 1/MAX/MAX
+MAX MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN -1 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 1 0
+MAX MIN -2 ---
+ java.lang.IllegalArgumentException: 2147483647 to -2147483648 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 2 0
+MAX MIN -3 1431655766/MAX/MIN
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 3/MAX/MIN+1
+MAX MIN MAX 0
+MAX MIN MIN 2/MAX/-1
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 0 -1 0
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 0
+MIN 0 2 1073741825/MIN/0
+MIN 0 -3 0
+MIN 0 3 715827883/MIN/-2
+MIN 0 17 126322568/MIN/-9
+MIN 0 127 16909321/MIN/-8
+MIN 0 MIN+1 0
+MIN 0 MAX 2/MIN/-1
+MIN 0 MIN 0
+MIN -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN -1 -1 0
+MIN -1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to -1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 -2 0
+MIN -1 2 1073741824/MIN/-2
+MIN -1 -3 0
+MIN -1 3 715827883/MIN/-2
+MIN -1 17 126322568/MIN/-9
+MIN -1 127 16909321/MIN/-8
+MIN -1 MIN+1 0
+MIN -1 MAX 2/MIN/-1
+MIN -1 MIN 0
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 1 -1 0
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 0
+MIN 1 2 1073741825/MIN/0
+MIN 1 -3 0
+MIN 1 3 715827884/MIN/1
+MIN 1 17 126322568/MIN/-9
+MIN 1 127 16909321/MIN/-8
+MIN 1 MIN+1 0
+MIN 1 MAX 2/MIN/-1
+MIN 1 MIN 0
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 3 -1 0
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 0
+MIN 3 2 1073741826/MIN/2
+MIN 3 -3 0
+MIN 3 3 715827884/MIN/1
+MIN 3 17 126322568/MIN/-9
+MIN 3 127 16909321/MIN/-8
+MIN 3 MIN+1 0
+MIN 3 MAX 2/MIN/-1
+MIN 3 MIN 0
+MIN MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN+1 -1 0
+MIN MIN+1 1 2/MIN/MIN+1
+MIN MIN+1 -2 0
+MIN MIN+1 2 1/MIN/MIN
+MIN MIN+1 -3 0
+MIN MIN+1 3 1/MIN/MIN
+MIN MIN+1 17 1/MIN/MIN
+MIN MIN+1 127 1/MIN/MIN
+MIN MIN+1 MIN+1 0
+MIN MIN+1 MAX 1/MIN/MIN
+MIN MIN+1 MIN 0
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MAX -1 0
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 0
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 to 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 0
+MIN MAX 3 1431655766/MIN/MAX
+MIN MAX 17 252645136/MIN/MAX
+MIN MAX 127 33818641/MIN/MAX-15
+MIN MAX MIN+1 0
+MIN MAX MAX 3/MIN/MAX-1
+MIN MAX MIN 0
+MIN MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN -1 1/MIN/MIN
+MIN MIN 1 1/MIN/MIN
+MIN MIN -2 1/MIN/MIN
+MIN MIN 2 1/MIN/MIN
+MIN MIN -3 1/MIN/MIN
+MIN MIN 3 1/MIN/MIN
+MIN MIN 17 1/MIN/MIN
+MIN MIN 127 1/MIN/MIN
+MIN MIN MIN+1 1/MIN/MIN
+MIN MIN MAX 1/MIN/MIN
+MIN MIN MIN 1/MIN/MIN
+
+>>> start until end <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 0
+0 0 -1 0
+0 0 1 0
+0 0 -2 0
+0 0 2 0
+0 0 -3 0
+0 0 3 0
+0 0 17 0
+0 0 127 0
+0 0 MIN+1 0
+0 0 MAX 0
+0 0 MIN 0
+0 -1 0 0
+0 -1 -1 0
+0 -1 1 0
+0 -1 -2 0
+0 -1 2 0
+0 -1 -3 0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 0
+0 -1 MAX 0
+0 -1 MIN 0
+0 1 0 1/0/0
+0 1 -1 1/0/0
+0 1 1 1/0/0
+0 1 -2 1/0/0
+0 1 2 1/0/0
+0 1 -3 1/0/0
+0 1 3 1/0/0
+0 1 17 1/0/0
+0 1 127 1/0/0
+0 1 MIN+1 1/0/0
+0 1 MAX 1/0/0
+0 1 MIN 1/0/0
+0 3 0 3/0/2
+0 3 -1 3/0/2
+0 3 1 3/0/2
+0 3 -2 3/0/2
+0 3 2 3/0/2
+0 3 -3 3/0/2
+0 3 3 3/0/2
+0 3 17 3/0/2
+0 3 127 3/0/2
+0 3 MIN+1 3/0/2
+0 3 MAX 3/0/2
+0 3 MIN 3/0/2
+0 MIN+1 0 0
+0 MIN+1 -1 0
+0 MIN+1 1 0
+0 MIN+1 -2 0
+0 MIN+1 2 0
+0 MIN+1 -3 0
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 0
+0 MIN+1 MAX 0
+0 MIN+1 MIN 0
+0 MAX 0 MAX/0/MAX-1
+0 MAX -1 MAX/0/MAX-1
+0 MAX 1 MAX/0/MAX-1
+0 MAX -2 MAX/0/MAX-1
+0 MAX 2 MAX/0/MAX-1
+0 MAX -3 MAX/0/MAX-1
+0 MAX 3 MAX/0/MAX-1
+0 MAX 17 MAX/0/MAX-1
+0 MAX 127 MAX/0/MAX-1
+0 MAX MIN+1 MAX/0/MAX-1
+0 MAX MAX MAX/0/MAX-1
+0 MAX MIN MAX/0/MAX-1
+0 MIN 0 0
+0 MIN -1 0
+0 MIN 1 0
+0 MIN -2 0
+0 MIN 2 0
+0 MIN -3 0
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 0
+0 MIN MAX 0
+0 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 1/-1/-1
+-1 0 -1 1/-1/-1
+-1 0 1 1/-1/-1
+-1 0 -2 1/-1/-1
+-1 0 2 1/-1/-1
+-1 0 -3 1/-1/-1
+-1 0 3 1/-1/-1
+-1 0 17 1/-1/-1
+-1 0 127 1/-1/-1
+-1 0 MIN+1 1/-1/-1
+-1 0 MAX 1/-1/-1
+-1 0 MIN 1/-1/-1
+-1 -1 0 0
+-1 -1 -1 0
+-1 -1 1 0
+-1 -1 -2 0
+-1 -1 2 0
+-1 -1 -3 0
+-1 -1 3 0
+-1 -1 17 0
+-1 -1 127 0
+-1 -1 MIN+1 0
+-1 -1 MAX 0
+-1 -1 MIN 0
+-1 1 0 2/-1/0
+-1 1 -1 2/-1/0
+-1 1 1 2/-1/0
+-1 1 -2 2/-1/0
+-1 1 2 2/-1/0
+-1 1 -3 2/-1/0
+-1 1 3 2/-1/0
+-1 1 17 2/-1/0
+-1 1 127 2/-1/0
+-1 1 MIN+1 2/-1/0
+-1 1 MAX 2/-1/0
+-1 1 MIN 2/-1/0
+-1 3 0 4/-1/2
+-1 3 -1 4/-1/2
+-1 3 1 4/-1/2
+-1 3 -2 4/-1/2
+-1 3 2 4/-1/2
+-1 3 -3 4/-1/2
+-1 3 3 4/-1/2
+-1 3 17 4/-1/2
+-1 3 127 4/-1/2
+-1 3 MIN+1 4/-1/2
+-1 3 MAX 4/-1/2
+-1 3 MIN 4/-1/2
+-1 MIN+1 0 0
+-1 MIN+1 -1 0
+-1 MIN+1 1 0
+-1 MIN+1 -2 0
+-1 MIN+1 2 0
+-1 MIN+1 -3 0
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 0
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 0
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -1 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 2 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -3 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 3 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 17 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX 127 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MAX ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX MIN ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MIN 0 0
+-1 MIN -1 0
+-1 MIN 1 0
+-1 MIN -2 0
+-1 MIN 2 0
+-1 MIN -3 0
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 0
+-1 MIN MAX 0
+-1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 0
+1 0 -1 0
+1 0 1 0
+1 0 -2 0
+1 0 2 0
+1 0 -3 0
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 0
+1 0 MAX 0
+1 0 MIN 0
+1 -1 0 0
+1 -1 -1 0
+1 -1 1 0
+1 -1 -2 0
+1 -1 2 0
+1 -1 -3 0
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 0
+1 -1 MAX 0
+1 -1 MIN 0
+1 1 0 0
+1 1 -1 0
+1 1 1 0
+1 1 -2 0
+1 1 2 0
+1 1 -3 0
+1 1 3 0
+1 1 17 0
+1 1 127 0
+1 1 MIN+1 0
+1 1 MAX 0
+1 1 MIN 0
+1 3 0 2/1/2
+1 3 -1 2/1/2
+1 3 1 2/1/2
+1 3 -2 2/1/2
+1 3 2 2/1/2
+1 3 -3 2/1/2
+1 3 3 2/1/2
+1 3 17 2/1/2
+1 3 127 2/1/2
+1 3 MIN+1 2/1/2
+1 3 MAX 2/1/2
+1 3 MIN 2/1/2
+1 MIN+1 0 0
+1 MIN+1 -1 0
+1 MIN+1 1 0
+1 MIN+1 -2 0
+1 MIN+1 2 0
+1 MIN+1 -3 0
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 0
+1 MIN+1 MAX 0
+1 MIN+1 MIN 0
+1 MAX 0 MAX-1/1/MAX-1
+1 MAX -1 MAX-1/1/MAX-1
+1 MAX 1 MAX-1/1/MAX-1
+1 MAX -2 MAX-1/1/MAX-1
+1 MAX 2 MAX-1/1/MAX-1
+1 MAX -3 MAX-1/1/MAX-1
+1 MAX 3 MAX-1/1/MAX-1
+1 MAX 17 MAX-1/1/MAX-1
+1 MAX 127 MAX-1/1/MAX-1
+1 MAX MIN+1 MAX-1/1/MAX-1
+1 MAX MAX MAX-1/1/MAX-1
+1 MAX MIN MAX-1/1/MAX-1
+1 MIN 0 0
+1 MIN -1 0
+1 MIN 1 0
+1 MIN -2 0
+1 MIN 2 0
+1 MIN -3 0
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 0
+1 MIN MAX 0
+1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 0
+3 0 -1 0
+3 0 1 0
+3 0 -2 0
+3 0 2 0
+3 0 -3 0
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 0
+3 0 MAX 0
+3 0 MIN 0
+3 -1 0 0
+3 -1 -1 0
+3 -1 1 0
+3 -1 -2 0
+3 -1 2 0
+3 -1 -3 0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 0
+3 -1 MAX 0
+3 -1 MIN 0
+3 1 0 0
+3 1 -1 0
+3 1 1 0
+3 1 -2 0
+3 1 2 0
+3 1 -3 0
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 0
+3 1 MAX 0
+3 1 MIN 0
+3 3 0 0
+3 3 -1 0
+3 3 1 0
+3 3 -2 0
+3 3 2 0
+3 3 -3 0
+3 3 3 0
+3 3 17 0
+3 3 127 0
+3 3 MIN+1 0
+3 3 MAX 0
+3 3 MIN 0
+3 MIN+1 0 0
+3 MIN+1 -1 0
+3 MIN+1 1 0
+3 MIN+1 -2 0
+3 MIN+1 2 0
+3 MIN+1 -3 0
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 0
+3 MIN+1 MAX 0
+3 MIN+1 MIN 0
+3 MAX 0 MAX-3/3/MAX-1
+3 MAX -1 MAX-3/3/MAX-1
+3 MAX 1 MAX-3/3/MAX-1
+3 MAX -2 MAX-3/3/MAX-1
+3 MAX 2 MAX-3/3/MAX-1
+3 MAX -3 MAX-3/3/MAX-1
+3 MAX 3 MAX-3/3/MAX-1
+3 MAX 17 MAX-3/3/MAX-1
+3 MAX 127 MAX-3/3/MAX-1
+3 MAX MIN+1 MAX-3/3/MAX-1
+3 MAX MAX MAX-3/3/MAX-1
+3 MAX MIN MAX-3/3/MAX-1
+3 MIN 0 0
+3 MIN -1 0
+3 MIN 1 0
+3 MIN -2 0
+3 MIN 2 0
+3 MIN -3 0
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 0
+3 MIN MAX 0
+3 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 MAX/MIN+1/-1
+MIN+1 0 -1 MAX/MIN+1/-1
+MIN+1 0 1 MAX/MIN+1/-1
+MIN+1 0 -2 MAX/MIN+1/-1
+MIN+1 0 2 MAX/MIN+1/-1
+MIN+1 0 -3 MAX/MIN+1/-1
+MIN+1 0 3 MAX/MIN+1/-1
+MIN+1 0 17 MAX/MIN+1/-1
+MIN+1 0 127 MAX/MIN+1/-1
+MIN+1 0 MIN+1 MAX/MIN+1/-1
+MIN+1 0 MAX MAX/MIN+1/-1
+MIN+1 0 MIN MAX/MIN+1/-1
+MIN+1 -1 0 MAX-1/MIN+1/-2
+MIN+1 -1 -1 MAX-1/MIN+1/-2
+MIN+1 -1 1 MAX-1/MIN+1/-2
+MIN+1 -1 -2 MAX-1/MIN+1/-2
+MIN+1 -1 2 MAX-1/MIN+1/-2
+MIN+1 -1 -3 MAX-1/MIN+1/-2
+MIN+1 -1 3 MAX-1/MIN+1/-2
+MIN+1 -1 17 MAX-1/MIN+1/-2
+MIN+1 -1 127 MAX-1/MIN+1/-2
+MIN+1 -1 MIN+1 MAX-1/MIN+1/-2
+MIN+1 -1 MAX MAX-1/MIN+1/-2
+MIN+1 -1 MIN MAX-1/MIN+1/-2
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 17 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 127 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MAX ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 MIN ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 17 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 127 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MAX ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 MIN ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MIN+1 0 0
+MIN+1 MIN+1 -1 0
+MIN+1 MIN+1 1 0
+MIN+1 MIN+1 -2 0
+MIN+1 MIN+1 2 0
+MIN+1 MIN+1 -3 0
+MIN+1 MIN+1 3 0
+MIN+1 MIN+1 17 0
+MIN+1 MIN+1 127 0
+MIN+1 MIN+1 MIN+1 0
+MIN+1 MIN+1 MAX 0
+MIN+1 MIN+1 MIN 0
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 3 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 17 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX 127 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MAX ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX MIN ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MIN 0 0
+MIN+1 MIN -1 0
+MIN+1 MIN 1 0
+MIN+1 MIN -2 0
+MIN+1 MIN 2 0
+MIN+1 MIN -3 0
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 0
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 0
+MAX 0 -1 0
+MAX 0 1 0
+MAX 0 -2 0
+MAX 0 2 0
+MAX 0 -3 0
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 0
+MAX 0 MAX 0
+MAX 0 MIN 0
+MAX -1 0 0
+MAX -1 -1 0
+MAX -1 1 0
+MAX -1 -2 0
+MAX -1 2 0
+MAX -1 -3 0
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 0
+MAX -1 MAX 0
+MAX -1 MIN 0
+MAX 1 0 0
+MAX 1 -1 0
+MAX 1 1 0
+MAX 1 -2 0
+MAX 1 2 0
+MAX 1 -3 0
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 0
+MAX 1 MAX 0
+MAX 1 MIN 0
+MAX 3 0 0
+MAX 3 -1 0
+MAX 3 1 0
+MAX 3 -2 0
+MAX 3 2 0
+MAX 3 -3 0
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 0
+MAX 3 MAX 0
+MAX 3 MIN 0
+MAX MIN+1 0 0
+MAX MIN+1 -1 0
+MAX MIN+1 1 0
+MAX MIN+1 -2 0
+MAX MIN+1 2 0
+MAX MIN+1 -3 0
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 0
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 0
+MAX MAX 0 0
+MAX MAX -1 0
+MAX MAX 1 0
+MAX MAX -2 0
+MAX MAX 2 0
+MAX MAX -3 0
+MAX MAX 3 0
+MAX MAX 17 0
+MAX MAX 127 0
+MAX MAX MIN+1 0
+MAX MAX MAX 0
+MAX MAX MIN 0
+MAX MIN 0 0
+MAX MIN -1 0
+MAX MIN 1 0
+MAX MIN -2 0
+MAX MIN 2 0
+MAX MIN -3 0
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 0
+MAX MIN MAX 0
+MAX MIN MIN 0
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 17 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 127 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN -1 0 MAX/MIN/-2
+MIN -1 -1 MAX/MIN/-2
+MIN -1 1 MAX/MIN/-2
+MIN -1 -2 MAX/MIN/-2
+MIN -1 2 MAX/MIN/-2
+MIN -1 -3 MAX/MIN/-2
+MIN -1 3 MAX/MIN/-2
+MIN -1 17 MAX/MIN/-2
+MIN -1 127 MAX/MIN/-2
+MIN -1 MIN+1 MAX/MIN/-2
+MIN -1 MAX MAX/MIN/-2
+MIN -1 MIN MAX/MIN/-2
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 17 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 127 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 17 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 127 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MAX ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 MIN ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MIN+1 0 1/MIN/MIN
+MIN MIN+1 -1 1/MIN/MIN
+MIN MIN+1 1 1/MIN/MIN
+MIN MIN+1 -2 1/MIN/MIN
+MIN MIN+1 2 1/MIN/MIN
+MIN MIN+1 -3 1/MIN/MIN
+MIN MIN+1 3 1/MIN/MIN
+MIN MIN+1 17 1/MIN/MIN
+MIN MIN+1 127 1/MIN/MIN
+MIN MIN+1 MIN+1 1/MIN/MIN
+MIN MIN+1 MAX 1/MIN/MIN
+MIN MIN+1 MIN 1/MIN/MIN
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 3 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 17 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX 127 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MIN+1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MAX ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX MIN ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MIN 0 0
+MIN MIN -1 0
+MIN MIN 1 0
+MIN MIN -2 0
+MIN MIN 2 0
+MIN MIN -3 0
+MIN MIN 3 0
+MIN MIN 17 0
+MIN MIN 127 0
+MIN MIN MIN+1 0
+MIN MIN MAX 0
+MIN MIN MIN 0
+
+>>> start until end by step <<<
+
+start end step length/first/last
+-----------------------------------------
+0 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 0 -1 0
+0 0 1 0
+0 0 -2 0
+0 0 2 0
+0 0 -3 0
+0 0 3 0
+0 0 17 0
+0 0 127 0
+0 0 MIN+1 0
+0 0 MAX 0
+0 0 MIN 0
+0 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 -1 -1 1/0/0
+0 -1 1 0
+0 -1 -2 1/0/0
+0 -1 2 0
+0 -1 -3 1/0/0
+0 -1 3 0
+0 -1 17 0
+0 -1 127 0
+0 -1 MIN+1 1/0/0
+0 -1 MAX 0
+0 -1 MIN 1/0/0
+0 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 1 -1 0
+0 1 1 1/0/0
+0 1 -2 0
+0 1 2 1/0/0
+0 1 -3 0
+0 1 3 1/0/0
+0 1 17 1/0/0
+0 1 127 1/0/0
+0 1 MIN+1 0
+0 1 MAX 1/0/0
+0 1 MIN 0
+0 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 3 -1 0
+0 3 1 3/0/2
+0 3 -2 0
+0 3 2 2/0/2
+0 3 -3 0
+0 3 3 1/0/0
+0 3 17 1/0/0
+0 3 127 1/0/0
+0 3 MIN+1 0
+0 3 MAX 1/0/0
+0 3 MIN 0
+0 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN+1 -1 MAX/0/MIN+2
+0 MIN+1 1 0
+0 MIN+1 -2 1073741824/0/MIN+2
+0 MIN+1 2 0
+0 MIN+1 -3 715827883/0/MIN+2
+0 MIN+1 3 0
+0 MIN+1 17 0
+0 MIN+1 127 0
+0 MIN+1 MIN+1 1/0/0
+0 MIN+1 MAX 0
+0 MIN+1 MIN 1/0/0
+0 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MAX -1 0
+0 MAX 1 MAX/0/MAX-1
+0 MAX -2 0
+0 MAX 2 1073741824/0/MAX-1
+0 MAX -3 0
+0 MAX 3 715827883/0/MAX-1
+0 MAX 17 126322568/0/MAX-8
+0 MAX 127 16909321/0/MAX-7
+0 MAX MIN+1 0
+0 MAX MAX 1/0/0
+0 MAX MIN 0
+0 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+0 MIN -1 ---
+ java.lang.IllegalArgumentException: 0 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+0 MIN 1 0
+0 MIN -2 1073741824/0/MIN+2
+0 MIN 2 0
+0 MIN -3 715827883/0/MIN+2
+0 MIN 3 0
+0 MIN 17 0
+0 MIN 127 0
+0 MIN MIN+1 2/0/MIN+1
+0 MIN MAX 0
+0 MIN MIN 1/0/0
+
+start end step length/first/last
+-----------------------------------------
+-1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 0 -1 0
+-1 0 1 1/-1/-1
+-1 0 -2 0
+-1 0 2 1/-1/-1
+-1 0 -3 0
+-1 0 3 1/-1/-1
+-1 0 17 1/-1/-1
+-1 0 127 1/-1/-1
+-1 0 MIN+1 0
+-1 0 MAX 1/-1/-1
+-1 0 MIN 0
+-1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 -1 -1 0
+-1 -1 1 0
+-1 -1 -2 0
+-1 -1 2 0
+-1 -1 -3 0
+-1 -1 3 0
+-1 -1 17 0
+-1 -1 127 0
+-1 -1 MIN+1 0
+-1 -1 MAX 0
+-1 -1 MIN 0
+-1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 1 -1 0
+-1 1 1 2/-1/0
+-1 1 -2 0
+-1 1 2 1/-1/-1
+-1 1 -3 0
+-1 1 3 1/-1/-1
+-1 1 17 1/-1/-1
+-1 1 127 1/-1/-1
+-1 1 MIN+1 0
+-1 1 MAX 1/-1/-1
+-1 1 MIN 0
+-1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 3 -1 0
+-1 3 1 4/-1/2
+-1 3 -2 0
+-1 3 2 2/-1/1
+-1 3 -3 0
+-1 3 3 2/-1/2
+-1 3 17 1/-1/-1
+-1 3 127 1/-1/-1
+-1 3 MIN+1 0
+-1 3 MAX 1/-1/-1
+-1 3 MIN 0
+-1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN+1 -1 MAX-1/-1/MIN+2
+-1 MIN+1 1 0
+-1 MIN+1 -2 1073741823/-1/MIN+3
+-1 MIN+1 2 0
+-1 MIN+1 -3 715827882/-1/MIN+4
+-1 MIN+1 3 0
+-1 MIN+1 17 0
+-1 MIN+1 127 0
+-1 MIN+1 MIN+1 1/-1/-1
+-1 MIN+1 MAX 0
+-1 MIN+1 MIN 1/-1/-1
+-1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MAX -1 0
+-1 MAX 1 ---
+ java.lang.IllegalArgumentException: -1 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+-1 MAX -2 0
+-1 MAX 2 1073741824/-1/MAX-2
+-1 MAX -3 0
+-1 MAX 3 715827883/-1/MAX-2
+-1 MAX 17 126322568/-1/MAX-9
+-1 MAX 127 16909321/-1/MAX-8
+-1 MAX MIN+1 0
+-1 MAX MAX 2/-1/MAX-1
+-1 MAX MIN 0
+-1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+-1 MIN -1 MAX/-1/MIN+1
+-1 MIN 1 0
+-1 MIN -2 1073741824/-1/MIN+1
+-1 MIN 2 0
+-1 MIN -3 715827883/-1/MIN+1
+-1 MIN 3 0
+-1 MIN 17 0
+-1 MIN 127 0
+-1 MIN MIN+1 1/-1/-1
+-1 MIN MAX 0
+-1 MIN MIN 1/-1/-1
+
+start end step length/first/last
+-----------------------------------------
+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 0 -1 1/1/1
+1 0 1 0
+1 0 -2 1/1/1
+1 0 2 0
+1 0 -3 1/1/1
+1 0 3 0
+1 0 17 0
+1 0 127 0
+1 0 MIN+1 1/1/1
+1 0 MAX 0
+1 0 MIN 1/1/1
+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 -1 -1 2/1/0
+1 -1 1 0
+1 -1 -2 1/1/1
+1 -1 2 0
+1 -1 -3 1/1/1
+1 -1 3 0
+1 -1 17 0
+1 -1 127 0
+1 -1 MIN+1 1/1/1
+1 -1 MAX 0
+1 -1 MIN 1/1/1
+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 1 -1 0
+1 1 1 0
+1 1 -2 0
+1 1 2 0
+1 1 -3 0
+1 1 3 0
+1 1 17 0
+1 1 127 0
+1 1 MIN+1 0
+1 1 MAX 0
+1 1 MIN 0
+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 3 -1 0
+1 3 1 2/1/2
+1 3 -2 0
+1 3 2 1/1/1
+1 3 -3 0
+1 3 3 1/1/1
+1 3 17 1/1/1
+1 3 127 1/1/1
+1 3 MIN+1 0
+1 3 MAX 1/1/1
+1 3 MIN 0
+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 1 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN+1 1 0
+1 MIN+1 -2 1073741824/1/MIN+3
+1 MIN+1 2 0
+1 MIN+1 -3 715827883/1/MIN+3
+1 MIN+1 3 0
+1 MIN+1 17 0
+1 MIN+1 127 0
+1 MIN+1 MIN+1 2/1/MIN+2
+1 MIN+1 MAX 0
+1 MIN+1 MIN 1/1/1
+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MAX -1 0
+1 MAX 1 MAX-1/1/MAX-1
+1 MAX -2 0
+1 MAX 2 1073741823/1/MAX-2
+1 MAX -3 0
+1 MAX 3 715827882/1/MAX-3
+1 MAX 17 126322568/1/MAX-7
+1 MAX 127 16909321/1/MAX-6
+1 MAX MIN+1 0
+1 MAX MAX 1/1/1
+1 MAX MIN 0
+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+1 MIN -1 ---
+ java.lang.IllegalArgumentException: 1 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+1 MIN 1 0
+1 MIN -2 1073741825/1/MIN+1
+1 MIN 2 0
+1 MIN -3 715827883/1/MIN+3
+1 MIN 3 0
+1 MIN 17 0
+1 MIN 127 0
+1 MIN MIN+1 2/1/MIN+2
+1 MIN MAX 0
+1 MIN MIN 2/1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+3 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 0 -1 3/3/1
+3 0 1 0
+3 0 -2 2/3/1
+3 0 2 0
+3 0 -3 1/3/3
+3 0 3 0
+3 0 17 0
+3 0 127 0
+3 0 MIN+1 1/3/3
+3 0 MAX 0
+3 0 MIN 1/3/3
+3 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 -1 -1 4/3/0
+3 -1 1 0
+3 -1 -2 2/3/1
+3 -1 2 0
+3 -1 -3 2/3/0
+3 -1 3 0
+3 -1 17 0
+3 -1 127 0
+3 -1 MIN+1 1/3/3
+3 -1 MAX 0
+3 -1 MIN 1/3/3
+3 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 1 -1 2/3/2
+3 1 1 0
+3 1 -2 1/3/3
+3 1 2 0
+3 1 -3 1/3/3
+3 1 3 0
+3 1 17 0
+3 1 127 0
+3 1 MIN+1 1/3/3
+3 1 MAX 0
+3 1 MIN 1/3/3
+3 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 3 -1 0
+3 3 1 0
+3 3 -2 0
+3 3 2 0
+3 3 -3 0
+3 3 3 0
+3 3 17 0
+3 3 127 0
+3 3 MIN+1 0
+3 3 MAX 0
+3 3 MIN 0
+3 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 3 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN+1 1 0
+3 MIN+1 -2 1073741825/3/MIN+3
+3 MIN+1 2 0
+3 MIN+1 -3 715827884/3/MIN+2
+3 MIN+1 3 0
+3 MIN+1 17 0
+3 MIN+1 127 0
+3 MIN+1 MIN+1 2/3/MIN+4
+3 MIN+1 MAX 0
+3 MIN+1 MIN 2/3/MIN+3
+3 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MAX -1 0
+3 MAX 1 MAX-3/3/MAX-1
+3 MAX -2 0
+3 MAX 2 1073741822/3/MAX-2
+3 MAX -3 0
+3 MAX 3 715827882/3/MAX-1
+3 MAX 17 126322568/3/MAX-5
+3 MAX 127 16909321/3/MAX-4
+3 MAX MIN+1 0
+3 MAX MAX 1/3/3
+3 MAX MIN 0
+3 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+3 MIN -1 ---
+ java.lang.IllegalArgumentException: 3 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+3 MIN 1 0
+3 MIN -2 1073741826/3/MIN+1
+3 MIN 2 0
+3 MIN -3 715827884/3/MIN+2
+3 MIN 3 0
+3 MIN 17 0
+3 MIN 127 0
+3 MIN MIN+1 2/3/MIN+4
+3 MIN MAX 0
+3 MIN MIN 2/3/MIN+3
+
+start end step length/first/last
+-----------------------------------------
+MIN+1 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 0 -1 0
+MIN+1 0 1 MAX/MIN+1/-1
+MIN+1 0 -2 0
+MIN+1 0 2 1073741824/MIN+1/-1
+MIN+1 0 -3 0
+MIN+1 0 3 715827883/MIN+1/-1
+MIN+1 0 17 126322568/MIN+1/-8
+MIN+1 0 127 16909321/MIN+1/-7
+MIN+1 0 MIN+1 0
+MIN+1 0 MAX 1/MIN+1/MIN+1
+MIN+1 0 MIN 0
+MIN+1 -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 -1 -1 0
+MIN+1 -1 1 MAX-1/MIN+1/-2
+MIN+1 -1 -2 0
+MIN+1 -1 2 1073741823/MIN+1/-3
+MIN+1 -1 -3 0
+MIN+1 -1 3 715827882/MIN+1/-4
+MIN+1 -1 17 126322568/MIN+1/-8
+MIN+1 -1 127 16909321/MIN+1/-7
+MIN+1 -1 MIN+1 0
+MIN+1 -1 MAX 1/MIN+1/MIN+1
+MIN+1 -1 MIN 0
+MIN+1 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 1 -1 0
+MIN+1 1 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 1 -2 0
+MIN+1 1 2 1073741824/MIN+1/-1
+MIN+1 1 -3 0
+MIN+1 1 3 715827883/MIN+1/-1
+MIN+1 1 17 126322568/MIN+1/-8
+MIN+1 1 127 16909321/MIN+1/-7
+MIN+1 1 MIN+1 0
+MIN+1 1 MAX 2/MIN+1/0
+MIN+1 1 MIN 0
+MIN+1 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 3 -1 0
+MIN+1 3 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 3 -2 0
+MIN+1 3 2 1073741825/MIN+1/1
+MIN+1 3 -3 0
+MIN+1 3 3 715827884/MIN+1/2
+MIN+1 3 17 126322568/MIN+1/-8
+MIN+1 3 127 16909321/MIN+1/-7
+MIN+1 3 MIN+1 0
+MIN+1 3 MAX 2/MIN+1/0
+MIN+1 3 MIN 0
+MIN+1 MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN+1 -1 0
+MIN+1 MIN+1 1 0
+MIN+1 MIN+1 -2 0
+MIN+1 MIN+1 2 0
+MIN+1 MIN+1 -3 0
+MIN+1 MIN+1 3 0
+MIN+1 MIN+1 17 0
+MIN+1 MIN+1 127 0
+MIN+1 MIN+1 MIN+1 0
+MIN+1 MIN+1 MAX 0
+MIN+1 MIN+1 MIN 0
+MIN+1 MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MAX -1 0
+MIN+1 MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483647 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN+1 MAX -2 0
+MIN+1 MAX 2 MAX/MIN+1/MAX-2
+MIN+1 MAX -3 0
+MIN+1 MAX 3 1431655765/MIN+1/MAX-2
+MIN+1 MAX 17 252645135/MIN+1/MAX-16
+MIN+1 MAX 127 33818641/MIN+1/MAX-14
+MIN+1 MAX MIN+1 0
+MIN+1 MAX MAX 2/MIN+1/0
+MIN+1 MAX MIN 0
+MIN+1 MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN+1 MIN -1 1/MIN+1/MIN+1
+MIN+1 MIN 1 0
+MIN+1 MIN -2 1/MIN+1/MIN+1
+MIN+1 MIN 2 0
+MIN+1 MIN -3 1/MIN+1/MIN+1
+MIN+1 MIN 3 0
+MIN+1 MIN 17 0
+MIN+1 MIN 127 0
+MIN+1 MIN MIN+1 1/MIN+1/MIN+1
+MIN+1 MIN MAX 0
+MIN+1 MIN MIN 1/MIN+1/MIN+1
+
+start end step length/first/last
+-----------------------------------------
+MAX 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 0 -1 MAX/MAX/1
+MAX 0 1 0
+MAX 0 -2 1073741824/MAX/1
+MAX 0 2 0
+MAX 0 -3 715827883/MAX/1
+MAX 0 3 0
+MAX 0 17 0
+MAX 0 127 0
+MAX 0 MIN+1 1/MAX/MAX
+MAX 0 MAX 0
+MAX 0 MIN 1/MAX/MAX
+MAX -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX -1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -1 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX -1 1 0
+MAX -1 -2 1073741824/MAX/1
+MAX -1 2 0
+MAX -1 -3 715827883/MAX/1
+MAX -1 3 0
+MAX -1 17 0
+MAX -1 127 0
+MAX -1 MIN+1 2/MAX/0
+MAX -1 MAX 0
+MAX -1 MIN 1/MAX/MAX
+MAX 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 1 -1 MAX-1/MAX/2
+MAX 1 1 0
+MAX 1 -2 1073741823/MAX/3
+MAX 1 2 0
+MAX 1 -3 715827882/MAX/4
+MAX 1 3 0
+MAX 1 17 0
+MAX 1 127 0
+MAX 1 MIN+1 1/MAX/MAX
+MAX 1 MAX 0
+MAX 1 MIN 1/MAX/MAX
+MAX 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX 3 -1 MAX-3/MAX/4
+MAX 3 1 0
+MAX 3 -2 1073741822/MAX/5
+MAX 3 2 0
+MAX 3 -3 715827882/MAX/4
+MAX 3 3 0
+MAX 3 17 0
+MAX 3 127 0
+MAX 3 MIN+1 1/MAX/MAX
+MAX 3 MAX 0
+MAX 3 MIN 1/MAX/MAX
+MAX MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN+1 -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483647 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN+1 1 0
+MAX MIN+1 -2 MAX/MAX/MIN+3
+MAX MIN+1 2 0
+MAX MIN+1 -3 1431655765/MAX/MIN+3
+MAX MIN+1 3 0
+MAX MIN+1 17 0
+MAX MIN+1 127 0
+MAX MIN+1 MIN+1 2/MAX/0
+MAX MIN+1 MAX 0
+MAX MIN+1 MIN 2/MAX/-1
+MAX MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MAX -1 0
+MAX MAX 1 0
+MAX MAX -2 0
+MAX MAX 2 0
+MAX MAX -3 0
+MAX MAX 3 0
+MAX MAX 17 0
+MAX MAX 127 0
+MAX MAX MIN+1 0
+MAX MAX MAX 0
+MAX MAX MIN 0
+MAX MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MAX MIN -1 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483648 by -1: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 1 0
+MAX MIN -2 ---
+ java.lang.IllegalArgumentException: 2147483647 until -2147483648 by -2: seqs cannot contain more than Int.MaxValue elements.
+MAX MIN 2 0
+MAX MIN -3 1431655765/MAX/MIN+3
+MAX MIN 3 0
+MAX MIN 17 0
+MAX MIN 127 0
+MAX MIN MIN+1 3/MAX/MIN+1
+MAX MIN MAX 0
+MAX MIN MIN 2/MAX/-1
+
+start end step length/first/last
+-----------------------------------------
+MIN 0 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 0 -1 0
+MIN 0 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 0 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 0 -2 0
+MIN 0 2 1073741824/MIN/-2
+MIN 0 -3 0
+MIN 0 3 715827883/MIN/-2
+MIN 0 17 126322568/MIN/-9
+MIN 0 127 16909321/MIN/-8
+MIN 0 MIN+1 0
+MIN 0 MAX 2/MIN/-1
+MIN 0 MIN 0
+MIN -1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN -1 -1 0
+MIN -1 1 MAX/MIN/-2
+MIN -1 -2 0
+MIN -1 2 1073741824/MIN/-2
+MIN -1 -3 0
+MIN -1 3 715827883/MIN/-2
+MIN -1 17 126322568/MIN/-9
+MIN -1 127 16909321/MIN/-8
+MIN -1 MIN+1 0
+MIN -1 MAX 1/MIN/MIN
+MIN -1 MIN 0
+MIN 1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 1 -1 0
+MIN 1 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 1 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 1 -2 0
+MIN 1 2 1073741825/MIN/0
+MIN 1 -3 0
+MIN 1 3 715827883/MIN/-2
+MIN 1 17 126322568/MIN/-9
+MIN 1 127 16909321/MIN/-8
+MIN 1 MIN+1 0
+MIN 1 MAX 2/MIN/-1
+MIN 1 MIN 0
+MIN 3 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN 3 -1 0
+MIN 3 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 3 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN 3 -2 0
+MIN 3 2 1073741826/MIN/2
+MIN 3 -3 0
+MIN 3 3 715827884/MIN/1
+MIN 3 17 126322568/MIN/-9
+MIN 3 127 16909321/MIN/-8
+MIN 3 MIN+1 0
+MIN 3 MAX 2/MIN/-1
+MIN 3 MIN 0
+MIN MIN+1 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN+1 -1 0
+MIN MIN+1 1 1/MIN/MIN
+MIN MIN+1 -2 0
+MIN MIN+1 2 1/MIN/MIN
+MIN MIN+1 -3 0
+MIN MIN+1 3 1/MIN/MIN
+MIN MIN+1 17 1/MIN/MIN
+MIN MIN+1 127 1/MIN/MIN
+MIN MIN+1 MIN+1 0
+MIN MIN+1 MAX 1/MIN/MIN
+MIN MIN+1 MIN 0
+MIN MAX 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MAX -1 0
+MIN MAX 1 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 1: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -2 0
+MIN MAX 2 ---
+ java.lang.IllegalArgumentException: -2147483648 until 2147483647 by 2: seqs cannot contain more than Int.MaxValue elements.
+MIN MAX -3 0
+MIN MAX 3 1431655765/MIN/MAX-3
+MIN MAX 17 252645135/MIN/MAX-17
+MIN MAX 127 33818641/MIN/MAX-15
+MIN MAX MIN+1 0
+MIN MAX MAX 3/MIN/MAX-1
+MIN MAX MIN 0
+MIN MIN 0 ---
+ java.lang.IllegalArgumentException: step cannot be 0.
+MIN MIN -1 0
+MIN MIN 1 0
+MIN MIN -2 0
+MIN MIN 2 0
+MIN MIN -3 0
+MIN MIN 3 0
+MIN MIN 17 0
+MIN MIN 127 0
+MIN MIN MIN+1 0
+MIN MIN MAX 0
+MIN MIN MIN 0
+
diff --git a/test/files/run/range-unit.scala b/test/files/run/range-unit.scala
new file mode 100644
index 0000000000..ece0d9806c
--- /dev/null
+++ b/test/files/run/range-unit.scala
@@ -0,0 +1,55 @@
+import scala.collection.immutable.Range
+
+object Test {
+ // ha ha, I always forget math.abs(Int.MinValue) == Int.MinValue
+ val numbers = (
+ ( (-3 to 3) ++ List(17, 127, Int.MaxValue, Int.MinValue + 1)
+ ).distinct.sortBy(n => (math.abs(n), n))
+ ) :+ Int.MinValue
+
+ // reducing output a little
+ val endpoints = numbers filterNot Set(-3, -2, 2, 17, 127)
+
+ def num(n: Int) = {
+ val frommax = Int.MaxValue - n
+ val frommin = Int.MinValue - n
+
+ if (n > 0) {
+ if (frommax == 0) "MAX"
+ else if (frommax < 1000) "MAX-" + frommax
+ else "" + n
+ }
+ else {
+ if (frommin == 0) "MIN"
+ else if (frommin > -1000) "MIN+" + (-frommin)
+ else "" + n
+ }
+ }
+
+ def run[T](body: => Range): List[Any] = {
+ try { val r = body ; if (r.isEmpty) List(r.length) else List(num(r.length), num(r.head), num(r.last)) }
+ catch { case e: IllegalArgumentException => List("---\n " + e) }
+ }
+
+ def runGroup(label: String, f: (Int, Int, Int) => Range) {
+ println(">>> " + label + " <<<\n")
+ for (start <- endpoints) {
+ val s = "%-7s %-7s %-7s %s".format("start", "end", "step", "length/first/last")
+ println(s + "\n" + ("-" * s.length))
+ for (end <- endpoints ; step <- numbers) {
+ print("%-7s %-7s %-7s ".format(num(start), num(end), num(step)))
+ println(run(f(start, end, step)).mkString("/"))
+ }
+ println("")
+ }
+ }
+
+ def main(args: Array[String]): Unit = {
+ runGroup("Range.inclusive", Range.inclusive(_, _, _))
+ runGroup("Range.apply", Range.apply(_, _, _))
+ runGroup("start to end", (x, y, _) => x to y)
+ runGroup("start to end by step", _ to _ by _)
+ runGroup("start until end", (x, y, _) => x until y)
+ runGroup("start until end by step", _ until _ by _)
+ }
+}
diff --git a/test/files/run/reflection-implClass.scala b/test/files/run/reflection-implClass.scala
index b91f122a23..2b30e29bb3 100644
--- a/test/files/run/reflection-implClass.scala
+++ b/test/files/run/reflection-implClass.scala
@@ -8,19 +8,19 @@
object Test extends App with Outer {
import scala.reflect.mirror
- assert(mirror.classToSymbol(manifest[Foo].erasure).info.declaration(mirror.newTermName("bar")).info ==
- mirror.classToSymbol(manifest[Bar].erasure).info.declaration(mirror.newTermName("foo")).info)
+ assert(mirror.classToSymbol(manifest[Foo].erasure).typeSig.declaration(mirror.newTermName("bar")).typeSig ==
+ mirror.classToSymbol(manifest[Bar].erasure).typeSig.declaration(mirror.newTermName("foo")).typeSig)
val s1 = implClass(manifest[Foo].erasure)
assert(s1 != mirror.NoSymbol)
- assert(s1.info != mirror.NoType)
- assert(s1.companionModule.info != mirror.NoType)
- assert(s1.companionModule.info.declaration(mirror.newTermName("bar")) != mirror.NoSymbol)
+ assert(s1.typeSig != mirror.NoType)
+ assert(s1.companionModule.typeSig != mirror.NoType)
+ assert(s1.companionModule.typeSig.declaration(mirror.newTermName("bar")) != mirror.NoSymbol)
val s2 = implClass(manifest[Bar].erasure)
assert(s2 != mirror.NoSymbol)
- assert(s2.info != mirror.NoType)
- assert(s2.companionModule.info != mirror.NoType)
- assert(s2.companionModule.info.declaration(mirror.newTermName("foo")) != mirror.NoSymbol)
+ assert(s2.typeSig != mirror.NoType)
+ assert(s2.companionModule.typeSig != mirror.NoType)
+ assert(s2.companionModule.typeSig.declaration(mirror.newTermName("foo")) != mirror.NoSymbol)
def implClass(clazz: Class[_]) = {
val implClass = Class.forName(clazz.getName + "$class")
mirror.classToSymbol(implClass)
diff --git a/test/files/run/si5262.check b/test/files/run/si5262.check
new file mode 100644
index 0000000000..4c7a875de5
--- /dev/null
+++ b/test/files/run/si5262.check
@@ -0,0 +1,2 @@
+List(1, 2, 3, 4)
+List(1, 2, null, 4) \ No newline at end of file
diff --git a/test/files/run/si5262.scala b/test/files/run/si5262.scala
new file mode 100644
index 0000000000..fc4e57aa96
--- /dev/null
+++ b/test/files/run/si5262.scala
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+object Test {
+
+ def serializationDeserialization(obj : Any) {
+ val bos = new java.io.ByteArrayOutputStream()
+ val out = new java.io.ObjectOutputStream(bos)
+ out.writeObject(obj)
+
+ val arr = bos.toByteArray()
+ val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(arr))
+ val o = in.readObject()
+ println(o)
+ }
+
+ def main(args : Array[String]) {
+ serializationDeserialization(List(1,2,3,4))
+ serializationDeserialization(List(1,2,null,4))
+ }
+
+}
diff --git a/test/files/run/si5375.check b/test/files/run/si5375.check
new file mode 100644
index 0000000000..7d3002ffda
--- /dev/null
+++ b/test/files/run/si5375.check
@@ -0,0 +1 @@
+Composite throwable \ No newline at end of file
diff --git a/test/files/run/si5375.scala b/test/files/run/si5375.scala
new file mode 100644
index 0000000000..e4b329deae
--- /dev/null
+++ b/test/files/run/si5375.scala
@@ -0,0 +1,19 @@
+
+
+
+import collection.parallel.CompositeThrowable
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ val foos = (1 to 1000) toSeq;
+ try {
+ foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i)
+ } catch {
+ case CompositeThrowable(thr) => println("Composite throwable")
+ }
+ }
+
+}
diff --git a/test/files/run/t4835.check b/test/files/run/t4835.check
new file mode 100644
index 0000000000..531c3d7bb6
--- /dev/null
+++ b/test/files/run/t4835.check
@@ -0,0 +1,7 @@
+-1 0 1 2 3 4 5 6 7 8 9
+-1 1 3 5 7 9 11 13 15 17 19
+1 1
+2 1 2
+2 1 A 2
+3 1 2 3
+3 1 A 2 B 3
diff --git a/test/files/run/t4835.scala b/test/files/run/t4835.scala
new file mode 100644
index 0000000000..50d161be40
--- /dev/null
+++ b/test/files/run/t4835.scala
@@ -0,0 +1,38 @@
+/*
+ * Test case for SI-4835. This tests confirm that the fix
+ * doesn't break laziness. To test memory consumption,
+ * I need to confirm that OutOfMemoryError doesn't occur.
+ * I could create such tests. However, such tests consume
+ * too much time and memory.
+ */
+object Test {
+ private final val INFINITE = -1
+ def testStreamIterator(num: Int, stream: Stream[Int]): Unit = {
+ val iter = stream.iterator
+ print(num)
+ // if num == -1, then steram is infinite sequence
+ if (num == INFINITE) {
+ for(i <- 0 until 10) {
+ print(" " + iter.next())
+ }
+ } else {
+ while(iter.hasNext) {
+ print(" " + iter.next())
+ }
+ }
+ println()
+ }
+
+ def main(args: Array[String]): Unit = {
+ import Stream.{from, cons, empty}
+ testStreamIterator(INFINITE, from(0))
+ testStreamIterator(INFINITE, from(0).filter(_ % 2 == 1))
+ testStreamIterator(1, Stream(1))
+ testStreamIterator(2, Stream(1, 2))
+ //Stream with side effect
+ testStreamIterator(2, cons(1, cons({ print(" A"); 2}, empty)))
+ testStreamIterator(3, Stream(1, 2, 3))
+ //Stream with side effect
+ testStreamIterator(3, cons(1, cons({ print(" A"); 2}, cons({ print(" B"); 3}, Stream.empty))))
+ }
+}
diff --git a/test/files/run/trait-renaming.check b/test/files/run/trait-renaming.check
new file mode 100644
index 0000000000..b2e5affde5
--- /dev/null
+++ b/test/files/run/trait-renaming.check
@@ -0,0 +1,2 @@
+public static int bippy.A$B$1$class.f(bippy.A$B$1)
+public static void bippy.A$B$1$class.$init$(bippy.A$B$1)
diff --git a/test/files/run/trait-renaming/A_1.scala b/test/files/run/trait-renaming/A_1.scala
new file mode 100644
index 0000000000..2c3d4f566f
--- /dev/null
+++ b/test/files/run/trait-renaming/A_1.scala
@@ -0,0 +1,15 @@
+package bippy {
+ class A {
+ def f = {
+ trait B {
+ def f = 5
+ }
+ trait C {
+ def g = 10
+ }
+ new B with C { }
+ }
+
+ def g = Class.forName("bippy.A$B$1$class")
+ }
+}
diff --git a/test/files/run/trait-renaming/B_2.scala b/test/files/run/trait-renaming/B_2.scala
new file mode 100644
index 0000000000..174e929fe2
--- /dev/null
+++ b/test/files/run/trait-renaming/B_2.scala
@@ -0,0 +1,5 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ (new bippy.A).g.getDeclaredMethods.map(_.toString).sorted foreach println
+ }
+}
diff --git a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
index fbacb9f45c..8273e302a2 100644
--- a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
+++ b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
@@ -414,21 +414,21 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
}).reduceLeft(_ && _)
}
- // property("groupBy must be equal") = forAll(collectionPairs) {
- // case (t, coll) =>
- // (for ((f, ind) <- groupByFunctions.zipWithIndex) yield {
- // val tgroup = t.groupBy(f)
- // val cgroup = coll.groupBy(f)
- // if (tgroup != cgroup || cgroup != tgroup) {
- // println("from: " + t)
- // println("and: " + coll)
- // println("groups are: ")
- // println(tgroup)
- // println(cgroup)
- // }
- // ("operator " + ind) |: tgroup == cgroup && cgroup == tgroup
- // }).reduceLeft(_ && _)
- // }
+ property("groupBy must be equal") = forAll(collectionPairs) {
+ case (t, coll) =>
+ (for ((f, ind) <- groupByFunctions.zipWithIndex) yield {
+ val tgroup = t.groupBy(f)
+ val cgroup = coll.groupBy(f)
+ if (tgroup != cgroup || cgroup != tgroup) {
+ println("from: " + t)
+ println("and: " + coll)
+ println("groups are: ")
+ println(tgroup)
+ println(cgroup)
+ }
+ ("operator " + ind) |: tgroup == cgroup && cgroup == tgroup
+ }).reduceLeft(_ && _)
+ }
}
diff --git a/test/pending/run/t5418.check b/test/pending/run/t5418.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/pending/run/t5418.check
diff --git a/test/pending/run/t5418.scala b/test/pending/run/t5418.scala
new file mode 100644
index 0000000000..065710f15e
--- /dev/null
+++ b/test/pending/run/t5418.scala
@@ -0,0 +1,14 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ new Object().getClass
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh
index 4221e3205c..3a75593f21 100755
--- a/tools/binary-repo-lib.sh
+++ b/tools/binary-repo-lib.sh
@@ -7,6 +7,8 @@ remote_urlbase="http://typesafe.artifactoryonline.com/typesafe/scala-sha-bootstr
libraryJar="$(pwd)/lib/scala-library.jar"
desired_ext=".desired.sha1"
push_jar="$(pwd)/tools/push.jar"
+# Cache dir has .sbt in it to line up with SBT build.
+cache_dir="${HOME}/.sbt/cache/scala"
# Checks whether or not curl is installed and issues a warning on failure.
checkCurl() {
@@ -126,6 +128,25 @@ pushJarFiles() {
else
echo "Binary changes have been pushed. You may now submit the new *${desired_ext} files to git."
fi
+}
+
+# Pulls a single binary artifact from a remote repository.
+# Argument 1 - The uri to the file that should be downloaded.
+# Argument 2 - SHA of the file...
+# Returns: Cache location.
+pullJarFileToCache() {
+ local uri=$1
+ local sha=$2
+ local cache_loc=$cache_dir/$uri
+ local cdir=$(dirname $cache_loc)
+ if [[ ! -d $cdir ]]; then
+ mkdir -p $cdir
+ fi
+ # TODO - Check SHA of local cache is accurate.
+ if [[ ! -f $cache_loc ]]; then
+ curlDownload $cache_loc ${remote_urlbase}/${uri}
+ fi
+ echo "$cache_loc"
}
# Pulls a single binary artifact from a remote repository.
@@ -139,8 +160,9 @@ pullJarFile() {
local jar_name=${jar#$jar_dir/}
local version=${sha1% ?$jar_name}
local remote_uri=${version}/${jar#$basedir/}
- echo "Downloading from ${remote_urlbase}/${remote_uri}"
- curlDownload $jar ${remote_urlbase}/${remote_uri}
+ echo "Resolving [${remote_uri}]"
+ local cached_file=$(pullJarFileToCache $remote_uri $version)
+ cp $cached_file $jar
}
# Pulls binary artifacts from the remote repository.
@@ -152,7 +174,6 @@ pullJarFiles() {
jar=${sha%$desired_ext}
local valid=$(isJarFileValid $jar)
if [[ "$valid" != "OK" ]]; then
- echo "Obtaining [$jar] from binary repository..."
pullJarFile $jar $basedir
fi
done