summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/macros/util/Helpers.scala32
-rw-r--r--src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala462
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala9
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala51
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/CheckerException.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/package.scala3
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala6
-rw-r--r--src/compiler/scala/tools/nsc/settings/FscSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala17
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala24
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Solving.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala11
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala4
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala8
26 files changed, 359 insertions, 364 deletions
diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala
index f12582a3a1..f40c6bb7e6 100644
--- a/src/compiler/scala/reflect/macros/util/Helpers.scala
+++ b/src/compiler/scala/reflect/macros/util/Helpers.scala
@@ -23,25 +23,27 @@ trait Helpers {
* or to streamline creation of the list of macro arguments.
*/
def transformTypeTagEvidenceParams(macroImplRef: Tree, transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = {
+ val MacroContextUniverse = definitions.MacroContextUniverse
val treeInfo.MacroImplReference(isBundle, _, macroImpl, _) = macroImplRef
val paramss = macroImpl.paramss
- if (paramss.isEmpty || paramss.last.isEmpty) return paramss // no implicit parameters in the signature => nothing to do
- val rc =
- if (isBundle) macroImpl.owner.tpe.member(nme.c)
- else {
- def cparam = paramss.head.head
- if (paramss.head.isEmpty || !(cparam.tpe <:< MacroContextClass.tpe)) return paramss // no context parameter in the signature => nothing to do
- cparam
- }
+ val ContextParam = paramss match {
+ case Nil | _ :+ Nil => NoSymbol // no implicit parameters in the signature => nothing to do
+ case _ if isBundle => macroImpl.owner.tpe member nme.c
+ case (cparam :: _) :: _ if cparam.tpe <:< MacroContextClass.tpe => cparam
+ case _ => NoSymbol // no context parameter in the signature => nothing to do
+ }
def transformTag(param: Symbol): Symbol = param.tpe.dealias match {
- case TypeRef(SingleType(SingleType(_, ac), universe), WeakTypeTagClass, targ :: Nil)
- if ac == rc && universe == MacroContextUniverse =>
- transform(param, targ.typeSymbol)
- case _ =>
- param
+ case TypeRef(SingleType(SingleType(_, ContextParam), MacroContextUniverse), WeakTypeTagClass, targ :: Nil) => transform(param, targ.typeSymbol)
+ case _ => param
+ }
+ ContextParam match {
+ case NoSymbol => paramss
+ case _ =>
+ paramss.last map transformTag filter (_.exists) match {
+ case Nil => paramss.init
+ case transformed => paramss.init :+ transformed
+ }
}
- val transformed = paramss.last map transformTag filter (_ ne NoSymbol)
- if (transformed.isEmpty) paramss.init else paramss.init :+ transformed
}
/** Increases metalevel of the type, i.e. transforms:
diff --git a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
index 2ce2fb3eaa..899aa93a3b 100644
--- a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala
@@ -27,7 +27,7 @@ class OfflineCompilerCommand(arguments: List[String], settings: FscSettings) ext
val baseDirectory = {
val pwd = System.getenv("PWD")
if (pwd == null || isWin) Directory.Current getOrElse Directory("/")
- else Directory(pwd)
+ else Directory(pwd)
}
currentDir.value = baseDirectory.path
}
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index f2e5c9b1eb..7cf2f8559b 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -18,8 +18,14 @@ trait DocComments { self: Global =>
val cookedDocComments = mutable.HashMap[Symbol, String]()
- /** The raw doc comment map */
- val docComments = mutable.HashMap[Symbol, DocComment]()
+ /** The raw doc comment map
+ *
+ * In IDE, background compilation runs get interrupted by
+ * reloading new sourcefiles. This is weak to avoid
+ * memleaks due to the doc of their cached symbols
+ * (e.g. in baseTypeSeq) between periodic doc reloads.
+ */
+ val docComments = mutable.WeakHashMap[Symbol, DocComment]()
def clearDocComments() {
cookedDocComments.clear()
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index caab299635..9c8e13a1a9 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -282,7 +282,7 @@ abstract class NodePrinters {
traverseList("[]", "type parameter")(tparams)
vparamss match {
case Nil => println("Nil")
- case Nil :: Nil => println("List(Nil)")
+ case ListOfNil => println("List(Nil)")
case ps :: Nil =>
printLine("", "1 parameter list")
ps foreach traverse
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 07e24900e9..50aad8e043 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -303,6 +303,15 @@ self =>
def o2p(offset: Int): Position
def r2p(start: Int, mid: Int, end: Int): Position
+ /** Creates a range position from the given start offset to
+ * the value of in.lastOffset.
+ */
+ def rangeSince(start: Int): Position = r2p(start, start, in.lastOffset)
+
+ /** Like in.skipToken, but returns a range position surrounding the skipped token.
+ */
+ def skipTokenRange(): Position = rangeSince(in.skipToken())
+
/** whether a non-continuable syntax error has been seen */
private var lastErrorOffset : Int = -1
@@ -568,8 +577,9 @@ self =>
and
}
- def expectedMsgTemplate(exp: String, fnd: String) = s"$exp expected but $fnd found."
- def expectedMsg(token: Int): String = expectedMsgTemplate(token2string(token), token2string(in.token))
+ def expectedMsgTemplate(expected: String, found: String): String = s"$expected expected but $found found."
+ def expectedMsg(expected: Int, found: Int): String = expectedMsgTemplate(token2string(expected), token2string(found))
+ def expectedMsg(token: Int): String = expectedMsg(token, in.token)
/** Consume one token of the specified type, or signal an error if it is not there. */
def accept(token: Int): Int = {
@@ -587,6 +597,10 @@ self =>
if (in.token == token) in.nextToken()
offset
}
+ /** If the given token is available for consumption, consume it and return true.
+ * Otherwise, do nothing and return false.
+ */
+ def acceptIfPresent(token: Int) = (in.token == token) && { accept(token) ; true }
/** {{{
* semi = nl {nl} | `;`
@@ -703,14 +717,24 @@ self =>
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
- def atPos[T <: Tree](offset: Int)(t: T): T = atPos(r2p(offset, offset, in.lastOffset max offset))(t)
- def atPos[T <: Tree](start: Int, point: Int)(t: T): T = atPos(r2p(start, point, in.lastOffset max start))(t)
+ def atPos[T <: Tree](start: Int)(t: T): T = atPos[T](start, start)(t)
+ def atPos[T <: Tree](start: Int, point: Int)(t: T): T = atPos[T](start, point, in.lastOffset max start)(t)
def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T = atPos(r2p(start, point, end))(t)
def atPos[T <: Tree](pos: Position)(t: T): T = global.atPos(pos)(t)
def atInPos[T <: Tree](t: T): T = atPos(o2p(in.offset))(t)
def setInPos[T <: Tree](t: T): T = t setPos o2p(in.offset)
+ /** Use with caution. */
+ def peekahead(): Unit = {
+ in.prev copyFrom in
+ in.nextToken()
+ }
+ def pushback(): Unit = {
+ in.next copyFrom in
+ in copyFrom in.prev
+ }
+
/** Convert tree to formal parameter list. */
def convertToParams(tree: Tree): List[ValDef] = tree match {
case Parens(ts) => ts map convertToParam
@@ -749,10 +773,9 @@ self =>
if (!sepFirst)
ts += part
- while (in.token == separator) {
- in.nextToken()
+ while (acceptIfPresent(separator))
ts += part
- }
+
ts.toList
}
@inline final def commaSeparated[T](part: => T): List[T] = tokenSeparated(COMMA, sepFirst = false, part)
@@ -829,10 +852,8 @@ self =>
private def tupleInfixType(start: Int) = {
in.nextToken()
- if (in.token == RPAREN) {
- in.nextToken()
+ if (acceptIfPresent(RPAREN))
atPos(start, accept(ARROW)) { makeFunctionTypeTree(Nil, typ()) }
- }
else {
val ts = functionTypes()
accept(RPAREN)
@@ -936,13 +957,8 @@ self =>
)
def compoundTypeRest(t: Tree): Tree = {
- val ts = new ListBuffer[Tree] += t
- while (in.token == WITH) {
- in.nextToken()
- ts += annotType()
- }
+ val types = t :: tokenSeparated(WITH, sepFirst = true, annotType())
newLineOptWhenFollowedBy(LBRACE)
- val types = ts.toList
val braceOffset = in.offset
val hasRefinement = in.token == LBRACE
val refinements = if (hasRefinement) refinement() else Nil
@@ -956,7 +972,7 @@ self =>
}
// The second case includes an empty refinement - refinements is empty, but
// it still gets a CompoundTypeTree.
- ts.toList match {
+ types match {
case tp :: Nil if !hasRefinement => tp // single type, no refinement, already positioned
case tps => atPos(t.pos.startOrPoint)(CompoundTypeTree(Template(tps, emptyValDef, refinements)))
}
@@ -1024,19 +1040,19 @@ self =>
def path(thisOK: Boolean, typeOK: Boolean): Tree = {
val start = in.offset
var t: Tree = null
- if (in.token == THIS) {
- in.nextToken()
+ if (acceptIfPresent(THIS)) {
t = atPos(start) { This(tpnme.EMPTY) }
if (!thisOK || in.token == DOT) {
t = selectors(t, typeOK, accept(DOT))
}
- } else if (in.token == SUPER) {
- in.nextToken()
+ }
+ else if (acceptIfPresent(SUPER)) {
t = atPos(start) { Super(This(tpnme.EMPTY), mixinQualifierOpt()) }
accept(DOT)
t = selector(t)
if (in.token == DOT) t = selectors(t, typeOK, in.skipToken())
- } else {
+ }
+ else {
val tok = in.token
val name = ident()
t = atPos(start) {
@@ -1045,18 +1061,18 @@ self =>
}
if (in.token == DOT) {
val dotOffset = in.skipToken()
- if (in.token == THIS) {
- in.nextToken()
+ if (acceptIfPresent(THIS)) {
t = atPos(start) { This(name.toTypeName) }
if (!thisOK || in.token == DOT)
t = selectors(t, typeOK, accept(DOT))
- } else if (in.token == SUPER) {
- in.nextToken()
+ }
+ else if (acceptIfPresent(SUPER)) {
t = atPos(start) { Super(This(name.toTypeName), mixinQualifierOpt()) }
accept(DOT)
t = selector(t)
if (in.token == DOT) t = selectors(t, typeOK, in.skipToken())
- } else {
+ }
+ else {
t = selectors(t, typeOK, dotOffset)
}
}
@@ -1065,10 +1081,8 @@ self =>
}
def selectors(t: Tree, typeOK: Boolean, dotOffset: Int): Tree =
- if (typeOK && in.token == TYPE) {
- in.nextToken()
+ if (typeOK && acceptIfPresent(TYPE))
atPos(t.pos.startOrPoint, dotOffset) { SingletonTypeTree(t) }
- }
else {
val t1 = selector(t)
if (in.token == DOT) { selectors(t1, typeOK, in.skipToken()) }
@@ -1165,10 +1179,10 @@ self =>
private def freshPlaceholder(): Tree = {
val start = in.offset
val pname = freshName("x$")
- in.nextToken()
+ accept(USCORE)
val id = atPos(start)(Ident(pname))
val param = atPos(id.pos.focus)(gen.mkSyntheticParam(pname.toTermName))
- placeholderParams = param :: placeholderParams
+ placeholderParams ::= param
id
}
@@ -1211,7 +1225,7 @@ self =>
/* ------------- NEW LINES ------------------------------------------------- */
def newLineOpt() {
- if (in.token == NEWLINE) in.nextToken()
+ acceptIfPresent(NEWLINE)
}
def newLinesOpt() {
@@ -1235,9 +1249,7 @@ self =>
* TypedOpt ::= [`:' Type]
* }}}
*/
- def typedOpt(): Tree =
- if (in.token == COLON) { in.nextToken(); typ() }
- else TypeTree()
+ def typedOpt(): Tree = if (acceptIfPresent(COLON)) typ() else TypeTree()
def typeOrInfixType(location: Int): Tree =
if (location == Local) typ()
@@ -1261,16 +1273,9 @@ self =>
/* ----------- EXPRESSIONS ------------------------------------------------ */
- def condExpr(): Tree = {
- if (in.token == LPAREN) {
- in.nextToken()
- val r = expr()
- accept(RPAREN)
- r
- } else {
- accept(LPAREN)
- newLiteral(true)
- }
+ def condExpr(): Tree = in.token match {
+ case LPAREN => inParens(expr())
+ case _ => syntaxErrorOrIncompleteAnd("parenthesized conditional expression expected", skipIt = false)(newLiteral(true))
}
/* hook for IDE, unlike expression can be stubbed
@@ -1311,8 +1316,7 @@ self =>
val cond = condExpr()
newLinesOpt()
val thenp = expr()
- val elsep = if (in.token == ELSE) { in.nextToken(); expr() }
- else literalUnit
+ val elsep = if (acceptIfPresent(ELSE)) expr() else literalUnit
If(cond, thenp, elsep)
}
parseIf
@@ -1321,23 +1325,19 @@ self =>
val body = in.token match {
case LBRACE => inBracesOrUnit(block())
case LPAREN => inParensOrUnit(expr())
- case _ => expr()
+ case _ => expr()
}
def catchFromExpr() = List(makeCatchFromExpr(expr()))
- val catches: List[CaseDef] =
- if (in.token != CATCH) Nil
- else {
- in.nextToken()
+ val catches: List[CaseDef] = (
+ if (!acceptIfPresent(CATCH)) Nil else {
if (in.token != LBRACE) catchFromExpr()
else inBracesOrNil {
if (isCaseDefStart) caseClauses()
else catchFromExpr()
}
}
- val finalizer = in.token match {
- case FINALLY => in.nextToken(); expr()
- case _ => EmptyTree
- }
+ )
+ val finalizer = if (acceptIfPresent(FINALLY)) expr() else EmptyTree
Try(body, catches, finalizer)
}
parseTry
@@ -1348,7 +1348,7 @@ self =>
val cond = condExpr()
newLinesOpt()
val body = expr()
- makeWhile(start, cond, body)
+ makeWhile(cond, body)
}
}
parseWhile
@@ -1367,16 +1367,15 @@ self =>
case FOR =>
val start = in.skipToken()
def parseFor = atPos(start) {
- val enums =
+ val enums = (
if (in.token == LBRACE) inBracesOrNil(enumerators())
else inParensOrNil(enumerators())
+ )
newLinesOpt()
- if (in.token == YIELD) {
- in.nextToken()
+ if (acceptIfPresent(YIELD))
makeForYield(enums, expr())
- } else {
+ else
makeFor(enums, expr())
- }
}
def adjustStart(tree: Tree) =
if (tree.pos.isRange && start < tree.pos.start)
@@ -1403,7 +1402,7 @@ self =>
if (in.token == EQUALS) {
t match {
case Ident(_) | Select(_, _) | Apply(_, _) =>
- t = atPos(t.pos.startOrPoint, in.skipToken()) { makeAssign(t, expr()) }
+ t = atPos(t.pos.startOrPoint, in.skipToken()) { gen.mkAssign(t, expr()) }
case _ =>
}
} else if (in.token == COLON) {
@@ -1467,9 +1466,8 @@ self =>
val param0 = convertToParam {
atPos(in.offset) {
Ident(ident()) match {
- case expr if in.token == COLON =>
- in.nextToken() ; Typed(expr, typeOrInfixType(location))
- case expr => expr
+ case expr if acceptIfPresent(COLON) => Typed(expr, typeOrInfixType(location))
+ case expr => expr
}
}
}
@@ -1545,32 +1543,28 @@ self =>
* }}}
*/
def simpleExpr(): Tree = {
- var canApply = true
- val t =
- if (isLiteral) literal()
- else in.token match {
- case XMLSTART =>
- xmlLiteral()
- case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
- path(thisOK = true, typeOK = false)
- case USCORE =>
- freshPlaceholder()
- case LPAREN =>
- atPos(in.offset)(makeParens(commaSeparated(expr())))
- case LBRACE =>
- canApply = false
- blockExpr()
- case NEW =>
- canApply = false
- val nstart = in.skipToken()
- val npos = r2p(nstart, nstart, in.lastOffset)
- val tstart = in.offset
- val (parents, self, stats) = template()
- val cpos = r2p(tstart, tstart, in.lastOffset max tstart)
- gen.mkNew(parents, self, stats, npos, cpos)
- case _ =>
- syntaxErrorOrIncompleteAnd("illegal start of simple expression", skipIt = true)(errorTermTree)
- }
+ val canApply = in.token match {
+ case LBRACE | NEW => false
+ case _ => true
+ }
+ def mkNew(): Tree = {
+ val npos = skipTokenRange()
+ val tstart = in.offset
+ val (parents, self, stats) = template()
+ val cpos = rangeSince(tstart)
+
+ gen.mkNew(parents, self, stats, npos, cpos)
+ }
+ val t = in.token match {
+ case _ if isLiteral => literal()
+ case XMLSTART => xmlLiteral()
+ case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER => path(thisOK = true, typeOK = false)
+ case USCORE => freshPlaceholder()
+ case LPAREN => atPos(in.offset)(makeParens(commaSeparated(expr())))
+ case LBRACE => blockExpr()
+ case NEW => mkNew()
+ case _ => syntaxErrorOrIncompleteAnd("illegal start of simple expression", skipIt = true)(errorTermTree)
+ }
simpleExprRest(t, canApply = canApply)
}
@@ -1677,9 +1671,9 @@ self =>
* Guard ::= if PostfixExpr
* }}}
*/
- def guard(): Tree =
- if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) }
- else EmptyTree
+ def guard(): Tree = if (acceptIfPresent(IF)) guardExpr() else EmptyTree
+
+ def guardExpr(): Tree = stripParens(postfixExpr())
/** {{{
* Enumerators ::= Generator {semi Enumerator}
@@ -1704,27 +1698,26 @@ self =>
* }}}
*/
def generator(enums: ListBuffer[Enumerator], eqOK: Boolean) {
- val start = in.offset
- val hasVal = in.token == VAL
- if (hasVal)
- in.nextToken()
+ val start = in.offset
+ val hasVal = acceptIfPresent(VAL)
+ val pat = noSeq.pattern1()
+ val point = in.offset
+ val equalsBody = equalsExprOpt()
+ val hasEq = !equalsBody.isEmpty
+
+ if (hasVal && !hasEq)
+ syntaxError(in.offset, "val in for comprehension must be followed by assignment")
+ else if (hasEq && !eqOK)
+ syntaxError(point, "for comprehension must start with generator: " + expectedMsg(expected = LARROW, found = EQUALS))
+ else if (hasVal)
+ deprecationWarning(start, "val keyword in for comprehension is deprecated")
+
+ val rhs = equalsBody orElse { accept(LARROW) ; expr() }
- val pat = noSeq.pattern1()
- val point = in.offset
- val hasEq = in.token == EQUALS
-
- if (hasVal) {
- if (hasEq) deprecationWarning(in.offset, "val keyword in for comprehension is deprecated")
- else syntaxError(in.offset, "val in for comprehension must be followed by assignment")
- }
-
- if (hasEq && eqOK) in.nextToken()
- else accept(LARROW)
- val rhs = expr()
enums += makeGenerator(r2p(start, point, in.lastOffset max start), pat, hasEq, rhs)
// why max above? IDE stress tests have shown that lastOffset could be less than start,
// I guess this happens if instead if a for-expression we sit on a closing paren.
- while (in.token == IF) enums += makeFilter(in.offset, guard())
+ enums ++= tokenSeparated(IF, sepFirst = true, makeFilter(in.offset, guardExpr()))
}
def makeFilter(start: Int, tree: Tree) = Filter(r2p(start, tree.pos.point, tree.pos.endOrPoint), tree)
@@ -1832,14 +1825,6 @@ self =>
var top = simplePattern(badPattern3)
// after peekahead
def acceptWildStar() = atPos(top.pos.startOrPoint, in.prev.offset)(Star(stripParens(top)))
- def peekahead() = {
- in.prev copyFrom in
- in.nextToken()
- }
- def pushback() = {
- in.next copyFrom in
- in copyFrom in.prev
- }
// See SI-3189, SI-4832 for motivation. Cf SI-3480 for counter-motivation.
// TODO: dredge out the remnants of regexp patterns.
// /{/ peek for _*) or _*} (for xml escape)
@@ -2013,16 +1998,15 @@ self =>
* }}}
*/
def accessQualifierOpt(mods: Modifiers): Modifiers = {
- var result = mods
- if (in.token == LBRACKET) {
- in.nextToken()
- if (mods.hasAccessBoundary)
- syntaxError("duplicate private/protected qualifier", skipIt = false)
- result = if (in.token == THIS) { in.nextToken(); mods | Flags.LOCAL }
- else Modifiers(mods.flags, identForType())
- accept(RBRACKET)
+ def newModifiers(): Modifiers = (
+ if (acceptIfPresent(THIS)) mods | Flags.LOCAL // private/protected[this]
+ else Modifiers(mods.flags, identForType()) // private/protected[foo]
+ )
+ in.token match {
+ case LBRACKET if mods.hasAccessBoundary => syntaxError("duplicate private/protected qualifier", skipIt = false) ; mods
+ case LBRACKET => inBrackets(newModifiers())
+ case _ => mods
}
- result
}
private val flagTokens: Map[Int, Long] = Map(
@@ -2160,25 +2144,24 @@ self =>
}
paramType()
}
- val default =
- if (in.token == EQUALS) {
- in.nextToken()
+ val default = (
+ if (acceptIfPresent(EQUALS)) {
mods |= Flags.DEFAULTPARAM
expr()
- } else EmptyTree
+ }
+ else EmptyTree
+ )
atPos(start, if (name == nme.ERROR) start else nameOffset) {
ValDef((mods | implicitmod.toLong | bynamemod) withAnnotations annots, name.toTermName, tpt, default)
}
}
- def paramClause(): List[ValDef] = {
- if (in.token == RPAREN)
- return Nil
+ def paramClause(): List[ValDef] = in.token match {
+ case RPAREN => Nil
+ case _ =>
+ if (acceptIfPresent(IMPLICIT))
+ implicitmod = Flags.IMPLICIT
- if (in.token == IMPLICIT) {
- in.nextToken()
- implicitmod = Flags.IMPLICIT
- }
- commaSeparated(param())
+ commaSeparated(param())
}
val vds = new ListBuffer[List[ValDef]]
val start = in.offset
@@ -2186,8 +2169,7 @@ self =>
if (ofCaseClass && in.token != LPAREN)
syntaxError(in.lastOffset, "case classes without a parameter list are not allowed;\n"+
"use either case objects or case classes with an explicit `()' as a parameter list.")
- while (implicitmod == 0 && in.token == LPAREN) {
- in.nextToken()
+ while (implicitmod == 0 && acceptIfPresent(LPAREN)) {
vds += paramClause()
accept(RPAREN)
caseParam = false
@@ -2211,18 +2193,16 @@ self =>
def paramType(): Tree = paramType(useStartAsPosition = false)
def paramType(useStartAsPosition: Boolean): Tree = {
val start = in.offset
- in.token match {
- case ARROW =>
+ if (acceptIfPresent(ARROW))
+ atPos(start)(byNameApplication(typ()))
+ else {
+ val t = typ()
+ if (isRawStar) {
in.nextToken()
- atPos(start)(byNameApplication(typ()))
- case _ =>
- val t = typ()
- if (isRawStar) {
- in.nextToken()
- if (useStartAsPosition) atPos(start)(repeatedApplication(t))
- else atPos(t.pos.startOrPoint, t.pos.point)(repeatedApplication(t))
- }
- else t
+ if (useStartAsPosition) atPos(start)(repeatedApplication(t))
+ else atPos(t.pos.startOrPoint, t.pos.point)(repeatedApplication(t))
+ }
+ else t
}
}
@@ -2257,14 +2237,13 @@ self =>
}
if (contextBoundBuf ne null) {
while (in.token == VIEWBOUND) {
- contextBoundBuf += atPos(in.skipToken()) {
- makeFunctionTypeTree(List(Ident(pname)), typ())
- }
+ contextBoundBuf += atPos(in.skipToken())(makeFunctionTypeTree(List(Ident(pname)), typ()))
}
while (in.token == COLON) {
- contextBoundBuf += atPos(in.skipToken()) {
- AppliedTypeTree(typ(), List(Ident(pname)))
- }
+ val start = in.skipToken()
+ val tycon = typ()
+ val applied = atPos(tycon.pos withStart start)(AppliedTypeTree(tycon, Ident(pname) :: Nil))
+ contextBoundBuf += applied
}
}
param
@@ -2290,7 +2269,7 @@ self =>
t setPos o2p(in.offset)
}
- def bound(tok: Int): Tree = if (in.token == tok) { in.nextToken(); typ() } else EmptyTree
+ def bound(tok: Int): Tree = if (acceptIfPresent(tok)) typ() else EmptyTree
/* -------- DEFS ------------------------------------------- */
@@ -2302,11 +2281,10 @@ self =>
def importClause(): List[Tree] = {
val offset = accept(IMPORT)
commaSeparated(importExpr()) match {
- case Nil => Nil
+ case Nil => Nil
case t :: rest =>
// The first import should start at the position of the keyword.
- t.setPos(t.pos.withStart(offset))
- t :: rest
+ (t setPos (t.pos withStart offset)) :: rest
}
}
@@ -2335,12 +2313,9 @@ self =>
case _ =>
val nameOffset = in.offset
val name = ident()
- if (in.token == DOT) {
+ if (acceptIfPresent(DOT))
// import foo.bar.ident.<unknown> and so create a select node and recurse.
- val t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name))
- in.nextToken()
- return loop(t)
- }
+ return loop(atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name)))
// import foo.bar.Baz;
else List(makeImportSelector(name, nameOffset))
}
@@ -2371,30 +2346,27 @@ self =>
selectors
}
- def wildcardOrIdent() = {
- if (in.token == USCORE) { in.nextToken() ; nme.WILDCARD }
- else ident()
- }
+ def wildcardOrIdent() = if (acceptIfPresent(USCORE)) nme.WILDCARD else ident()
/** {{{
* ImportSelector ::= Id [`=>' Id | `=>' `_']
* }}}
*/
def importSelector(): ImportSelector = {
- val start = in.offset
- val name = wildcardOrIdent()
- var renameOffset = -1
- val rename = in.token match {
- case ARROW =>
- in.nextToken()
- renameOffset = in.offset
- wildcardOrIdent()
- case _ if name == nme.WILDCARD => null
- case _ =>
- renameOffset = start
- name
- }
- ImportSelector(name, start, rename, renameOffset)
+ val start = in.offset
+ val name = wildcardOrIdent()
+
+ // The first case is overly cleverly using named arguments to reverse the
+ // positions of the last two parameters, because reading the rename will
+ // move the value of in.offset. Hey, I didn't invent side effects, I too am
+ // a victim here. I can't find a single place where the rename position
+ // is used anyway.
+ if (acceptIfPresent(ARROW))
+ ImportSelector(name, start, renamePos = in.offset, rename = wildcardOrIdent())
+ else if (name == nme.WILDCARD)
+ ImportSelector(name, start, null, -1)
+ else
+ ImportSelector(name, start, name, start)
}
/** {{{
@@ -2433,6 +2405,8 @@ self =>
defOrDcl(caseAwareTokenOffset, modifiers() withAnnotations annots)
}
+ def equalsExprOpt(): Tree = if (acceptIfPresent(EQUALS)) expr() else EmptyTree
+
/** {{{
* PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
* ValDcl ::= Id {`,' Id} `:' Type
@@ -2440,45 +2414,55 @@ self =>
* }}}
*/
def patDefOrDcl(pos : Int, mods: Modifiers): List[Tree] = {
- var newmods = mods
in.nextToken()
- val lhs = commaSeparated(stripParens(noSeq.pattern2()))
- val tp = typedOpt()
- val rhs =
- if (tp.isEmpty || in.token == EQUALS) {
- accept(EQUALS)
- if (!tp.isEmpty && newmods.isMutable &&
- (lhs.toList forall (_.isInstanceOf[Ident])) && in.token == USCORE) {
- in.nextToken()
- newmods = newmods | Flags.DEFAULTINIT
- EmptyTree
- } else {
- expr()
- }
- } else {
- newmods = newmods | Flags.DEFERRED
- EmptyTree
- }
- def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
- //Console.println("DEBUG: p = "+p.toString()); // DEBUG
- val trees =
- makePatDef(newmods,
- if (tp.isEmpty) p
- else Typed(p, tp) setPos (p.pos union tp.pos),
- rhs)
- if (newmods.isDeferred) {
- trees match {
- case List(ValDef(_, _, _, EmptyTree)) =>
- if (mods.isLazy) syntaxError(p.pos, "lazy values may not be abstract", skipIt = false)
- case _ => syntaxError(p.pos, "pattern definition may not be abstract", skipIt = false)
- }
+
+ val lhses = commaSeparated(stripParens(noSeq.pattern2()))
+ val lhs = lhses.last
+ val tpt = typedOpt()
+ val ascriptedLhs = if (tpt.isEmpty) lhs else atPos(lhs.pos union tpt.pos)(Typed(lhs, tpt))
+ val hasEq = acceptIfPresent(EQUALS)
+ // SI-7854 an underscore following the equals doesn't necessarily mean default initialization.
+ val isDefaultInit = hasEq && in.token == USCORE && {
+ peekahead()
+ isStatSep || isStatSeqEnd || { pushback() ; false }
+ }
+ val rhs = if (hasEq && !isDefaultInit) expr() else EmptyTree
+ def allIdents = lhses forall (_.isInstanceOf[Ident])
+
+ def defaultInitFlag(): Long = {
+ if (!allIdents)
+ syntaxError(lhs.pos, "pattern definition is ineligible for default initialization", skipIt = false)
+ else if (!mods.isMutable)
+ syntaxError(lhs.pos, "only vars are eligible for default initialization", skipIt = false)
+ else if (tpt.isEmpty)
+ syntaxError(lhs.pos, "an explicit type is required for default initialization", skipIt = false)
+
+ Flags.DEFAULTINIT
+ }
+ def deferredFlag(): Long = {
+ if (mods.isLazy) // e.g. lazy val foo: Int
+ syntaxError(lhs.pos, "lazy values may not be abstract", skipIt = false)
+ else if (!allIdents) // e.g. val Some(x)
+ syntaxError(lhs.pos, "pattern definition may not be abstract", skipIt = false)
+
+ Flags.DEFERRED
+ }
+ val newmods = mods | (
+ if (isDefaultInit) defaultInitFlag()
+ else if (rhs.isEmpty) deferredFlag()
+ else 0L
+ )
+
+ def makeValDefs(decl: Tree): List[Tree] = {
+ val newTpt = if (tpt.isEmpty) decl else Typed(decl, tpt.duplicate setPos tpt.pos.focus) setPos decl.pos.focus
+ makePatDef(newmods, newTpt, rhs.duplicate setPos rhs.pos.focus) match {
+ case tree :: Nil => (tree setPos decl.pos) :: Nil
+ case trees => trees map (_ setPos decl.pos.focus)
}
- trees
}
- val trees = (lhs.toList.init flatMap (mkDefs(_, tp.duplicate, rhs.duplicate))) ::: mkDefs(lhs.last, tp, rhs)
- val hd = trees.head
- hd setPos hd.pos.withStart(pos)
- ensureNonOverlapping(hd, trees.tail)
+
+ val trees = (lhses.init flatMap makeValDefs) ::: makePatDef(newmods, ascriptedLhs, rhs)
+ ensureNonOverlapping(trees.last, trees.init)
trees
}
@@ -2523,7 +2507,8 @@ self =>
in.nextToken()
if (in.token == THIS) {
atPos(start, in.skipToken()) {
- val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), ofCaseClass = false)
+ val cbounds = classContextBounds map (_.duplicate)
+ val vparamss = paramClauses(nme.CONSTRUCTOR, cbounds, ofCaseClass = false)
newLineOptWhenFollowedBy(LBRACE)
val rhs = in.token match {
case LBRACE => atPos(in.offset) { constrBlock(vparamss) }
@@ -2547,7 +2532,8 @@ self =>
// i.e. (B[T] or T => B)
val contextBoundBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, contextBoundBuf)
- val vparamss = paramClauses(name, contextBoundBuf.toList, ofCaseClass = false)
+ val cbounds = contextBoundBuf.toList
+ val vparamss = paramClauses(name, cbounds, ofCaseClass = false)
newLineOptWhenFollowedBy(LBRACE)
var restype = fromWithinReturnType(typedOpt())
val rhs =
@@ -2707,8 +2693,9 @@ self =>
val result = gen.mkClassDef(mods1, name, tparams, template)
// Context bounds generate implicit parameters (part of the template) with types
// from tparams: we need to ensure these don't overlap
- if (!classContextBounds.isEmpty)
+ if (classContextBounds.nonEmpty)
ensureNonOverlapping(template, tparams)
+
result
}
}
@@ -2770,18 +2757,15 @@ self =>
* }}}
*/
def templateParents(): List[Tree] = {
- val parents = new ListBuffer[Tree]
- def readAppliedParent() = {
+ def readAppliedParent(): Tree = {
val start = in.offset
val parent = startAnnotType()
- parents += (in.token match {
+ in.token match {
case LPAREN => atPos(start)((parent /: multipleArgumentExprs())(Apply.apply))
case _ => parent
- })
+ }
}
- readAppliedParent()
- while (in.token == WITH) { in.nextToken(); readAppliedParent() }
- parents.toList
+ tokenSeparated(WITH, sepFirst = false, readAppliedParent())
}
/** {{{
@@ -2815,9 +2799,9 @@ self =>
def ensureEarlyDef(tree: Tree): Tree = tree match {
case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred =>
copyValDef(vdef)(mods = mods | Flags.PRESUPER)
- case tdef @ TypeDef(mods, name, tparams, rhs) =>
+ case tdef @ TypeDef(mods, _, _, _) =>
deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.")
- treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs)
+ copyTypeDef(tdef)(mods = mods | Flags.PRESUPER)
case docdef @ DocDef(comm, rhs) =>
treeCopy.DocDef(docdef, comm, rhs)
case stat if !stat.isEmpty =>
@@ -2852,7 +2836,6 @@ self =>
)
val parentPos = o2p(in.offset)
val tstart1 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart
-
atPos(tstart1) {
// Exclude only the 9 primitives plus AnyVal.
if (inScalaRootPackage && ScalaValueClassNames.contains(name))
@@ -3103,10 +3086,9 @@ self =>
def compilationUnit(): PackageDef = checkNoEscapingPlaceholders {
def topstats(): List[Tree] = {
val ts = new ListBuffer[Tree]
- while (in.token == SEMI) in.nextToken()
+ while (acceptIfPresent(SEMI)) ()
val start = in.offset
- if (in.token == PACKAGE) {
- in.nextToken()
+ if (acceptIfPresent(PACKAGE)) {
if (in.token == OBJECT) {
// TODO - this next line is supposed to be
// ts += packageObjectDef(start)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 6957f85689..5ef40923b4 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -52,6 +52,15 @@ trait Scanners extends ScannersCommon {
type Offset = Int
trait TokenData extends CommonTokenData {
+ override def toString = s"""
+ |TokenData(
+ | token $token ${token2string(token)}
+ | offset $offset
+ | last $lastOffset
+ | name $name
+ | strVal $strVal
+ | base $base
+ |)""".stripMargin.trim
/** the next token */
var token: Int = EMPTY
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 91ff530e05..fba74330a6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -191,14 +191,6 @@ abstract class TreeBuilder {
}
}
- /** Create a tree representing an assignment <lhs = rhs> */
- def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
- case Apply(fn, args) =>
- Apply(atPos(fn.pos) { Select(fn, nme.update) }, args ::: List(rhs))
- case _ =>
- Assign(lhs, rhs)
- }
-
/** Tree for `od op`, start is start0 if od.pos is borked. */
def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = {
val start = if (od.pos.isDefined) od.pos.startOrPoint else start0
@@ -206,22 +198,21 @@ abstract class TreeBuilder {
}
/** Create tree representing a while loop */
- def makeWhile(startPos: Int, cond: Tree, body: Tree): Tree = {
- val lname = freshTermName(nme.WHILE_PREFIX)
- def default = wrappingPos(List(cond, body)) match {
- case p if p.isDefined => p.endOrPoint
- case _ => startPos
- }
- val continu = atPos(o2p(body.pos pointOrElse default)) { Apply(Ident(lname), Nil) }
- val rhs = If(cond, Block(List(body), continu), Literal(Constant(())))
- LabelDef(lname, Nil, rhs)
+ def makeWhile(cond: Tree, body: Tree): Tree = {
+ val lname = freshTermName(nme.WHILE_PREFIX)
+ val continu = atPos(cond.pos.focus)(Apply(Ident(lname), Nil))
+ val rhs = atPos(cond.pos union body.pos)(If(cond, atPos(body.pos)(Block(body :: Nil, continu)), Literal(Constant(()))))
+
+ atPos(rhs.pos)(LabelDef(lname, Nil, rhs))
}
/** Create tree representing a do-while loop */
def makeDoWhile(lname: TermName, body: Tree, cond: Tree): Tree = {
- val continu = Apply(Ident(lname), Nil)
- val rhs = Block(List(body), If(cond, continu, Literal(Constant(()))))
- LabelDef(lname, Nil, rhs)
+ val continu = atPos(cond.pos.focus)(Apply(Ident(lname), Nil))
+ val condition = atPos(cond.pos)(If(cond, continu, Literal(Constant(()))))
+ val rhs = atPos(cond.pos union body.pos)(Block(body :: Nil, condition))
+
+ atPos(rhs.pos)(LabelDef(lname, Nil, rhs))
}
/** Create block of statements `stats` */
@@ -313,19 +304,13 @@ abstract class TreeBuilder {
* The closure is assigned a transparent position with the point at pos.point and
* the limits given by pat and body.
*/
- def makeClosure(pos: Position, pat: Tree, body: Tree): Tree = {
- def splitpos = wrappingPos(List(pat, body)).withPoint(pos.point).makeTransparent
- matchVarPattern(pat) match {
- case Some((name, tpt)) =>
- Function(
- List(atPos(pat.pos) { ValDef(Modifiers(PARAM), name.toTermName, tpt, EmptyTree) }),
- body) setPos splitpos
- case None =>
- atPos(splitpos) {
- makeVisitor(List(CaseDef(pat, EmptyTree, body)), checkExhaustive = false)
- }
+ def makeClosure(pos: Position, pat: Tree, body: Tree): Tree =
+ atPos((pos union pat.pos union body.pos).makeTransparent) {
+ matchVarPattern(pat) match {
+ case Some((name, tpt)) => Function(atPos(pat.pos)(ValDef(Modifiers(PARAM), name.toTermName, tpt, EmptyTree)) :: Nil, body)
+ case None => makeVisitor(CaseDef(pat, body) :: Nil, checkExhaustive = false)
+ }
}
- }
/* Make an application qual.meth(pat => body) positioned at `pos`.
*/
@@ -503,7 +488,7 @@ abstract class TreeBuilder {
tmp, TypeTree(), matchExpr)
}
var cnt = 0
- val restDefs = for ((vname, tpt, pos) <- vars) yield atPos(pos) {
+ val restDefs = for ((vname, tpt, pos) <- vars) yield atPos(pos.focus) {
cnt += 1
ValDef(mods, vname.toTermName, tpt, Select(Ident(tmp), newTermName("_" + cnt)))
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/CheckerException.scala b/src/compiler/scala/tools/nsc/backend/icode/CheckerException.scala
index 0856f2f09d..8bcdb6dbd2 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/CheckerException.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/CheckerException.scala
@@ -3,10 +3,8 @@
* @author Martin Odersky
*/
-
package scala.tools.nsc
package backend
package icode
class CheckerException(s: String) extends Exception(s)
-
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 843299398b..a80fee876e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1319,6 +1319,8 @@ abstract class GenICode extends SubComponent {
/** Some useful equality helpers.
*/
def isNull(t: Tree) = cond(t) { case Literal(Constant(null)) => true }
+ def isLiteral(t: Tree) = cond(t) { case Literal(_) => true }
+ def isNonNullExpr(t: Tree) = isLiteral(t) || ((t.symbol ne null) && t.symbol.isModule)
/* If l or r is constant null, returns the other ; otherwise null */
def ifOneIsNull(l: Tree, r: Tree) = if (isNull(l)) r else if (isNull(r)) l else null
@@ -1514,6 +1516,23 @@ abstract class GenICode extends SubComponent {
val branchesReachable = !ctx1.bb.ignore
ctx1.bb emitOnly CZJUMP(thenCtx.bb, elseCtx.bb, EQ, ObjectReference)
branchesReachable
+ } else if (isNonNullExpr(l)) {
+ // Avoid null check if L is statically non-null.
+ //
+ // "" == expr -> "".equals(expr)
+ // Nil == expr -> Nil.equals(expr)
+ //
+ // Common enough (through pattern matching) to treat this specially here rather than
+ // hoping that -Yconst-opt is enabled. The impossible branches for null checks lead
+ // to spurious "branch not covered" warnings in Jacoco code coverage.
+ var ctx1 = genLoad(l, ctx, ObjectReference)
+ val branchesReachable = !ctx1.bb.ignore
+ ctx1 = genLoad(r, ctx1, ObjectReference)
+ ctx1.bb emitOnly(
+ CALL_METHOD(Object_equals, Dynamic),
+ CZJUMP(thenCtx.bb, elseCtx.bb, NE, BOOL)
+ )
+ branchesReachable
} else {
val eqEqTempLocal = getTempLocal
var ctx1 = genLoad(l, ctx, ObjectReference)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 2c8fda85f4..633e71a756 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -93,7 +93,7 @@ trait TypeKinds { self: ICodes =>
/**
* this is directly assignable to other if no coercion or
* casting is needed to convert this to other. It's a distinct
- * relationship from <:< because on the JVM, BOOL, BYTE, CHAR,
+ * relationship from <:< because on the JVM, BOOL, BYTE, CHAR,
* SHORT need no coercion to INT even though JVM arrays
* are covariant, ARRAY[SHORT] is not a subtype of ARRAY[INT]
*/
@@ -101,7 +101,7 @@ trait TypeKinds { self: ICodes =>
case INT => this.isIntSizedType
case _ => this <:< other
}
-
+
/** Is this type a category 2 type in JVM terms? (ie, is it LONG or DOUBLE?) */
def isWideType: Boolean = false
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 182209dfe6..eff7d3211e 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -866,11 +866,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
// a plain class lacking companion module, for details see `isCandidateForForwarders`).
// -----------------------------------------------------------------------------------------
- val ExcludedForwarderFlags = {
- import symtab.Flags._
- // Should include DEFERRED but this breaks findMember.
- ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO )
- }
+ val ExcludedForwarderFlags = genASM.ExcludedForwarderFlags
/* Adds a @remote annotation, actual use unknown.
*
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala
index 2c3bf26958..01c4ff5a52 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala
@@ -18,10 +18,10 @@ trait GenJVMASM {
import icodes._
import definitions._
- protected val ExcludedForwarderFlags = {
+ val ExcludedForwarderFlags = {
import Flags._
// Should include DEFERRED but this breaks findMember.
- ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO )
+ ( SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO )
}
protected def isJavaEntryPoint(icls: IClass) = {
diff --git a/src/compiler/scala/tools/nsc/package.scala b/src/compiler/scala/tools/nsc/package.scala
index 761fd79358..817a4a5c88 100644
--- a/src/compiler/scala/tools/nsc/package.scala
+++ b/src/compiler/scala/tools/nsc/package.scala
@@ -23,5 +23,6 @@ package object nsc {
type MissingRequirementError = scala.reflect.internal.MissingRequirementError
val MissingRequirementError = scala.reflect.internal.MissingRequirementError
- val ListOfNil = List(Nil)
+ @deprecated("Use scala.reflect.internal.util.ListOfNil", "2.11.0")
+ lazy val ListOfNil = scala.reflect.internal.util.ListOfNil
}
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index fdb5c72c3d..52c6ddc6ee 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -9,6 +9,7 @@ package reporters
import java.io.{ BufferedReader, IOException, PrintWriter }
import scala.reflect.internal.util._
+import StringOps._
/**
* This class implements a Reporter that displays messages on a text
@@ -40,7 +41,10 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
StringOps.countElementsAsString((severity).count, label(severity))
/** Prints the message. */
- def printMessage(msg: String) { writer.print(msg + "\n"); writer.flush() }
+ def printMessage(msg: String) {
+ writer print trimAllTrailingSpace(msg) + "\n"
+ writer.flush()
+ }
/** Prints the message with the given position indication. */
def printMessage(posIn: Position, msg: String) {
diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
index 34c8e8df9a..8c2b510bfd 100644
--- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
@@ -44,7 +44,7 @@ class FscSettings(error: String => Unit) extends Settings(error) {
// we need to ensure the files specified with relative locations are absolutized based on the currentDir
(r, args map {a => absolutizePath(a)})
}
-
+
/**
* Take an individual path and if it's not absolute turns it into an absolute path based on currentDir.
* If it's already absolute then it's left alone.
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index a2bf5bf9e5..b2e071579e 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -90,7 +90,7 @@ abstract class ExplicitOuter extends InfoTransform
sym expandName clazz
sym.referenced = clazz
- sym setInfo MethodType(Nil, restpe.widen)
+ sym setInfo MethodType(Nil, restpe)
}
def newOuterField(clazz: Symbol) = {
val accFlags = SYNTHETIC | ARTIFACT | PARAMACCESSOR | ( if (clazz.isEffectivelyFinal) PrivateLocal else PROTECTED )
@@ -276,18 +276,16 @@ abstract class ExplicitOuter extends InfoTransform
else outerPath(outerSelect(base), from.outerClass, to)
}
-
override def transform(tree: Tree): Tree = {
+ def sym = tree.symbol
val savedOuterParam = outerParam
try {
tree match {
case Template(_, _, _) =>
outerParam = NoSymbol
- case DefDef(_, _, _, vparamss, _, _) =>
- if (tree.symbol.isClassConstructor && isInner(tree.symbol.owner)) {
- outerParam = vparamss.head.head.symbol
- assert(outerParam.name startsWith nme.OUTER, outerParam.name)
- }
+ case DefDef(_, _, _, (param :: _) :: _, _, _) if sym.isClassConstructor && isInner(sym.owner) =>
+ outerParam = param.symbol
+ assert(outerParam.name startsWith nme.OUTER, outerParam.name)
case _ =>
}
super.transform(tree)
@@ -361,10 +359,9 @@ abstract class ExplicitOuter extends InfoTransform
/** The definition tree of the outer accessor of current class
*/
def outerAccessorDef: Tree = localTyper typed {
- outerAccessor(currentClass) match {
- case acc if acc.isDeferred => DefDef(acc, EmptyTree)
- case acc => DefDef(acc, Select(This(currentClass), outerField(currentClass)))
- }
+ val acc = outerAccessor(currentClass)
+ val rhs = if (acc.isDeferred) EmptyTree else Select(This(currentClass), outerField(currentClass))
+ DefDef(acc, rhs)
}
/** The definition tree of the outer accessor for class mixinClass.
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 45aa1106f0..f7b194a6ca 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -292,6 +292,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis {
type Type = global.Type
type Tree = global.Tree
+ import global.definitions.ConstantNull
// resets hash consing -- only supposed to be called by TreeMakersToProps
def prepareNewAnalysis(): Unit = { Var.resetUniques(); Const.resetUniques() }
@@ -320,7 +321,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
val staticTpCheckable: Type = checkableType(staticTp)
private[this] var _mayBeNull = false
- def registerNull(): Unit = { ensureCanModify(); if (NullTp <:< staticTpCheckable) _mayBeNull = true }
+ def registerNull(): Unit = { ensureCanModify(); if (ConstantNull <:< staticTpCheckable) _mayBeNull = true }
def mayBeNull: Boolean = _mayBeNull
// case None => domain is unknown,
@@ -568,7 +569,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
object TypeConst extends TypeConstExtractor {
def apply(tp: Type) = {
- if (tp =:= NullTp) NullConst
+ if (tp =:= ConstantNull) NullConst
else if (tp.isInstanceOf[SingletonType]) ValueConst.fromType(tp)
else Const.unique(tp, new TypeConst(tp))
}
@@ -577,7 +578,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
// corresponds to a type test that does not imply any value-equality (well, except for outer checks, which we don't model yet)
sealed class TypeConst(val tp: Type) extends Const {
- assert(!(tp =:= NullTp))
+ assert(!(tp =:= ConstantNull))
/*private[this] val id: Int = */ Const.nextTypeId
val wideTp = widenToClass(tp)
@@ -598,7 +599,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
}
def apply(p: Tree) = {
val tp = p.tpe.normalize
- if (tp =:= NullTp) NullConst
+ if (tp =:= ConstantNull) NullConst
else {
val wideTp = widenToClass(tp)
@@ -626,16 +627,14 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
}
sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const {
// debug.patmat("VC"+(tp, wideTp, toString))
- assert(!(tp =:= NullTp)) // TODO: assert(!tp.isStable)
+ assert(!(tp =:= ConstantNull)) // TODO: assert(!tp.isStable)
/*private[this] val id: Int = */Const.nextValueId
def isValue = true
}
-
- lazy val NullTp = ConstantType(Constant(null))
case object NullConst extends Const {
- def tp = NullTp
- def wideTp = NullTp
+ def tp = ConstantNull
+ def wideTp = ConstantNull
def isValue = true
override def toString = "null"
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 8feb87210e..7eb899d9d7 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -50,7 +50,7 @@ trait TreeAndTypeAnalysis extends Debugging {
case UnitClass =>
Some(List(UnitTpe))
case BooleanClass =>
- Some((List(ConstantType(Constant(true)), ConstantType(Constant(false)))))
+ Some(ConstantTrue :: ConstantFalse :: Nil)
// TODO case _ if tp.isTupleType => // recurse into component types
case modSym: ModuleClassSymbol =>
Some(List(tp))
@@ -271,9 +271,9 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
case SubstOnlyTreeMaker(_, _) => True
case GuardTreeMaker(guard) =>
guard.tpe match {
- case ConstantType(Constant(true)) => True
- case ConstantType(Constant(false)) => False
- case _ => handleUnknown(tm)
+ case ConstantTrue => True
+ case ConstantFalse => False
+ case _ => handleUnknown(tm)
}
case ExtractorTreeMaker(_, _, _) |
ProductExtractorTreeMaker(_, _) |
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index ba78438b66..8a04c67582 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -402,23 +402,15 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
private def noGuards(cs: List[CaseDef]): Boolean = !cs.exists(isGuardedCase)
// must do this before removing guards from cases and collapsing (SI-6011, SI-6048)
- private def unreachableCase(cs: List[CaseDef]): Option[CaseDef] = {
- var cases = cs
- var unreachable: Option[CaseDef] = None
-
- while (cases.nonEmpty && unreachable.isEmpty) {
- val currCase = cases.head
- if (isDefault(currCase) && cases.tail.nonEmpty) // subsumed by the `else if` that follows, but faster
- unreachable = Some(cases.tail.head)
- else if (!isGuardedCase(currCase) || currCase.guard.tpe =:= ConstantType(Constant(true)))
- unreachable = cases.tail.find(caseImplies(currCase))
- else if (currCase.guard.tpe =:= ConstantType(Constant(false)))
- unreachable = Some(currCase)
-
- cases = cases.tail
+ private def unreachableCase(cases: List[CaseDef]): Option[CaseDef] = {
+ def loop(cases: List[CaseDef]): Option[CaseDef] = cases match {
+ case head :: next :: _ if isDefault(head) => Some(next) // subsumed by the next case, but faster
+ case head :: rest if !isGuardedCase(head) || head.guard.tpe =:= ConstantTrue => rest find caseImplies(head) orElse loop(rest)
+ case head :: _ if head.guard.tpe =:= ConstantFalse => Some(head)
+ case _ :: rest => loop(rest)
+ case _ => None
}
-
- unreachable
+ loop(cases)
}
// empty list ==> failure
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index cf26ec3398..317685682d 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -288,8 +288,8 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
def irrefutableExtractorType(tp: Type): Boolean = tp.resultType.dealias match {
case TypeRef(_, SomeClass, _) => true
// probably not useful since this type won't be inferred nor can it be written down (yet)
- case ConstantType(Constant(true)) => true
- case _ => false
+ case ConstantTrue => true
+ case _ => false
}
def unapply(xtm: ExtractorTreeMaker): Option[(Tree, Symbol)] = xtm match {
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
index 114bcba5df..6267585ea8 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
@@ -9,6 +9,7 @@ package scala.tools.nsc.transform.patmat
import scala.collection.mutable
import scala.reflect.internal.util.Statistics
import scala.language.postfixOps
+import scala.reflect.internal.util.Collections._
// naive CNF translation and simple DPLL solver
trait Solving extends Logic {
@@ -205,9 +206,8 @@ trait Solving extends Logic {
// SI-7020 Linked- for deterministic counter examples.
val pos = new mutable.LinkedHashSet[Sym]()
val neg = new mutable.LinkedHashSet[Sym]()
- f.foreach{_.foreach{ lit =>
- if (lit.pos) pos += lit.sym else neg += lit.sym
- }}
+ mforeach(f)(lit => if (lit.pos) pos += lit.sym else neg += lit.sym)
+
// appearing in both positive and negative
val impures: mutable.LinkedHashSet[Sym] = pos intersect neg
// appearing only in either positive/negative positions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9ac0b0835a..347426d42a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1183,8 +1183,8 @@ trait Namers extends MethodSynthesis {
// value parameters of the base class (whose defaults might be overridden)
var baseParamss = (vparamss, overridden.tpe.paramss) match {
// match empty and missing parameter list
- case (Nil, List(Nil)) => Nil
- case (List(Nil), Nil) => ListOfNil
+ case (Nil, ListOfNil) => Nil
+ case (ListOfNil, Nil) => ListOfNil
case (_, paramss) => paramss
}
assert(
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 3a188c0044..e44c83aa56 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -171,8 +171,8 @@ abstract class TreeCheckers extends Analyzer {
)
- def errorFn(msg: Any): Unit = Console.err println "[check: %s] %s".format(phase.prev, msg)
- def errorFn(pos: Position, msg: Any): Unit = errorFn(posstr(pos) + ": " + msg)
+ def errorFn(pos: Position, msg: Any): Unit = currentUnit.warning(pos, "[check: %s] %s".format(phase.prev, msg))
+ def errorFn(msg: Any): Unit = errorFn(NoPosition, msg)
def informFn(msg: Any) {
if (settings.verbose || settings.debug)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3343ee2bcc..157c6ba4de 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -43,12 +43,17 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
final val shortenImports = false
+ // allows override of the behavior of the resetTyper method w.r.t comments
+ def resetDocComments() = {
+ clearDocComments()
+ }
+
def resetTyper() {
//println("resetTyper called")
resetContexts()
resetImplicits()
transformed.clear()
- clearDocComments()
+ resetDocComments()
}
object UnTyper extends Traverser {
@@ -2606,7 +2611,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
val rhs = methodBodyTyper.virtualizedMatch(match_, mode, B1.tpe)
- val defdef = newDefDef(methodSym, rhs)(vparamss = mapParamss(methodSym)(newParam))
+ val defdef = newDefDef(methodSym, rhs)(vparamss = mapParamss(methodSym)(newParam), tpt = TypeTree(B1.tpe))
(defdef, matchResTp)
}
@@ -4873,7 +4878,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// Unfortunately implicit not found strings looks for all the world like
// missing interpolators.
def isArgToImplicitNotFound = context.enclosingApply.tree match {
- case Apply(fn, _) => fn.symbol.enclClass == ImplicitNotFoundClass
+ case Apply(fn, _) => fn.symbol != null && fn.symbol.enclClass == ImplicitNotFoundClass
case _ => false
}
def warnAbout(s: String) = {
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index b77a536caf..2d905d5436 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -297,7 +297,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
// reporter doesn't accumulate errors, but the front-end does
def throwIfErrors() = {
if (frontEnd.hasErrors) throw ToolBoxError(
- "reflective compilation has failed: " + EOL + EOL + (frontEnd.infos map (_.msg) mkString EOL)
+ "reflective compilation has failed:" + EOL + EOL + (frontEnd.infos map (_.msg) mkString EOL)
)
}
}
@@ -319,7 +319,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
val instance = new ToolBoxGlobal(command.settings, frontEndToReporter(frontEnd, command.settings))
if (frontEnd.hasErrors) {
throw ToolBoxError(
- "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL +
+ "reflective compilation has failed: cannot initialize the compiler:" + EOL + EOL +
(frontEnd.infos map (_.msg) mkString EOL)
)
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index c2d8bcdcd6..0d1fb6be07 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -10,7 +10,7 @@ trait Reifiers { self: Quasiquotes =>
import global.build.{SyntacticClassDef, SyntacticTraitDef, SyntacticModuleDef,
SyntacticDefDef, SyntacticValDef, SyntacticVarDef,
SyntacticBlock, SyntacticApplied, SyntacticTypeApplied,
- SyntacticFunction, SyntacticNew}
+ SyntacticFunction, SyntacticNew, SyntacticAssign}
import global.treeInfo._
import global.definitions._
import Cardinality._
@@ -71,9 +71,9 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs)
case SyntacticVarDef(mods, name, tpt, rhs) =>
reifyBuildCall(nme.SyntacticVarDef, mods, name, tpt, rhs)
- case SyntacticApplied(fun, argss) if argss.length > 1 =>
- reifyBuildCall(nme.SyntacticApplied, fun, argss)
- case SyntacticApplied(fun, argss @ (_ :+ (_ :+ Placeholder(_, _, DotDotDot)))) =>
+ case SyntacticAssign(lhs, rhs) =>
+ reifyBuildCall(nme.SyntacticAssign, lhs, rhs)
+ case SyntacticApplied(fun, argss) if argss.nonEmpty =>
reifyBuildCall(nme.SyntacticApplied, fun, argss)
case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)