diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-18 10:39:14 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-18 10:39:14 -0800 |
commit | 0beca4b2f039fb21222cef29c1b7b5a012df5e61 (patch) | |
tree | a79814df4fcf045f0862489a6f33531a0984796c /src/compiler | |
parent | 9bc68766aa17b3509de1bac0e330ea80b6955cdf (diff) | |
parent | eca51c403066f20e6b82ba55bf6794d165b0a9ab (diff) | |
download | scala-0beca4b2f039fb21222cef29c1b7b5a012df5e61.tar.gz scala-0beca4b2f039fb21222cef29c1b7b5a012df5e61.tar.bz2 scala-0beca4b2f039fb21222cef29c1b7b5a012df5e61.zip |
Merge pull request #3383 from adriaanm/merge-2.10.x
Merge 2.10.x
Diffstat (limited to 'src/compiler')
8 files changed, 47 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 38a6170637..0728fff74f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1030,7 +1030,11 @@ self => /** Assumed (provisionally) to be TermNames. */ def ident(skipIt: Boolean): Name = ( - if (isIdent) rawIdent().encode + if (isIdent) { + val name = in.name.encode + in.nextToken() + name + } else syntaxErrorOrIncompleteAnd(expectedMsg(IDENTIFIER), skipIt)(nme.ERROR) ) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 32c15b04aa..8011abc1ed 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -607,10 +607,7 @@ trait Scanners extends ScannersCommon { if (ch == '`') { nextChar() finishNamed(BACKQUOTED_IDENT) - if (name.length == 0) - syntaxError("empty quoted identifier") - else if (name == nme.WILDCARD) - syntaxError("wildcard invalid as backquoted identifier") + if (name.length == 0) syntaxError("empty quoted identifier") } else syntaxError("unclosed quoted identifier") } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index d44e7a9312..1332d01dbd 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -793,10 +793,7 @@ abstract class GenICode extends SubComponent { case _ => } ctx1.bb.emit(cm, tree.pos) - - if (sym == ctx1.method.symbol) { - ctx1.method.recursive = true - } + ctx1.method.updateRecursive(sym) generatedType = if (sym.isClassConstructor) UNIT else toTypeKind(sym.info.resultType) diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 4d1d59cd12..267fa15312 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -195,6 +195,10 @@ trait Members { this } + final def updateRecursive(called: Symbol): Unit = { + recursive ||= (called == symbol) + } + def addLocal(l: Local): Local = findOrElse(locals)(_ == l) { locals ::= l ; l } def addParam(p: Local): Unit = diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 7e1a82a155..eb40e1dbde 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -469,9 +469,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { } bytecodeWriter.writeClass(label, jclassName, arr, outF) } catch { - case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") => - // TODO check where ASM throws the equivalent of CodeSizeTooBigException - log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).") + case e: java.lang.RuntimeException if e != null && (e.getMessage contains "too large!") => + reporter.error(sym.pos, + s"Could not write class $jclassName because it exceeds JVM code size limits. ${e.getMessage}") } } diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index 4b9e056df3..c2d0f5ccec 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -64,8 +64,10 @@ abstract class BrowsingLoaders extends GlobalSymbolLoaders { addPackagePrefix(pre) packagePrefix += ("." + name) case Ident(name) => - if (packagePrefix.length != 0) packagePrefix += "." - packagePrefix += name + if (name != nme.EMPTY_PACKAGE_NAME) { // mirrors logic in Namers, see createPackageSymbol + if (packagePrefix.length != 0) packagePrefix += "." + packagePrefix += name + } case _ => throw new MalformedInput(pkg.pos.point, "illegal tree node in package prefix: "+pkg) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index f704d8ac89..6ca2205881 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -575,23 +575,28 @@ abstract class ICodeReader extends ClassfileParser { case JVM.invokevirtual => val m = pool.getMemberSymbol(u2, static = false); size += 2 code.emit(CALL_METHOD(m, Dynamic)) + method.updateRecursive(m) case JVM.invokeinterface => val m = pool.getMemberSymbol(u2, static = false); size += 4 in.skip(2) code.emit(CALL_METHOD(m, Dynamic)) + // invokeinterface can't be recursive case JVM.invokespecial => val m = pool.getMemberSymbol(u2, static = false); size += 2 val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(onInstance = true) else SuperCall(m.owner.name) code.emit(CALL_METHOD(m, style)) + method.updateRecursive(m) case JVM.invokestatic => val m = pool.getMemberSymbol(u2, static = true); size += 2 if (isBox(m)) code.emit(BOX(toTypeKind(m.info.paramTypes.head))) else if (isUnbox(m)) code.emit(UNBOX(toTypeKind(m.info.resultType))) - else + else { code.emit(CALL_METHOD(m, Static(onInstance = false))) + method.updateRecursive(m) + } case JVM.invokedynamic => // TODO, this is just a place holder. A real implementation must parse the class constant entry debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 5d0d5392dd..9b7c79b614 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3326,6 +3326,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // calls to the default getters. Example: // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a)) checkNotMacro() + + // SI-8111 transformNamedApplication eagerly shuffles around the application to preserve + // evaluation order. During this process, it calls `changeOwner` on symbols that + // are transplanted underneath synthetic temporary vals. + // + // Here, we keep track of the symbols owned by `context.owner` to enable us to + // rollback, so that we don't end up with "orphaned" symbols. + // + // TODO: Find a better way! + // + // Note that duplicating trees would not be enough to fix this problem, we would also need to + // clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator), + // or, better yet, disentangle the logic in `transformNamedApplication` so that we could + // determine whether names/defaults is viable *before* transforming trees. + def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner + val symsOwnedByContextOwner = tree.collect { + case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol + } + def rollbackNamesDefaultsOwnerChanges() { + symsOwnedByContextOwner foreach (_.owner = context.owner) + } + val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x) if (fun1.isErroneous) duplErrTree else { @@ -3354,6 +3376,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { + rollbackNamesDefaultsOwnerChanges() tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } |