summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala5
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala34
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/CommonTokens.scala112
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Tokens.scala150
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala127
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala278
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala4
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaTokens.scala176
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala17
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala40
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala27
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/PostErasure.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala61
-rw-r--r--src/compiler/scala/tools/nsc/util/package.scala13
29 files changed, 580 insertions, 592 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index df5952a4cf..c2caed70a0 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -98,6 +98,11 @@ trait CompilationUnits { global: Global =>
override def toString = map.toString
}
+ // namer calls typer.computeType(rhs) on DefDef / ValDef when tpt is empty. the result
+ // is cached here and re-used in typedDefDef / typedValDef
+ // Also used to cache imports type-checked by namer.
+ val transformed = new mutable.AnyRefMap[Tree, Tree]
+
/** things to check at end of compilation unit */
val toCheck = new ListBuffer[() => Unit]
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 5492e563dd..81e96b76ac 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -81,6 +81,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def picklerPhase: Phase = if (currentRun.isDefined) currentRun.picklerPhase else NoPhase
+ def erasurePhase: Phase = if (currentRun.isDefined) currentRun.erasurePhase else NoPhase
+
// platform specific elements
protected class GlobalPlatform extends {
@@ -527,7 +529,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
} with Erasure
// phaseName = "posterasure"
- object postErasure extends {
+ override object postErasure extends {
val global: Global.this.type = Global.this
val runsAfter = List("erasure")
val runsRightAfter = Some("erasure")
@@ -1212,7 +1214,26 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Have we already supplemented the error message of a compiler crash? */
private[nsc] final var supplementedError = false
- private val unitbuf = new mutable.ListBuffer[CompilationUnit]
+ private class SyncedCompilationBuffer { self =>
+ private val underlying = new mutable.ArrayBuffer[CompilationUnit]
+ def size = synchronized { underlying.size }
+ def +=(cu: CompilationUnit): this.type = { synchronized { underlying += cu }; this }
+ def head: CompilationUnit = synchronized{ underlying.head }
+ def apply(i: Int): CompilationUnit = synchronized { underlying(i) }
+ def iterator: Iterator[CompilationUnit] = new collection.AbstractIterator[CompilationUnit] {
+ private var used = 0
+ def hasNext = self.synchronized{ used < underlying.size }
+ def next = self.synchronized {
+ if (!hasNext) throw new NoSuchElementException("next on empty Iterator")
+ used += 1
+ underlying(used-1)
+ }
+ }
+ def toList: List[CompilationUnit] = synchronized{ underlying.toList }
+ }
+
+ private val unitbuf = new SyncedCompilationBuffer
+
val compiledFiles = new mutable.HashSet[String]
/** A map from compiled top-level symbols to their source files */
@@ -1223,9 +1244,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
private var phasec: Int = 0 // phases completed
private var unitc: Int = 0 // units completed this phase
- private var _unitbufSize = 0
- def size = _unitbufSize
+ def size = unitbuf.size
override def toString = "scalac Run for:\n " + compiledFiles.toList.sorted.mkString("\n ")
// Calculate where to stop based on settings -Ystop-before or -Ystop-after.
@@ -1450,7 +1470,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** add unit to be compiled in this run */
private def addUnit(unit: CompilationUnit) {
unitbuf += unit
- _unitbufSize += 1 // counting as they're added so size is cheap
compiledFiles += unit.source.file.path
}
private def checkDeprecatedSettings(unit: CompilationUnit) {
@@ -1466,11 +1485,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/* !!! Note: changing this to unitbuf.toList.iterator breaks a bunch
of tests in tests/res. This is bad, it means the resident compiler
relies on an iterator of a mutable data structure reflecting changes
- made to the underlying structure (in whatever accidental way it is
- currently depending upon.)
+ made to the underlying structure.
*/
def units: Iterator[CompilationUnit] = unitbuf.iterator
-
+
def registerPickle(sym: Symbol): Unit = ()
/** does this run compile given class, module, or case factory? */
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index d553d71bf5..c2d62db558 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -19,7 +19,7 @@ import util.Exceptional.unwrap
* exec scala "$0" "$@"
* !#
* Console.println("Hello, world!")
- * argv.toList foreach Console.println
+ * args.toList foreach Console.println
* </pre>
* <p>And here is a batch file example on Windows XP:</p>
* <pre>
@@ -29,7 +29,7 @@ import util.Exceptional.unwrap
* goto :eof
* ::!#
* Console.println("Hello, world!")
- * argv.toList foreach Console.println
+ * args.toList foreach Console.println
* </pre>
*
* @author Lex Spoon
diff --git a/src/compiler/scala/tools/nsc/ast/parser/CommonTokens.scala b/src/compiler/scala/tools/nsc/ast/parser/CommonTokens.scala
new file mode 100644
index 0000000000..5fcb02814b
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/parser/CommonTokens.scala
@@ -0,0 +1,112 @@
+package scala.tools.nsc
+package ast.parser
+
+/** Common code between Scala's Tokens and JavaTokens. */
+abstract class CommonTokens {
+
+ def isIdentifier(code: Int): Boolean
+ def isLiteral(code: Int): Boolean
+
+ /** special tokens */
+ final val EMPTY = -3
+ final val UNDEF = -2
+ final val ERROR = -1
+ final val EOF = 0
+
+ /** literals */
+ final val CHARLIT = 1
+ final val INTLIT = 2
+ final val LONGLIT = 3
+ final val FLOATLIT = 4
+ final val DOUBLELIT = 5
+ final val STRINGLIT = 6
+
+ /** keywords */
+ final val NEW = 20
+ final val THIS = 21
+ final val SUPER = 23
+
+ final val NULL = 24
+ final val TRUE = 25
+ final val FALSE = 26
+
+ // J: INSTANCEOF = 27
+ // J: CONST = 28
+
+ /** modifiers */
+ // S: IMPLICIT = 40
+ // S: OVERRIDE = 41
+ // J: PUBLIC = 42
+ final val PROTECTED = 43
+ final val PRIVATE = 44
+ // S: SEALED = 45
+ final val ABSTRACT = 46
+ // J: DEFAULT = 47
+ // J: STATIC = 48
+ final val FINAL = 49
+ // J: TRANSIENT = 50
+ // J: VOLATILE = 51
+ // J: SYNCHRONIZED = 52
+ // J: NATIVE = 53
+ // J: STRICTFP = 54
+ // S: LAZY = 55
+ // J: THROWS = 56
+ // S: MACRO = 57
+
+ /** templates */
+ final val PACKAGE = 60
+ final val IMPORT = 61
+ final val CLASS = 62
+ // S: CASECLASS = 63
+ // S: OBJECT = 64
+ // S: CASEOBJECT = 65
+ // S: TRAIT, J: INTERFACE = 66
+ // J: ENUM = 67
+ final val EXTENDS = 68
+ // S: WITH, J: IMPLEMENTS = 69
+ // S: TYPE = 70
+ // S: FORSOME = 71
+ // S: DEF = 72
+ // S: VAL = 73
+ // S: VAR = 74
+
+ /** control structures */
+ final val IF = 80
+ // S: THEN = 81
+ final val ELSE = 82
+ final val WHILE = 83
+ final val DO = 84
+ final val FOR = 85
+ // S: YIELD = 86
+ // J: BREAK = 87
+ // J: CONTINUE = 88
+ // J: GOTO = 89
+ final val THROW = 90
+ final val TRY = 91
+ final val CATCH = 92
+ final val FINALLY = 93
+ // J: SWITCH = 94
+ // S: MATCH = 95
+ final val CASE = 96
+ final val RETURN = 97
+ // J: ASSERT = 98
+
+ /** parenthesis */
+ final val LPAREN = 100
+ final val RPAREN = 101
+ final val LBRACKET = 102
+ final val RBRACKET = 103
+ final val LBRACE = 104
+ final val RBRACE = 105
+
+ /** special symbols */
+ final val COMMA = 120
+ final val SEMI = 121
+ final val DOT = 122
+ final val COLON = 123
+ final val EQUALS = 124
+ final val AT = 125
+ // S: <special symbols> = 130 - 139
+ // J: <special symbols> = 140 - 179
+ // J: <primitive types> = 180 - 189
+}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index e3d2bf14a0..8271363527 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -413,12 +413,10 @@ self =>
*
* {{{
* object moduleName {
- * def main(argv: Array[String]): Unit = {
- * val args = argv
+ * def main(args: Array[String]): Unit =
* new AnyRef {
* stmts
* }
- * }
* }
* }}}
*/
@@ -433,9 +431,8 @@ self =>
// def main
def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String)))
- def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree))
- def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv)))
- def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, gen.mkAnonymousNew(stmts)))
+ def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.args, mainParamType, EmptyTree))
+ def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), gen.mkAnonymousNew(stmts))
// object Main
def moduleName = newTermName(ScriptRunner scriptMain settings)
@@ -2495,7 +2492,7 @@ self =>
def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
val trees = {
val pat = if (tp.isEmpty) p else Typed(p, tp) setPos (p.pos union tp.pos)
- gen.mkPatDef(newmods, pat, rhs)
+ makePatDef(newmods, pat, rhs)
}
if (newmods.isDeferred) {
trees match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
index 5a7dc4950d..e624aec88c 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
@@ -6,123 +6,57 @@
package scala.tools.nsc
package ast.parser
-/** Common code between JavaTokens and Tokens. Not as much (and not as concrete)
- * as one might like because JavaTokens for no clear reason chose new numbers for
- * identical token sets.
- */
-abstract class Tokens {
- /** special tokens */
- final val EMPTY = -3
- final val UNDEF = -2
- final val ERROR = -1
- final val EOF = 0
-
- /** literals */
- final val CHARLIT = 1
- final val INTLIT = 2
- final val LONGLIT = 3
- final val FLOATLIT = 4
- final val DOUBLELIT = 5
- final val STRINGLIT = 6
-
- def LPAREN: Int
- def RBRACE: Int
-
- def isIdentifier(code: Int): Boolean
- def isLiteral(code: Int): Boolean
-}
-
-object Tokens extends Tokens {
- final val STRINGPART = 7 // a part of an interpolated string
+object Tokens extends CommonTokens {
+ final val STRINGPART = 7 // a part of an interpolated string
final val SYMBOLLIT = 8
final val INTERPOLATIONID = 9 // the lead identifier of an interpolated string
- def isLiteral(code: Int) =
- code >= CHARLIT && code <= INTERPOLATIONID
+ def isLiteral(code: Int) = code >= CHARLIT && code <= INTERPOLATIONID
/** identifiers */
final val IDENTIFIER = 10
final val BACKQUOTED_IDENT = 11
- def isIdentifier(code: Int) = code >= IDENTIFIER && code <= BACKQUOTED_IDENT // used by ide
-
- /** keywords */
- final val IF = 20
- final val FOR = 21
- final val ELSE = 22
- final val THIS = 23
- final val NULL = 24
- final val NEW = 25
- final val WITH = 26
- final val SUPER = 27
- final val CASE = 28
- final val CASECLASS = 29
- final val CASEOBJECT = 30
- final val VAL = 31
- final val ABSTRACT = 32
- final val FINAL = 33
- final val PRIVATE = 34
- final val PROTECTED = 35
- final val OVERRIDE = 36
- final val IMPLICIT = 37
- final val VAR = 38
- final val DEF = 39
- final val TYPE = 40
- final val EXTENDS = 41
- final val TRUE = 42
- final val FALSE = 43
- final val OBJECT = 44
- final val CLASS = 45
-
- final val IMPORT = 46
- final val PACKAGE = 47
- final val YIELD = 48
- final val DO = 49
- final val TRAIT = 50
- final val SEALED = 51
- final val THROW = 52
- final val TRY = 53
- final val CATCH = 54
- final val FINALLY = 55
- final val WHILE = 56
- final val RETURN = 57
- final val MATCH = 58
- final val FORSOME = 59
- final val LAZY = 61
- final val MACRO = 62 // not yet used in 2.10
- final val THEN = 63 // not yet used in 2.10
+ def isIdentifier(code: Int) = code == IDENTIFIER || code == BACKQUOTED_IDENT // used by ide
+
+ /** modifiers */
+ final val IMPLICIT = 40
+ final val OVERRIDE = 41
+ final val SEALED = 45
+ final val LAZY = 55
+ final val MACRO = 57
+
+ /** templates */
+ final val CASECLASS = 63
+ final val OBJECT = 64
+ final val CASEOBJECT = 65
+ final val TRAIT = 66
+ final val WITH = 69
+ final val TYPE = 70
+ final val FORSOME = 71
+ final val DEF = 72
+ final val VAL = 73
+ final val VAR = 74
+
+ /** control structures */
+ final val THEN = 81
+ final val YIELD = 86
+ final val MATCH = 95
/** special symbols */
- final val COMMA = 70
- final val SEMI = 71
- final val DOT = 72
- final val USCORE = 73
- final val COLON = 74
- final val EQUALS = 75
- final val LARROW = 76
- final val ARROW = 77
- final val NEWLINE = 78
- final val NEWLINES = 79
- final val SUBTYPE = 80
- final val SUPERTYPE = 81
- final val HASH = 82
- final val AT = 83
- final val VIEWBOUND = 84
-
- /** parenthesis */
- final val LPAREN = 90
- final val RPAREN = 91
- final val LBRACKET = 92
- final val RBRACKET = 93
- final val LBRACE = 94
- final val RBRACE = 95
-
- /** XML mode */
- final val XMLSTART = 96
+ final val HASH = 130
+ final val USCORE = 131
+ final val ARROW = 132
+ final val LARROW = 133
+ final val SUBTYPE = 134
+ final val SUPERTYPE = 135
+ final val VIEWBOUND = 136
+ final val NEWLINE = 137
+ final val NEWLINES = 138
+ final val XMLSTART = 139
/** for IDE only */
- final val COMMENT = 97
-
- final val WHITESPACE = 105
- final val IGNORE = 106
- final val ESCAPE = 109
+ final val COMMENT = 200
+ final val WHITESPACE = 201
+ final val IGNORE = 202
+ final val ESCAPE = 203
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 525dcffb0c..6e5a3f6ef7 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -168,4 +168,6 @@ abstract class TreeBuilder {
vparamss ::: List(evidenceParams)
}
}
+
+ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = gen.mkPatDef(mods, pat, rhs)
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 18ccced75e..359e5d6c29 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -583,53 +583,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
trait BCAnnotGen extends BCInnerClassGen {
- /*
- * can-multi-thread
- */
- def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
- val ca = new Array[Char](bytes.length)
- var idx = 0
- while (idx < bytes.length) {
- val b: Byte = bytes(idx)
- assert((b & ~0x7f) == 0)
- ca(idx) = b.asInstanceOf[Char]
- idx += 1
- }
-
- ca
- }
-
- /*
- * can-multi-thread
- */
- private def arrEncode(sb: ScalaSigBytes): Array[String] = {
- var strs: List[String] = Nil
- val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
- // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
- var prevOffset = 0
- var offset = 0
- var encLength = 0
- while (offset < bSeven.size) {
- val deltaEncLength = (if (bSeven(offset) == 0) 2 else 1)
- val newEncLength = encLength.toLong + deltaEncLength
- if (newEncLength >= 65535) {
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- encLength = 0
- prevOffset = offset
- } else {
- encLength += deltaEncLength
- offset += 1
- }
- }
- if (prevOffset < offset) {
- assert(offset == bSeven.length)
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- }
- assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
- mkArrayReverse(strs)
- }
+ import genASM.{ubytesToCharArray, arrEncode}
/*
* can-multi-thread
@@ -676,7 +630,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
av.visit(name, strEncode(sb))
} else {
val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name)
- for(arg <- arrEncode(sb)) { arrAnnotV.visit(name, arg) }
+ for(arg <- genASM.arrEncode(sb)) { arrAnnotV.visit(name, arg) }
arrAnnotV.visitEnd()
} // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape.
@@ -772,25 +726,6 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
trait BCJGenSigGen {
- // @M don't generate java generics sigs for (members of) implementation
- // classes, as they are monomorphic (TODO: ok?)
- /*
- * must-single-thread
- */
- private def needsGenericSignature(sym: Symbol) = !(
- // PP: This condition used to include sym.hasExpandedName, but this leads
- // to the total loss of generic information if a private member is
- // accessed from a closure: both the field and the accessor were generated
- // without it. This is particularly bad because the availability of
- // generic information could disappear as a consequence of a seemingly
- // unrelated change.
- settings.Ynogenericsig
- || sym.isArtifact
- || sym.isLiftedMethod
- || sym.isBridge
- || (sym.ownerChain exists (_.isImplClass))
- )
-
def getCurrentCUnit(): CompilationUnit
/* @return
@@ -799,61 +734,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
*
* must-single-thread
*/
- def getGenericSignature(sym: Symbol, owner: Symbol): String = {
-
- if (!needsGenericSignature(sym)) { return null }
-
- val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
-
- val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
- if (jsOpt.isEmpty) { return null }
-
- val sig = jsOpt.get
- log(sig) // This seems useful enough in the general case.
-
- def wrap(op: => Unit) = {
- try { op; true }
- catch { case _: Throwable => false }
- }
-
- if (settings.Xverify) {
- // Run the signature parser to catch bogus signatures.
- val isValidSignature = wrap {
- // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
- import scala.tools.asm.util.CheckClassAdapter
- if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig }
- else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
- else { CheckClassAdapter checkClassSignature sig }
- }
-
- if (!isValidSignature) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created invalid generic signature for %s in %s
- |signature: %s
- |if this is reproducible, please report bug at https://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
- return null
- }
- }
-
- if ((settings.check containsName phaseName)) {
- val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
- val bytecodeTpe = owner.thisType.memberInfo(sym)
- if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
- |signature: %s
- |original type: %s
- |normalized type: %s
- |erasure type: %s
- |if this is reproducible, please report bug at http://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
- return null
- }
- }
-
- sig
- }
+ def getGenericSignature(sym: Symbol, owner: Symbol): String = genASM.getGenericSignature(sym, owner, getCurrentCUnit())
} // end of trait BCJGenSigGen
@@ -906,7 +787,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
)
// TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
- val jgensig = if (m.isDeferred) null else getGenericSignature(m, module); // only add generic signature if method concrete; bug #1745
+ val jgensig = genASM.staticForwarderGenericSignature(m, module, getCurrentCUnit())
addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m)
val (throws, others) = m.annotations partition (_.symbol == definitions.ThrowsClass)
val thrownExceptions: List[String] = getExceptions(throws)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index eb40e1dbde..a389816caf 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -20,7 +20,7 @@ import scala.annotation.tailrec
*
* Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2012Q2/GenASM.pdf
*/
-abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
+abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { self =>
import global._
import icodes._
import icodes.opcodes._
@@ -171,10 +171,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
var pickledBytes = 0 // statistics
- val javaNameCache = perRunCaches.newMap[Symbol, Name]()
+ val javaNameCache = perRunCaches.newAnyRefMap[Symbol, Name]()
// unlike javaNameCache, reverseJavaName contains entries only for class symbols and their internal names.
- val reverseJavaName = perRunCaches.newMap[String, Symbol]()
+ val reverseJavaName = perRunCaches.newAnyRefMap[String, Symbol]()
private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _)
private def hasPublicBitSet(flags: Int) = (flags & asm.Opcodes.ACC_PUBLIC) != 0
@@ -803,134 +803,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
annot.args.isEmpty &&
!annot.matches(DeprecatedAttr)
- // @M don't generate java generics sigs for (members of) implementation
- // classes, as they are monomorphic (TODO: ok?)
- private def needsGenericSignature(sym: Symbol) = !(
- // PP: This condition used to include sym.hasExpandedName, but this leads
- // to the total loss of generic information if a private member is
- // accessed from a closure: both the field and the accessor were generated
- // without it. This is particularly bad because the availability of
- // generic information could disappear as a consequence of a seemingly
- // unrelated change.
- settings.Ynogenericsig
- || sym.isArtifact
- || sym.isLiftedMethod
- || sym.isBridge
- || (sym.ownerChain exists (_.isImplClass))
- )
-
def getCurrentCUnit(): CompilationUnit
- /** @return
- * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
- * - otherwise the signature in question
- */
- def getGenericSignature(sym: Symbol, owner: Symbol): String = {
-
- if (!needsGenericSignature(sym)) { return null }
-
- val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
-
- val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
- if (jsOpt.isEmpty) { return null }
-
- val sig = jsOpt.get
- log(sig) // This seems useful enough in the general case.
-
- def wrap(op: => Unit) = {
- try { op; true }
- catch { case _: Throwable => false }
- }
-
- if (settings.Xverify) {
- // Run the signature parser to catch bogus signatures.
- val isValidSignature = wrap {
- // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
- import scala.tools.asm.util.CheckClassAdapter
- if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig } // requires asm-util.jar
- else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
- else { CheckClassAdapter checkClassSignature sig }
- }
-
- if(!isValidSignature) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created invalid generic signature for %s in %s
- |signature: %s
- |if this is reproducible, please report bug at https://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
- return null
- }
- }
-
- if ((settings.check containsName phaseName)) {
- val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
- val bytecodeTpe = owner.thisType.memberInfo(sym)
- if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
- |signature: %s
- |original type: %s
- |normalized type: %s
- |erasure type: %s
- |if this is reproducible, please report bug at http://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
- return null
- }
- }
-
- sig
- }
-
- def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
- val ca = new Array[Char](bytes.length)
- var idx = 0
- while(idx < bytes.length) {
- val b: Byte = bytes(idx)
- assert((b & ~0x7f) == 0)
- ca(idx) = b.asInstanceOf[Char]
- idx += 1
- }
-
- ca
- }
-
- private def arrEncode(sb: ScalaSigBytes): Array[String] = {
- var strs: List[String] = Nil
- val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
- // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
- var prevOffset = 0
- var offset = 0
- var encLength = 0
- while(offset < bSeven.length) {
- val deltaEncLength = (if(bSeven(offset) == 0) 2 else 1)
- val newEncLength = encLength.toLong + deltaEncLength
- if(newEncLength >= 65535) {
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- encLength = 0
- prevOffset = offset
- } else {
- encLength += deltaEncLength
- offset += 1
- }
- }
- if(prevOffset < offset) {
- assert(offset == bSeven.length)
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- }
- assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
- strs.reverse.toArray
- }
-
- private def strEncode(sb: ScalaSigBytes): String = {
- val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
- new java.lang.String(ca)
- // debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
- // debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
- // debug assert(enc(idx) == bvA.getByte(idx + 2))
- // debug assert(bvA.getLength == enc.size + 2)
- }
+ def getGenericSignature(sym: Symbol, owner: Symbol) = self.getGenericSignature(sym, owner, getCurrentCUnit())
def emitArgument(av: asm.AnnotationVisitor,
name: String,
@@ -1064,7 +939,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
)
// TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
- val jgensig = if (m.isDeferred) null else getGenericSignature(m, module); // only add generic signature if method concrete; bug #1745
+ val jgensig = staticForwarderGenericSignature(m, module, getCurrentCUnit())
addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m)
val (throws, others) = m.annotations partition (_.symbol == ThrowsClass)
val thrownExceptions: List[String] = getExceptions(throws)
@@ -3303,4 +3178,147 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
+ // @M don't generate java generics sigs for (members of) implementation
+ // classes, as they are monomorphic (TODO: ok?)
+ private def needsGenericSignature(sym: Symbol) = !(
+ // PP: This condition used to include sym.hasExpandedName, but this leads
+ // to the total loss of generic information if a private member is
+ // accessed from a closure: both the field and the accessor were generated
+ // without it. This is particularly bad because the availability of
+ // generic information could disappear as a consequence of a seemingly
+ // unrelated change.
+ settings.Ynogenericsig
+ || sym.isArtifact
+ || sym.isLiftedMethod
+ || sym.isBridge
+ || (sym.ownerChain exists (_.isImplClass))
+ )
+
+ final def staticForwarderGenericSignature(sym: Symbol, moduleClass: Symbol, unit: CompilationUnit): String = {
+ if (sym.isDeferred) null // only add generic signature if method concrete; bug #1745
+ else {
+ // SI-3452 Static forwarder generation uses the same erased signature as the method if forwards to.
+ // By rights, it should use the signature as-seen-from the module class, and add suitable
+ // primitive and value-class boxing/unboxing.
+ // But for now, just like we did in mixin, we just avoid writing a wrong generic signature
+ // (one that doesn't erase to the actual signature). See run/t3452b for a test case.
+ val memberTpe = enteringErasure(moduleClass.thisType.memberInfo(sym))
+ val erasedMemberType = erasure.erasure(sym)(memberTpe)
+ if (erasedMemberType =:= sym.info)
+ getGenericSignature(sym, moduleClass, memberTpe, unit)
+ else null
+ }
+ }
+
+ /** @return
+ * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
+ * - otherwise the signature in question
+ */
+ def getGenericSignature(sym: Symbol, owner: Symbol, unit: CompilationUnit): String = {
+ val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
+ getGenericSignature(sym, owner, memberTpe, unit)
+ }
+ def getGenericSignature(sym: Symbol, owner: Symbol, memberTpe: Type, unit: CompilationUnit): String = {
+ if (!needsGenericSignature(sym)) { return null }
+
+ val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
+ if (jsOpt.isEmpty) { return null }
+
+ val sig = jsOpt.get
+ log(sig) // This seems useful enough in the general case.
+
+ def wrap(op: => Unit) = {
+ try { op; true }
+ catch { case _: Throwable => false }
+ }
+
+ if (settings.Xverify) {
+ // Run the signature parser to catch bogus signatures.
+ val isValidSignature = wrap {
+ // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
+ import scala.tools.asm.util.CheckClassAdapter
+ if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig } // requires asm-util.jar
+ else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
+ else { CheckClassAdapter checkClassSignature sig }
+ }
+
+ if(!isValidSignature) {
+ unit.warning(sym.pos,
+ """|compiler bug: created invalid generic signature for %s in %s
+ |signature: %s
+ |if this is reproducible, please report bug at https://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
+ return null
+ }
+ }
+
+ if ((settings.check containsName phaseName)) {
+ val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
+ val bytecodeTpe = owner.thisType.memberInfo(sym)
+ if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
+ unit.warning(sym.pos,
+ """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
+ |signature: %s
+ |original type: %s
+ |normalized type: %s
+ |erasure type: %s
+ |if this is reproducible, please report bug at http://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
+ return null
+ }
+ }
+
+ sig
+ }
+
+ def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
+ val ca = new Array[Char](bytes.length)
+ var idx = 0
+ while(idx < bytes.length) {
+ val b: Byte = bytes(idx)
+ assert((b & ~0x7f) == 0)
+ ca(idx) = b.asInstanceOf[Char]
+ idx += 1
+ }
+
+ ca
+ }
+
+ final def arrEncode(sb: ScalaSigBytes): Array[String] = {
+ var strs: List[String] = Nil
+ val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
+ // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
+ var prevOffset = 0
+ var offset = 0
+ var encLength = 0
+ while(offset < bSeven.length) {
+ val deltaEncLength = (if(bSeven(offset) == 0) 2 else 1)
+ val newEncLength = encLength.toLong + deltaEncLength
+ if(newEncLength >= 65535) {
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ encLength = 0
+ prevOffset = offset
+ } else {
+ encLength += deltaEncLength
+ offset += 1
+ }
+ }
+ if(prevOffset < offset) {
+ assert(offset == bSeven.length)
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ }
+ assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
+ strs.reverse.toArray
+ }
+
+ private def strEncode(sb: ScalaSigBytes): String = {
+ val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
+ new java.lang.String(ca)
+ // debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
+ // debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
+ // debug assert(enc(idx) == bvA.getByte(idx + 2))
+ // debug assert(bvA.getLength == enc.size + 2)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index 9875d27047..a61ad392ee 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -190,7 +190,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
case GTGTGT => GTGT
case GTGTEQ => GTEQ
case GTGT => GT
- case GTEQ => ASSIGN
+ case GTEQ => EQUALS
}
if (closers isDefinedAt in.token) in.token = closers(in.token)
else accept(GT)
@@ -538,7 +538,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
in.nextToken()
if (in.token == IDENTIFIER) { // if there's an ident after the comma ...
val name = ident()
- if (in.token == ASSIGN || in.token == SEMI) { // ... followed by a `=` or `;`, we know it's a real variable definition
+ if (in.token == EQUALS || in.token == SEMI) { // ... followed by a `=` or `;`, we know it's a real variable definition
buf ++= maybe
buf += varDecl(in.currentPos, mods, tpt.duplicate, name.toTermName)
maybe.clear()
@@ -563,7 +563,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
val tpt1 = optArrayBrackets(tpt)
- if (in.token == ASSIGN && !mods.isParameter) skipTo(COMMA, SEMI)
+ if (in.token == EQUALS && !mods.isParameter) skipTo(COMMA, SEMI)
val mods1 = if (mods.isFinal) mods &~ Flags.FINAL else mods | Flags.MUTABLE
atPos(pos) {
ValDef(mods1, name, tpt1, blankExpr)
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index b7ea70e2c7..c5401219dd 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -155,7 +155,6 @@ trait JavaScanners extends ast.parser.ScannersCommon {
case AMP => "`&'"
case AMPAMP => "`&&'"
case AMPEQ => "`&='"
- case ASSIGN => "`='"
case ASTERISK => "`*'"
case ASTERISKEQ => "`*='"
case AT => "`@'"
@@ -169,6 +168,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
case DOT => "`.'"
case DOTDOTDOT => "`...'"
case EQEQ => "`=='"
+ case EQUALS => "`='"
case GT => "`>'"
case GTEQ => "`>='"
case GTGT => "`>>'"
@@ -337,7 +337,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
return
case '=' =>
- token = ASSIGN
+ token = EQUALS
in.next()
if (in.ch == '=') {
token = EQEQ
diff --git a/src/compiler/scala/tools/nsc/javac/JavaTokens.scala b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala
index 953a3c6d82..9b31e6e8a2 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaTokens.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala
@@ -6,117 +6,89 @@
package scala.tools.nsc
package javac
-object JavaTokens extends ast.parser.Tokens {
+object JavaTokens extends ast.parser.CommonTokens {
- def isLiteral(code : Int) =
+ def isLiteral(code: Int) =
code >= CHARLIT && code <= STRINGLIT
/** identifiers */
final val IDENTIFIER = 10
- def isIdentifier(code : Int) =
+ def isIdentifier(code: Int) =
code == IDENTIFIER
/** keywords */
- final val ABSTRACT = 20
- final val ASSERT = 21
- final val BOOLEAN = 22
- final val BREAK = 23
- final val BYTE = 24
- final val CASE = 25
- final val CATCH = 26
- final val CHAR = 27
- final val CLASS = 28
- final val CONST = 29
- final val CONTINUE = 30
- final val DEFAULT = 31
- final val DO = 32
- final val DOUBLE = 33
- final val ELSE = 34
- final val ENUM = 35
- final val EXTENDS = 36
- final val FINAL = 37
- final val FINALLY = 38
- final val FLOAT = 39
- final val FOR = 40
- final val IF = 41
- final val GOTO = 42
- final val IMPLEMENTS = 43
- final val IMPORT = 44
- final val INSTANCEOF = 45
- final val INT = 46
- final val INTERFACE = 47
- final val LONG = 48
- final val NATIVE = 49
- final val NEW = 50
- final val PACKAGE = 51
- final val PRIVATE = 52
- final val PROTECTED = 53
- final val PUBLIC = 54
- final val RETURN = 55
- final val SHORT = 56
- final val STATIC = 57
- final val STRICTFP = 58
- final val SUPER = 59
- final val SWITCH = 60
- final val SYNCHRONIZED = 61
- final val THIS = 62
- final val THROW = 63
- final val THROWS = 64
- final val TRANSIENT = 65
- final val TRY = 66
- final val VOID = 67
- final val VOLATILE = 68
- final val WHILE = 69
+ final val INSTANCEOF = 27
+ final val CONST = 28
+
+ /** modifiers */
+ final val PUBLIC = 42
+ final val DEFAULT = 47
+ final val STATIC = 48
+ final val TRANSIENT = 50
+ final val VOLATILE = 51
+ final val SYNCHRONIZED = 52
+ final val NATIVE = 53
+ final val STRICTFP = 54
+ final val THROWS = 56
+
+ /** templates */
+ final val INTERFACE = 66
+ final val ENUM = 67
+ final val IMPLEMENTS = 69
+
+ /** control structures */
+ final val BREAK = 87
+ final val CONTINUE = 88
+ final val GOTO = 89
+ final val SWITCH = 94
+ final val ASSERT = 98
/** special symbols */
- final val COMMA = 70
- final val SEMI = 71
- final val DOT = 72
- final val AT = 73
- final val COLON = 74
- final val ASSIGN = 75
- final val EQEQ = 76
- final val BANGEQ = 77
- final val LT = 78
- final val GT = 79
- final val LTEQ = 80
- final val GTEQ = 81
- final val BANG = 82
- final val QMARK = 83
- final val AMP = 84
- final val BAR = 85
- final val PLUS = 86
- final val MINUS = 87
- final val ASTERISK = 88
- final val SLASH = 89
- final val PERCENT = 90
- final val HAT = 91
- final val LTLT = 92
- final val GTGT = 93
- final val GTGTGT = 94
- final val AMPAMP = 95
- final val BARBAR = 96
- final val PLUSPLUS = 97
- final val MINUSMINUS = 98
- final val TILDE = 99
- final val DOTDOTDOT = 100
- final val AMPEQ = 104
- final val BAREQ = 105
- final val PLUSEQ = 106
- final val MINUSEQ = 107
- final val ASTERISKEQ = 1010
- final val SLASHEQ = 109
- final val PERCENTEQ = 110
- final val HATEQ = 111
- final val LTLTEQ = 112
- final val GTGTEQ = 113
- final val GTGTGTEQ = 114
+ final val EQEQ = 140
+ final val BANGEQ = 141
+ final val LT = 142
+ final val GT = 143
+ final val LTEQ = 144
+ final val GTEQ = 145
+ final val BANG = 146
+ final val QMARK = 147
+ final val AMP = 148
+ final val BAR = 149
+ final val PLUS = 150
+ final val MINUS = 151
+ final val ASTERISK = 152
+ final val SLASH = 153
+ final val PERCENT = 154
+ final val HAT = 155
+ final val LTLT = 156
+ final val GTGT = 157
+ final val GTGTGT = 158
+ final val AMPAMP = 159
+ final val BARBAR = 160
+ final val PLUSPLUS = 161
+ final val MINUSMINUS = 162
+ final val TILDE = 163
+ final val DOTDOTDOT = 164
+ final val AMPEQ = 165
+ final val BAREQ = 166
+ final val PLUSEQ = 167
+ final val MINUSEQ = 168
+ final val ASTERISKEQ = 169
+ final val SLASHEQ = 170
+ final val PERCENTEQ = 171
+ final val HATEQ = 172
+ final val LTLTEQ = 173
+ final val GTGTEQ = 174
+ final val GTGTGTEQ = 175
- /** parenthesis */
- final val LPAREN = 115
- final val RPAREN = 116
- final val LBRACKET = 117
- final val RBRACKET = 118
- final val LBRACE = 119
- final val RBRACE = 120
+ /** primitive types */
+ final val VOID = 180
+ final val BOOLEAN = 181
+ final val BYTE = 182
+ final val SHORT = 183
+ final val CHAR = 184
+ final val INT = 185
+ final val LONG = 186
+ final val FLOAT = 187
+ final val DOUBLE = 188
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 664645e53e..2f9cc01c0b 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -665,8 +665,11 @@ abstract class ClassfileParser {
// so have to check unsafeTypeParams.isEmpty before worrying about raw type case below,
// or we'll create a boatload of needless existentials.
else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp
- // raw type - existentially quantify all type parameters
- else debuglogResult(s"raw type from $classSym")(unsafeClassExistentialType(classSym))
+ else debuglogResult(s"raw type from $classSym"){
+ // raw type - existentially quantify all type parameters
+ val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)
+ newExistentialType(eparams, typeRef(pre, classSym, eparams.map(_.tpeHK)))
+ }
case tp =>
assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp")
tp
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index 933a2f70a1..d81a5d5755 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -232,6 +232,10 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
val parents = addSerializable(abstractFunctionErasedType)
val funOwner = originalFunction.symbol.owner
+ // TODO harmonize the naming of delamdafy anon-fun classes with those spun up by Uncurry
+ // - make `anonClass.isAnonymousClass` true.
+ // - use `newAnonymousClassSymbol` or push the required variations into a similar factory method
+ // - reinstate the assertion in `Erasure.resolveAnonymousBridgeClash`
val suffix = "$lambda$" + (
if (funOwner.isPrimaryConstructor) ""
else "$" + funOwner.name
@@ -282,18 +286,11 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
if (sym == NoSymbol) sym.toString
else s"$sym: ${sym.tpe} in ${sym.owner}"
- def clashError(bm: Symbol) = {
- unit.error(
- applyMethodDef.symbol.pos,
- sm"""bridge generated for member ${fulldef(applyMethodDef.symbol)}
- |which overrides ${fulldef(getMember(abstractFunctionErasedType.typeSymbol, nme.apply))}
- |clashes with definition of the member itself;
- |both have erased type ${exitingPostErasure(bm.tpe)}""")
- }
-
bridgeMethod foreach (bm =>
+ // TODO SI-6260 maybe just create the apply method with the signature (Object => Object) in all cases
+ // rather than the method+bridge pair.
if (bm.symbol.tpe =:= applyMethodDef.symbol.tpe)
- clashError(bm.symbol)
+ erasure.resolveAnonymousBridgeClash(applyMethodDef.symbol, bm.symbol)
)
val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index ccfddab94a..60c1553ef3 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -403,19 +403,19 @@ abstract class Erasure extends AddInterfaces
* @param other The overidden symbol for which the bridge was generated
* @param bridge The bridge
*/
- def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Boolean = {
+ def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Seq[(Position, String)] = {
def fulldef(sym: Symbol) =
if (sym == NoSymbol) sym.toString
else s"$sym: ${sym.tpe} in ${sym.owner}"
var noclash = true
+ val clashErrors = mutable.Buffer[(Position, String)]()
def clashError(what: String) = {
- noclash = false
- unit.error(
- if (member.owner == root) member.pos else root.pos,
- sm"""bridge generated for member ${fulldef(member)}
- |which overrides ${fulldef(other)}
- |clashes with definition of $what;
- |both have erased type ${exitingPostErasure(bridge.tpe)}""")
+ val pos = if (member.owner == root) member.pos else root.pos
+ val msg = sm"""bridge generated for member ${fulldef(member)}
+ |which overrides ${fulldef(other)}
+ |clashes with definition of $what;
+ |both have erased type ${exitingPostErasure(bridge.tpe)}"""
+ clashErrors += Tuple2(pos, msg)
}
for (bc <- root.baseClasses) {
if (settings.debug)
@@ -440,7 +440,7 @@ abstract class Erasure extends AddInterfaces
}
}
}
- noclash
+ clashErrors
}
/** TODO - work through this logic with a fine-toothed comb, incorporating
@@ -478,8 +478,18 @@ abstract class Erasure extends AddInterfaces
bridge setInfo (otpe cloneInfo bridge)
bridgeTarget(bridge) = member
- if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) ||
- checkBridgeOverrides(member, other, bridge)) {
+ def sigContainsValueClass = (member.tpe exists (_.typeSymbol.isDerivedValueClass))
+
+ val shouldAdd = (
+ !sigContainsValueClass
+ || (checkBridgeOverrides(member, other, bridge) match {
+ case Nil => true
+ case es if member.owner.isAnonymousClass => resolveAnonymousBridgeClash(member, bridge); true
+ case es => for ((pos, msg) <- es) unit.error(pos, msg); false
+ })
+ )
+
+ if (shouldAdd) {
exitingErasure(root.info.decls enter bridge)
if (other.owner == root) {
exitingErasure(root.info.decls.unlink(other))
@@ -1127,5 +1137,13 @@ abstract class Erasure extends AddInterfaces
}
}
+ final def resolveAnonymousBridgeClash(sym: Symbol, bridge: Symbol) {
+ // TODO reinstate this after Delambdafy generates anonymous classes that meet this requirement.
+ // require(sym.owner.isAnonymousClass, sym.owner)
+ log(s"Expanding name of ${sym.debugLocationString} as it clashes with bridge. Renaming deemed safe because the owner is anonymous.")
+ sym.expandName(sym.owner)
+ bridge.resetFlag(BRIDGE)
+ }
+
private class TypeRefAttachment(val tpe: TypeRef)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index b4329965fc..c3fbfae322 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -20,12 +20,16 @@ abstract class Flatten extends InfoTransform {
/** Updates the owning scope with the given symbol, unlinking any others.
*/
private def replaceSymbolInCurrentScope(sym: Symbol): Unit = exitingFlatten {
+ removeSymbolInCurrentScope(sym)
+ sym.owner.info.decls enter sym
+ }
+
+ private def removeSymbolInCurrentScope(sym: Symbol): Unit = exitingFlatten {
val scope = sym.owner.info.decls
val old = (scope lookupUnshadowedEntries sym.name).toList
old foreach (scope unlink _)
- scope enter sym
def old_s = old map (_.sym) mkString ", "
- debuglog(s"In scope of ${sym.owner}, unlinked $old_s and entered $sym")
+ if (old.nonEmpty) debuglog(s"In scope of ${sym.owner}, unlinked $old_s")
}
private def liftClass(sym: Symbol) {
@@ -121,6 +125,8 @@ abstract class Flatten extends InfoTransform {
val liftedBuffer = liftedDefs(tree.symbol.enclosingTopLevelClass.owner)
val index = liftedBuffer.length
liftedBuffer.insert(index, super.transform(tree))
+ if (tree.symbol.sourceModule.isStaticModule)
+ removeSymbolInCurrentScope(tree.symbol.sourceModule)
EmptyTree
case _ =>
super.transform(tree)
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 89f9cb4b06..673bc04bd9 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -172,18 +172,23 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// info) as they are seen from the class. We can't use the member that we get from the
// implementation class, as it's a clone that was made after erasure, and thus it does not
// know its info at the beginning of erasure anymore.
- // Optimize: no need if mixinClass has no typeparams.
- mixinMember cloneSymbol clazz modifyInfo (info =>
- if (mixinClass.typeParams.isEmpty) info
- else (clazz.thisType baseType mixinClass) memberInfo mixinMember
- )
+ val sym = mixinMember cloneSymbol clazz
+
+ val erasureMap = erasure.erasure(mixinMember)
+ val erasedInterfaceInfo: Type = erasureMap(mixinMember.info)
+ val specificForwardInfo = (clazz.thisType baseType mixinClass) memberInfo mixinMember
+ val forwarderInfo =
+ if (erasureMap(specificForwardInfo) =:= erasedInterfaceInfo)
+ specificForwardInfo
+ else {
+ erasedInterfaceInfo
+ }
+ // Optimize: no need if mixinClass has no typeparams.
+ // !!! JZ Really? What about the effect of abstract types, prefix?
+ if (mixinClass.typeParams.isEmpty) sym
+ else sym modifyInfo (_ => forwarderInfo)
}
- // clone before erasure got rid of type info we'll need to generate a javaSig
- // now we'll have the type info at (the beginning of) erasure in our history,
- // and now newSym has the info that's been transformed to fit this period
- // (no need for asSeenFrom as phase.erasedTypes)
- // TODO: verify we need the updateInfo and document why
- newSym updateInfo (mixinMember.info cloneInfo newSym)
+ newSym
}
/** Add getters and setters for all non-module fields of an implementation
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 870eafbf20..bbd11efa7e 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -24,7 +24,12 @@ abstract class OverridingPairs extends SymbolPairs {
/** Symbols to exclude: Here these are constructors and private/artifact symbols,
* including bridges. But it may be refined in subclasses.
*/
- override protected def exclude(sym: Symbol) = sym.isPrivateLocal || sym.isArtifact || sym.isConstructor
+ override protected def exclude(sym: Symbol) = (
+ sym.isPrivateLocal
+ || sym.isArtifact
+ || sym.isConstructor
+ || (sym.isPrivate && sym.owner != base) // Privates aren't inherited. Needed for pos/t7475a.scala
+ )
/** Types always match. Term symbols match if their member types
* relative to `self` match.
diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
index cc78e27282..32987fed8c 100644
--- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
@@ -8,7 +8,7 @@ package transform
/** This phase maps ErasedValueTypes to the underlying unboxed representation and
* performs peephole optimizations.
*/
-trait PostErasure extends InfoTransform with TypingTransformers {
+trait PostErasure extends InfoTransform with TypingTransformers with scala.reflect.internal.transform.PostErasure {
val global: Global
import global._
@@ -19,16 +19,6 @@ trait PostErasure extends InfoTransform with TypingTransformers {
def newTransformer(unit: CompilationUnit): Transformer = new PostErasureTransformer(unit)
override def changesBaseClasses = false
- object elimErasedValueType extends TypeMap {
- def apply(tp: Type) = tp match {
- case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp)))
- case ErasedValueType(_, underlying) => underlying
- case _ => mapOver(tp)
- }
- }
-
- def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp)
-
class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
override def transform(tree: Tree) = {
def finish(res: Tree) = logResult(s"Posterasure reduction\n Old: $tree\n New")(res)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index e5907e1a0f..c065fb54b7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -89,6 +89,8 @@ trait Contexts { self: Analyzer =>
if (settings.noimports) Nil
else if (unit.isJava) RootImports.javaList
else if (settings.nopredef || treeInfo.noPredefImportForUnit(unit.body)) {
+ // SI-8258 Needed for the presentation compiler using -sourcepath, otherwise cycles can occur. See the commit
+ // message for this ticket for an example.
debuglog("Omitted import of Predef._ for " + unit)
RootImports.javaAndScalaList
}
@@ -457,7 +459,9 @@ trait Contexts { self: Analyzer =>
c.prefix = prefixInChild
c.enclClass = if (isTemplateOrPackage) c else enclClass
c(ConstructorSuffix) = !isTemplateOrPackage && c(ConstructorSuffix)
- c.enclMethod = if (isDefDef) c else enclMethod
+
+ // SI-8245 `isLazy` need to skip lazy getters to ensure `return` binds to the right place
+ c.enclMethod = if (isDefDef && !owner.isLazy) c else enclMethod
registerContext(c.asInstanceOf[analyzer.Context])
debuglog("[context] ++ " + c.unit + " / " + tree.summaryString)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 776920ed42..8f5778862d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -306,7 +306,10 @@ trait Implicits {
*/
object Function1 {
val Sym = FunctionClass(1)
- def unapply(tp: Type) = tp baseType Sym match {
+ // It is tempting to think that this should be inspecting "tp baseType Sym"
+ // rather than tp. See test case run/t8280 and the commit message which
+ // accompanies it for explanation why that isn't done.
+ def unapply(tp: Type) = tp match {
case TypeRef(_, Sym, arg1 :: arg2 :: _) => Some((arg1, arg2))
case _ => None
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 997fd6fc65..2d6c94349b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -174,7 +174,8 @@ trait Infer extends Checkable {
private lazy val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)
/** The context-dependent inferencer part */
- class Inferencer(context: Context) extends InferencerContextErrors with InferCheckable {
+ abstract class Inferencer extends InferencerContextErrors with InferCheckable {
+ def context: Context
import InferErrorGen._
/* -- Error Messages --------------------------------------------------- */
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 29b3ec7f3e..1f90dd4939 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -661,9 +661,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
val expanded1 = atPos(enclosingMacroPosition.makeTransparent)(Typed(expanded0, TypeTree(innerPt)))
typecheck("blackbox typecheck", expanded1, outerPt)
} else {
- val expanded1 = expanded0
- val expanded2 = typecheck("whitebox typecheck #1", expanded1, outerPt)
- typecheck("whitebox typecheck #2", expanded2, innerPt)
+ // whitebox expansions need to be typechecked against WildcardType first in order to avoid SI-6992 and SI-8048
+ // then we typecheck against innerPt, not against outerPt in order to prevent SI-8209
+ val expanded1 = typecheck("whitebox typecheck #0", expanded0, WildcardType)
+ val expanded2 = typecheck("whitebox typecheck #1", expanded1, innerPt)
+ typecheck("whitebox typecheck #2", expanded2, outerPt)
}
}
override def onDelayed(delayed: Tree) = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index ec2b7d49f5..ba183fe3e6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -427,7 +427,7 @@ trait MethodSynthesis {
override def derivedSym = basisSym.lazyAccessor
override def derivedTree: DefDef = {
val ValDef(_, _, tpt0, rhs0) = tree
- val rhs1 = transformed.getOrElse(rhs0, rhs0)
+ val rhs1 = context.unit.transformed.getOrElse(rhs0, rhs0)
val body = (
if (tree.symbol.owner.isTrait || hasUnitType(basisSym)) rhs1
else gen.mkAssignAndReturn(basisSym, rhs1)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 632e25aa2e..9b5b0e1f37 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -169,6 +169,13 @@ trait Namers extends MethodSynthesis {
def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = {
debuglog("[overwrite] " + sym)
val newFlags = (sym.flags & LOCKED) | flags
+ sym.rawInfo match {
+ case tr: TypeRef =>
+ // !!! needed for: pos/t5954d; the uniques type cache will happilly serve up the same TypeRef
+ // over this mutated symbol, and we witness a stale cache for `parents`.
+ tr.invalidateCaches()
+ case _ =>
+ }
sym reset NoType setFlag newFlags setPos pos
sym.moduleClass andAlso (updatePosFlags(_, pos, moduleClassFlags(flags)))
@@ -457,6 +464,17 @@ trait Namers extends MethodSynthesis {
var m: Symbol = context.scope lookupModule tree.name
val moduleFlags = tree.mods.flags | MODULE
if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) {
+ // This code accounts for the way the package objects found in the classpath are opened up
+ // early by the completer of the package itself. If the `packageobjects` phase then finds
+ // the same package object in sources, we have to clean the slate and remove package object
+ // members from the package class.
+ //
+ // TODO SI-4695 Pursue the approach in https://github.com/scala/scala/pull/2789 that avoids
+ // opening up the package object on the classpath at all if one exists in source.
+ if (m.isPackageObject) {
+ val packageScope = m.enclosingPackageClass.rawInfo.decls
+ packageScope.filter(_.owner != m.enclosingPackageClass).toList.foreach(packageScope unlink _)
+ }
updatePosFlags(m, tree.pos, moduleFlags)
setPrivateWithin(tree, m)
m.moduleClass andAlso (setPrivateWithin(tree, _))
@@ -1408,12 +1426,18 @@ trait Namers extends MethodSynthesis {
if (expr1.isErrorTyped)
ErrorType
else {
- if (!treeInfo.isStableIdentifierPattern(expr1))
- typer.TyperErrorGen.UnstableTreeError(expr1)
+ expr1 match {
+ case This(_) =>
+ // SI-8207 okay, typedIdent expands Ident(self) to C.this which doesn't satisfy the next case
+ // TODO should we change `typedIdent` not to expand to the `Ident` to a `This`?
+ case _ if treeInfo.isStableIdentifierPattern(expr1) =>
+ case _ =>
+ typer.TyperErrorGen.UnstableTreeError(expr1)
+ }
val newImport = treeCopy.Import(imp, expr1, selectors).asInstanceOf[Import]
checkSelectors(newImport)
- transformed(imp) = newImport
+ context.unit.transformed(imp) = newImport
// copy symbol and type attributes back into old expression
// so that the structure builder will find it.
expr setSymbol expr1.symbol setType expr1.tpe
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index 41c656f8ce..cf3f265f0c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -221,10 +221,12 @@ trait PatternTypers {
* see test/files/../t5189*.scala
*/
private def convertToCaseConstructor(tree: Tree, caseClass: Symbol, ptIn: Type): Tree = {
- def untrustworthyPt = (
+ // TODO SI-7886 / SI-5900 This is well intentioned but doesn't quite hit the nail on the head.
+ // For now, I've put it completely behind -Xstrict-inference.
+ val untrustworthyPt = settings.strictInference && (
ptIn =:= AnyTpe
|| ptIn =:= NothingTpe
- || settings.strictInference && ptIn.typeSymbol != caseClass
+ || ptIn.typeSymbol != caseClass
)
val variantToSkolem = new VariantToSkolemMap
val caseClassType = tree.tpe.prefix memberType caseClass
@@ -371,4 +373,4 @@ trait PatternTypers {
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 2125e281f0..916b8a3e0c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -467,6 +467,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// overrideError("may not override parameterized type");
// @M: substSym
def checkOverrideAlias() {
+ // Important: first check the pair has the same kind, since the substitution
+ // carries high's type parameter's bounds over to low, so that
+ // type equality doesn't consider potentially different bounds on low/high's type params.
+ // In b781e25afe this went from using memberInfo to memberType (now lowType/highType), tested by neg/override.scala.
+ // TODO: was that the right fix? it seems type alias's RHS should be checked by looking at the symbol's info
if (pair.sameKind && lowType.substSym(low.typeParams, high.typeParams) =:= highType) ()
else overrideTypeError() // (1.6)
}
@@ -853,7 +858,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
val baseClass = clazz.info.baseTypeSeq(i).typeSymbol
seenTypes(i) match {
case Nil =>
- println("??? base "+baseClass+" not found in basetypes of "+clazz)
+ devWarning(s"base $baseClass not found in basetypes of $clazz. This might indicate incorrect caching of TypeRef#parents.")
case _ :: Nil =>
;// OK
case tp1 :: tp2 :: _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 020d26c712..aadc8f5e3b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -13,7 +13,7 @@ package scala
package tools.nsc
package typechecker
-import scala.collection.{ mutable, immutable }
+import scala.collection.{mutable, immutable}
import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance }
import mutable.ListBuffer
import symtab.Flags._
@@ -39,7 +39,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// namer calls typer.computeType(rhs) on DefDef / ValDef when tpt is empty. the result
// is cached here and re-used in typedDefDef / typedValDef
// Also used to cache imports type-checked by namer.
- val transformed = new mutable.HashMap[Tree, Tree]
+ val transformed = new mutable.AnyRefMap[Tree, Tree]
final val shortenImports = false
@@ -52,11 +52,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
//println("resetTyper called")
resetContexts()
resetImplicits()
- transformed.clear()
resetDocComments()
}
sealed abstract class SilentResult[+T] {
+ def isEmpty: Boolean
+ def nonEmpty = !isEmpty
+
@inline final def fold[U](none: => U)(f: T => U): U = this match {
case SilentResultValue(value) => f(value)
case _ => none
@@ -75,6 +77,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ override def isEmpty = true
def err: AbsTypeError = errors.head
def reportableErrors = errors match {
case (e1: AmbiguousImplicitTypeError) +: _ =>
@@ -88,7 +91,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
}
- case class SilentResultValue[+T](value: T) extends SilentResult[T] { }
+ case class SilentResultValue[+T](value: T) extends SilentResult[T] { override def isEmpty = false }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -108,7 +111,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val runDefinitions = currentRun.runDefinitions
import runDefinitions._
- val infer = new Inferencer(context0) {
+ private val transformed: mutable.Map[Tree, Tree] = unit.transformed
+
+ val infer = new Inferencer {
+ def context = Typer.this.context
// See SI-3281 re undoLog
override def isCoercible(tp: Type, pt: Type) = undoLog undo viewExists(tp, pt)
}
@@ -1797,32 +1803,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (settings.isScala211 && mdef.symbol == PredefModule)
ensurePredefParentsAreInSameSourceFile(impl2)
- // SI-5954. On second compile of a companion class contained in a package object we end up
- // with some confusion of names which leads to having two symbols with the same name in the
- // same owner. Until that can be straightened out we will warn on companion objects in package
- // objects. But this code also tries to be friendly by distinguishing between case classes and
- // user written companion pairs
- def warnPackageObjectMembers(mdef : ModuleDef) = for (m <- mdef.symbol.info.members) {
- // ignore synthetic objects, because the "companion" object to a case class is synthetic and
- // we only want one error per case class
- if (!m.isSynthetic) {
- // can't handle case classes in package objects
- if (m.isCaseClass) pkgObjectWarning(m, mdef, "case")
- // can't handle companion class/object pairs in package objects
- else if ((m.isClass && m.companionModule != NoSymbol && !m.companionModule.isSynthetic) ||
- (m.isModule && m.companionClass != NoSymbol && !m.companionClass.isSynthetic))
- pkgObjectWarning(m, mdef, "companion")
- }
-
- def pkgObjectWarning(m : Symbol, mdef : ModuleDef, restricted : String) = {
- val pkgName = mdef.symbol.ownerChain find (_.isPackage) map (_.decodedName) getOrElse mdef.symbol.toString
- context.warning(if (m.pos.isDefined) m.pos else mdef.pos, s"${m} should be placed directly in package ${pkgName} instead of package object ${pkgName}. Under some circumstances companion objects and case classes in package objects can fail to recompile. See https://issues.scala-lang.org/browse/SI-5954.")
- }
- }
-
- if (mdef.symbol.isPackageObject)
- warnPackageObjectMembers(mdef)
-
treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
}
@@ -4880,20 +4860,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
asym setInfo logResult(s"Updating bounds of ${asym.fullLocationString} in $tree from '$abounds' to")(TypeBounds(lo, hi))
}
if (asym != null && asym.isAbstractType) {
- // See pos/t1786 to follow what's happening here.
- def canEnhanceIdent = (
- asym.hasCompleteInfo
- && tparam.exists /* sometimes it is NoSymbol */
- && tparam.hasCompleteInfo /* SI-2940 */
- && !tparam.isFBounded /* SI-2251 */
- && !tparam.isHigherOrderTypeParameter
- && !(abounds.hi <:< tbounds.hi)
- && asym.isSynthetic /* this limits us to placeholder tparams, excluding named ones */
- )
arg match {
- case Bind(_, _) => enhanceBounds()
- case Ident(name) if canEnhanceIdent => enhanceBounds()
- case _ =>
+ // I removed the Ident() case that partially fixed SI-1786,
+ // because the stricter bounds being inferred broke e.g., slick
+ // worse, the fix was compilation order-dependent
+ // sharpenQuantifierBounds (used in skolemizeExistential) has an alternative fix (SI-6169) that's less invasive
+ case Bind(_, _) => enhanceBounds()
+ case _ =>
}
}
}
diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala
index 4237f36ade..bd95fdbb50 100644
--- a/src/compiler/scala/tools/nsc/util/package.scala
+++ b/src/compiler/scala/tools/nsc/util/package.scala
@@ -7,7 +7,7 @@ package scala
package tools
package nsc
-import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter }
+import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter, Reader }
package object util {
// forwarder for old code that builds against 2.9 and 2.10
@@ -46,6 +46,17 @@ package object util {
(result, ts2 filterNot (ts1 contains _))
}
+ def stringFromReader(reader: Reader) = {
+ val writer = new StringWriter()
+ var c = reader.read()
+ while(c != -1) {
+ writer.write(c)
+ c = reader.read()
+ }
+ reader.close()
+ writer.toString()
+ }
+
/** Generate a string using a routine that wants to write on a stream. */
def stringFromWriter(writer: PrintWriter => Unit): String = {
val stringWriter = new StringWriter()