diff options
21 files changed, 412 insertions, 174 deletions
diff --git a/src/build/pack.xml b/src/build/pack.xml index 564d290967..1735b93f3f 100644 --- a/src/build/pack.xml +++ b/src/build/pack.xml @@ -29,10 +29,15 @@ MAIN DISTRIBUTION PACKAGING <tarfileset dir="${dist.dir}" prefix="${dist.name}" excludes="bin/**"/> </tar> <gzip src="${dists.dir}/archives/${dist.name}.tar" destfile="${dists.dir}/archives/${dist.name}.tgz"/> - <exec executable="xz" failifexecutionfails="false"> - <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}.tar"/> - </exec> - <move file="${dists.dir}/archives/${dist.name}.tar.xz" tofile="${dists.dir}/archives/${dist.name}.txz" failonerror="false"/> + <if> + <not><equals arg1="${archives.skipxz}" arg2="true" /></not> + <then> + <exec executable="xz" failifexecutionfails="false"> + <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}.tar"/> + </exec> + <move file="${dists.dir}/archives/${dist.name}.tar.xz" tofile="${dists.dir}/archives/${dist.name}.txz" failonerror="false"/> + </then> + </if> <delete file="${dists.dir}/archives/${dist.name}.tar" /> <checksum fileext=".md5"> <fileset dir="${dists.dir}/archives"> @@ -54,10 +59,15 @@ MAIN DISTRIBUTION PACKAGING <tarfileset dir="${dist.dir}/doc/scala-devel-docs" prefix="${dist.name}-devel-docs"/> </tar> <gzip src="${dists.dir}/archives/${dist.name}-devel-docs.tar" destfile="${dists.dir}/archives/${dist.name}-devel-docs.tgz"/> - <exec executable="xz" failifexecutionfails="false"> - <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-devel-docs.tar"/> - </exec> - <move file="${dists.dir}/archives/${dist.name}-devel-docs.tar.xz" tofile="${dists.dir}/archives/${dist.name}-devel-docs.txz" failonerror="false"/> + <if> + <not><equals arg1="${archives.skipxz}" arg2="true" /></not> + <then> + <exec executable="xz" failifexecutionfails="false"> + <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-devel-docs.tar"/> + </exec> + <move file="${dists.dir}/archives/${dist.name}-devel-docs.tar.xz" tofile="${dists.dir}/archives/${dist.name}-devel-docs.txz" failonerror="false"/> + </then> + </if> <delete file="${dists.dir}/archives/${dist.name}-devel-docs.tar" /> <checksum fileext=".md5"> <fileset dir="${dists.dir}/archives"> @@ -84,10 +94,15 @@ MAIN DISTRIBUTION PACKAGING </tarfileset> </tar> <gzip src="${dists.dir}/archives/${dist.name}-sources.tar" destfile="${dists.dir}/archives/${dist.name}-sources.tgz"/> - <exec executable="xz" failifexecutionfails="false"> - <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-sources.tar"/> - </exec> - <move file="${dists.dir}/archives/${dist.name}-sources.tar.xz" tofile="${dists.dir}/archives/${dist.name}-sources.txz" failonerror="false"/> + <if> + <not><equals arg1="${archives.skipxz}" arg2="true" /></not> + <then> + <exec executable="xz" failifexecutionfails="false"> + <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-sources.tar"/> + </exec> + <move file="${dists.dir}/archives/${dist.name}-sources.tar.xz" tofile="${dists.dir}/archives/${dist.name}-sources.txz" failonerror="false"/> + </then> + </if> <delete file="${dists.dir}/archives/${dist.name}-sources.tar" /> <checksum fileext=".md5"> <fileset dir="${dists.dir}/archives"> diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 59651bcdf9..7f066a2cc3 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -36,7 +36,8 @@ trait GenSymbols { else if (sym.isEmptyPackageClass) mirrorMirrorSelect(nme.EmptyPackageClass) else if (sym.isModuleClass) - Select(Select(reify(sym.sourceModule), nme.asModule), nme.moduleClass) + if (sym.sourceModule.isLocatable) Select(Select(reify(sym.sourceModule), nme.asModule), nme.moduleClass) + else reifySymDef(sym) else if (sym.isPackage) mirrorMirrorCall(nme.staticPackage, reify(sym.fullName)) else if (sym.isLocatable) { diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala index a7ac299317..3892c86dd3 100644 --- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala +++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala @@ -174,15 +174,18 @@ trait SymbolTables { if (sym.annotations.isEmpty) EmptyTree else Apply(Select(currtab.symRef(sym), nme.setAnnotations), List(reifier.reify(sym.annotations))) } else { - import scala.reflect.internal.Flags._ - if (sym hasFlag LOCKED) { - // [Eugene] better to have a symbol without a type signature, than to crash with a CyclicReference - EmptyTree - } else { - val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(sym.info)) - if (sym.annotations.isEmpty) rset - else reifier.mirrorBuildCall(nme.setAnnotations, rset, reifier.mkList(sym.annotations map reifier.reifyAnnotationInfo)) - } + // SI-6204 don't reify signatures for incomplete symbols, because this might lead to cyclic reference errors + val signature = + if (sym.isInitialized) { + if (sym.isCapturedVariable) capturedVariableType(sym) + else sym.info + } else NoType + val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(signature)) + // `Symbol.annotations` doesn't initialize the symbol, so we don't need to do anything special here + // also since we call `sym.info` a few lines above, by now the symbol will be initialized (if possible) + // so the annotations will be filled in and will be waiting to be reified (unless symbol initialization is prohibited as described above) + if (sym.annotations.isEmpty) rset + else reifier.mirrorBuildCall(nme.setAnnotations, rset, reifier.mkList(sym.annotations map reifier.reifyAnnotationInfo)) } } diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index d87a242f1b..5464b6fc3b 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -661,13 +661,15 @@ abstract class Inliners extends SubComponent { * * TODO handle more robustly the case of a trait var changed at the source-level from public to private[this] * (eg by having ICodeReader use unpickler, see SI-5442). - * */ + + DISABLED + def potentiallyPublicized(f: Symbol): Boolean = { (m.sourceFile eq NoSourceFile) && f.name.containsChar('$') } + */ - def checkField(f: Symbol) = check(f, potentiallyPublicized(f) || - (f.isPrivate && !canMakePublic(f))) + def checkField(f: Symbol) = check(f, f.isPrivate && !canMakePublic(f)) def checkSuper(n: Symbol) = check(n, n.isPrivate || !n.isClassConstructor) def checkMethod(n: Symbol) = check(n, n.isPrivate) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 6fba6dcc39..8e928dc9e6 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -497,16 +497,7 @@ abstract class ExplicitOuter extends InfoTransform else atPos(tree.pos)(outerPath(outerValue, currentClass.outerClass, sym)) // (5) case Select(qual, name) => - /** return closest enclosing method, unless shadowed by an enclosing class; - * no use of closures here in the interest of speed. - */ - def closestEnclMethod(from: Symbol): Symbol = - if (from.isSourceMethod) from - else if (from.isClass) NoSymbol - else closestEnclMethod(from.owner) - - if (currentClass != sym.owner || - (closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass)) + if (currentClass != sym.owner) sym.makeNotPrivate(sym.owner) val qsym = qual.tpe.widen.typeSymbol diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 574c2c7049..2831afc48e 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -28,9 +28,6 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { /** the following two members override abstract members in Transform */ val phaseName: String = "extmethods" - /** The following flags may be set by this phase: */ - override def phaseNewFlags: Long = notPRIVATE - def newTransformer(unit: CompilationUnit): Transformer = new Extender(unit) diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 1012ea845f..08c78706fe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -294,17 +294,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL removeCPSAdaptAnnotations(origPt) else origPt - // we've packed the type for each case in typedMatch so that if all cases have the same existential case, we get a clean lub - // here, we should open up the existential again // relevant test cases: pos/existentials-harmful.scala, pos/gadt-gilles.scala, pos/t2683.scala, pos/virtpatmat_exist4.scala - // TODO: fix skolemizeExistential (it should preserve annotations, right?) - val pt = repeatedToSeq(ptUnCPS.skolemizeExistential(context.owner, context.tree) withAnnotations ptUnCPS.annotations) + // pt is the skolemized version + val pt = repeatedToSeq(ptUnCPS) + + // val packedPt = repeatedToSeq(typer.packedType(match_, context.owner)) // the alternative to attaching the default case override would be to simply // append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...) val matchFailGenOverride = match_.attachments.get[DefaultOverrideMatchAttachment].map{case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)} - val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag treeInfo.SYNTH_CASE_FLAGS + val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag treeInfo.SYNTH_CASE_FLAGS // pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental val combined = combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride) @@ -727,8 +727,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // binder has type paramType def treeMaker(binder: Symbol, pos: Position): TreeMaker = { + val paramAccessors = binder.constrParamAccessors + // binders corresponding to mutable fields should be stored (SI-5158, SI-6070) + val mutableBinders = + if (paramAccessors exists (_.isMutable)) + subPatBinders.zipWithIndex.collect{ case (binder, idx) if paramAccessors(idx).isMutable => binder } + else Nil + // checks binder ne null before chaining to the next extractor - ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder)) + ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder), mutableBinders) } // reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component @@ -990,10 +997,27 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL atPos(pos)(casegen.flatMapCond(cond, res, nextBinder, substitution(next))) } - trait PreserveSubPatBinders extends NoNewBinders { + // unless we're optimizing, emit local variable bindings for all subpatterns of extractor/case class patterns + protected val debugInfoEmitVars = !settings.optimise.value + + trait PreserveSubPatBinders extends TreeMaker { val subPatBinders: List[Symbol] val subPatRefs: List[Tree] + // unless `debugInfoEmitVars`, this set should contain the bare minimum for correctness + // mutable case class fields need to be stored regardless (SI-5158, SI-6070) -- see override in ProductExtractorTreeMaker + def storedBinders: Set[Symbol] = if (debugInfoEmitVars) subPatBinders.toSet else Set.empty + + def emitVars = storedBinders.nonEmpty + + private lazy val (stored, substed) = (subPatBinders, subPatRefs).zipped.partition{ case (sym, _) => storedBinders(sym) } + + protected lazy val localSubstitution: Substitution = if (!emitVars) Substitution(subPatBinders, subPatRefs) + else { + val (subPatBindersSubstituted, subPatRefsSubstituted) = substed.unzip + Substitution(subPatBindersSubstituted.toList, subPatRefsSubstituted.toList) + } + /** The substitution that specifies the trees that compute the values of the subpattern binders. * * We pretend to replace the subpattern binders by subpattern refs @@ -1003,7 +1027,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL Substitution(subPatBinders, subPatRefs) >> super.subPatternsAsSubstitution import CODE._ - def bindSubPats(in: Tree): Tree = Block(map2(subPatBinders, subPatRefs)(VAL(_) === _), in) + def bindSubPats(in: Tree): Tree = if (!emitVars) in + else { + val (subPatBindersStored, subPatRefsStored) = stored.unzip + Block(map2(subPatBindersStored.toList, subPatRefsStored.toList)(VAL(_) === _), in) + } } /** @@ -1064,11 +1092,16 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL */ case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])( val subPatBinders: List[Symbol], - val subPatRefs: List[Tree]) extends FunTreeMaker with PreserveSubPatBinders { + val subPatRefs: List[Tree], + val mutableBinders: List[Symbol]) extends FunTreeMaker with PreserveSubPatBinders { import CODE._ val nextBinder = prevBinder // just passing through + // mutable binders must be stored to avoid unsoundness or seeing mutation of fields after matching (SI-5158, SI-6070) + // (the implementation could be optimized by duplicating code from `super.storedBinders`, but this seems more elegant) + override def storedBinders: Set[Symbol] = super.storedBinders ++ mutableBinders.toSet + def chainBefore(next: Tree)(casegen: Casegen): Tree = { val nullCheck = REF(prevBinder) OBJ_NE NULL val cond = extraCond map (nullCheck AND _) getOrElse nullCheck @@ -1391,7 +1424,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // local / context-free def _asInstanceOf(b: Symbol, tp: Type): Tree - def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree + def _asInstanceOf(t: Tree, tp: Type): Tree def _equals(checker: Tree, binder: Symbol): Tree def _isInstanceOf(b: Symbol, tp: Type): Tree def and(a: Tree, b: Tree): Tree @@ -1449,7 +1482,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp) // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly) - def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp) + def _asInstanceOf(t: Tree, tp: Type): Tree = if (t.tpe != NoType && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp) def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp) def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false) // if (typesConform(b.info, tpX)) { patmatDebug("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE } @@ -3542,7 +3575,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL */ def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = { val matchEnd = newSynthCaseLabel("matchEnd") - val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations // + val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations matchEnd setInfo MethodType(List(matchRes), restpe) def newCaseSym = newSynthCaseLabel("case") setInfo MethodType(Nil, restpe) @@ -3553,7 +3586,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL val nextCase = newCaseSym _currCase = nextCase - LabelDef(currCase, Nil, mkCase(new OptimizedCasegen(matchEnd, nextCase, restpe))) + LabelDef(currCase, Nil, mkCase(new OptimizedCasegen(matchEnd, nextCase))) } // must compute catchAll after caseLabels (side-effects nextCase) @@ -3578,14 +3611,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL ) } - class OptimizedCasegen(matchEnd: Symbol, nextCase: Symbol, restpe: Type) extends CommonCodegen with Casegen { + class OptimizedCasegen(matchEnd: Symbol, nextCase: Symbol) extends CommonCodegen with Casegen { def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = optimizedCodegen.matcher(scrut, scrutSym, restpe)(cases, matchFailGen) // only used to wrap the RHS of a body // res: T // returns MatchMonad[T] - def one(res: Tree): Tree = matchEnd APPLY (_asInstanceOf(res, restpe)) // need cast for GADT magic + def one(res: Tree): Tree = matchEnd APPLY (res) // a jump to a case label is special-cased in typedApply protected def zero: Tree = nextCase APPLY () // prev: MatchMonad[T] diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 92c50a05c2..d2a89eb9ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -34,6 +34,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT /** the following two members override abstract members in Transform */ val phaseName: String = "superaccessors" + /** The following flags may be set by this phase: */ + override def phaseNewFlags: Long = notPRIVATE + protected def newTransformer(unit: CompilationUnit): Transformer = new SuperAccTransformer(unit) @@ -192,9 +195,11 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } } super.transform(tree) + case ModuleDef(_, _, _) => checkCompanionNameClashes(sym) super.transform(tree) + case Template(_, _, body) => val ownAccDefs = new ListBuffer[Tree] accDefs(currentOwner) = ownAccDefs @@ -221,72 +226,85 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT typeDef.symbol.deSkolemize.setFlag(SPECIALIZED) typeDef - case sel @ Select(qual @ This(_), name) => - // warn if they are selecting a private[this] member which - // also exists in a superclass, because they may be surprised - // to find out that a constructor parameter will shadow a - // field. See SI-4762. - if (settings.lint.value) { - if (sym.isPrivateLocal && sym.paramss.isEmpty) { - qual.symbol.ancestors foreach { parent => - parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 => - if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) { - unit.warning(sel.pos, - sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name - + " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within " - + sym.owner + " - you may want to give them distinct names." - ) + case sel @ Select(qual, name) => + /** return closest enclosing method, unless shadowed by an enclosing class; + * no use of closures here in the interest of speed. + */ + def closestEnclMethod(from: Symbol): Symbol = + if (from.isSourceMethod) from + else if (from.isClass) NoSymbol + else closestEnclMethod(from.owner) + + if (closestEnclMethod(currentOwner) hasAnnotation definitions.ScalaInlineClass) + sym.makeNotPrivate(sym.owner) + + qual match { + case This(_) => + // warn if they are selecting a private[this] member which + // also exists in a superclass, because they may be surprised + // to find out that a constructor parameter will shadow a + // field. See SI-4762. + if (settings.lint.value) { + if (sym.isPrivateLocal && sym.paramss.isEmpty) { + qual.symbol.ancestors foreach { parent => + parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 => + if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) { + unit.warning(sel.pos, + sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name + + " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within " + + sym.owner + " - you may want to give them distinct names.") + } + } } } } - } - } - // direct calls to aliases of param accessors to the superclass in order to avoid - // duplicating fields. - if (sym.isParamAccessor && sym.alias != NoSymbol) { - val result = (localTyper.typedPos(tree.pos) { - Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias) - }).asInstanceOf[Select] - debuglog("alias replacement: " + tree + " ==> " + result);//debug - localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true)) - } - else { - /** A trait which extends a class and accesses a protected member - * of that class cannot implement the necessary accessor method - * because its implementation is in an implementation class (e.g. - * Foo$class) which inherits nothing, and jvm access restrictions - * require the call site to be in an actual subclass. So non-trait - * classes inspect their ancestors for any such situations and - * generate the accessors. See SI-2296. - */ - // FIXME - this should be unified with needsProtectedAccessor, but some - // subtlety which presently eludes me is foiling my attempts. - val shouldEnsureAccessor = ( - currentClass.isTrait - && sym.isProtected - && sym.enclClass != currentClass - && !sym.owner.isTrait - && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) - && (qual.symbol.info.member(sym.name) ne NoSymbol) - ) - if (shouldEnsureAccessor) { - log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass) - ensureAccessor(sel) - } - else - mayNeedProtectedAccessor(sel, List(EmptyTree), false) - } + // direct calls to aliases of param accessors to the superclass in order to avoid + // duplicating fields. + if (sym.isParamAccessor && sym.alias != NoSymbol) { + val result = (localTyper.typedPos(tree.pos) { + Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias) + }).asInstanceOf[Select] + debuglog("alias replacement: " + tree + " ==> " + result); //debug + localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true)) + } else { + /** + * A trait which extends a class and accesses a protected member + * of that class cannot implement the necessary accessor method + * because its implementation is in an implementation class (e.g. + * Foo$class) which inherits nothing, and jvm access restrictions + * require the call site to be in an actual subclass. So non-trait + * classes inspect their ancestors for any such situations and + * generate the accessors. See SI-2296. + */ + // FIXME - this should be unified with needsProtectedAccessor, but some + // subtlety which presently eludes me is foiling my attempts. + val shouldEnsureAccessor = ( + currentClass.isTrait + && sym.isProtected + && sym.enclClass != currentClass + && !sym.owner.isTrait + && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) + && (qual.symbol.info.member(sym.name) ne NoSymbol)) + if (shouldEnsureAccessor) { + log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass) + ensureAccessor(sel) + } else + mayNeedProtectedAccessor(sel, List(EmptyTree), false) + } - case sel @ Select(Super(_, mix), name) => - if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) { - if (!settings.overrideVars.value) - unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf) - } - else if (isDisallowed(sym)) { - unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead") + case Super(_, mix) => + if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) { + if (!settings.overrideVars.value) + unit.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf) + } else if (isDisallowed(sym)) { + unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead") + } + transformSuperSelect(sel) + + case _ => + mayNeedProtectedAccessor(sel, List(EmptyTree), true) } - transformSuperSelect(sel) case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, withInvalidOwner(transform(rhs))) @@ -294,9 +312,6 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case TypeApply(sel @ Select(qual, name), args) => mayNeedProtectedAccessor(sel, args, true) - case sel @ Select(qual, name) => - mayNeedProtectedAccessor(sel, List(EmptyTree), true) - case Assign(lhs @ Select(qual, name), rhs) => if (lhs.symbol.isVariable && lhs.symbol.isJavaDefined && @@ -311,10 +326,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case Apply(fn, args) => assert(fn.tpe != null, tree) treeCopy.Apply(tree, transform(fn), transformArgs(fn.tpe.params, args)) + case Function(vparams, body) => withInvalidOwner { treeCopy.Function(tree, vparams, transform(body)) } + case _ => super.transform(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a6d7424837..d05368bd5f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3052,7 +3052,19 @@ trait Typers extends Modes with Adaptations with Tags { // target of a call. Since this information is no longer available from // typedArg, it is recorded here. checkDead.updateExpr(fun) - val args1 = typedArgs(args, forArgMode(fun, mode), paramTypes, formals) + + val args1 = + // no expected type when jumping to a match label -- anything goes (this is ok since we're typing the translation of well-typed code) + // ... except during erasure: we must take the expected type into account as it drives the insertion of casts! + // I've exhausted all other semi-clean approaches I could think of in balancing GADT magic, SI-6145, CPS type-driven transforms and other existential trickiness + // (the right thing to do -- packing existential types -- runs into limitations in subtyping existential types, + // casting breaks SI-6145, + // not casting breaks GADT typing as it requires sneaking ill-typed trees past typer) + if (!phase.erasedTypes && fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol)) + typedArgs(args, forArgMode(fun, mode)) + else + typedArgs(args, forArgMode(fun, mode), paramTypes, formals) + // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case: // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo) // precise(foo) : foo.type => foo.type @@ -5040,10 +5052,11 @@ trait Typers extends Modes with Adaptations with Tags { if (isPatternMode) { val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe) - val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, pt, canRemedy = uncheckedTypeExtractor.nonEmpty) - // println(s"Typed($expr, ${tpt.tpe}) : $pt --> $ownType (${isFullyDefined(ownType)}, ${makeFullyDefined(ownType)})") + // make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038) - treeTyped setType (if (isFullyDefined(ownType)) ownType else makeFullyDefined(ownType)) //ownType + val ptDefined = if (isFullyDefined(pt)) pt else makeFullyDefined(pt) + val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, ptDefined, canRemedy = uncheckedTypeExtractor.nonEmpty) + treeTyped setType ownType uncheckedTypeExtractor match { case None => treeTyped diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 4074dd9e93..44a7de3d3a 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -22,17 +22,17 @@ abstract class Universe extends scala.reflect.api.Universe { /** The extended API of symbols that's supported in macro context universes */ - trait SymbolContextApi extends SymbolApi with AttachableApi { this: Symbol => + trait SymbolContextApi extends SymbolApi with AttachableApi { self: Symbol => - def setFlags(flags: FlagSet): this.type + def setFlags(flags: FlagSet): Symbol - def setTypeSignature(tpe: Type): this.type + def setTypeSignature(tpe: Type): Symbol - def setAnnotations(annots: AnnotationInfo*): this.type + def setAnnotations(annots: AnnotationInfo*): Symbol - def setName(name: Name): this.type + def setName(name: Name): Symbol - def setPrivateWithin(sym: Symbol): this.type + def setPrivateWithin(sym: Symbol): Symbol } // Tree extensions --------------------------------------------------------------- @@ -41,20 +41,20 @@ abstract class Universe extends scala.reflect.api.Universe { /** The extended API of trees that's supported in macro context universes */ - trait TreeContextApi extends TreeApi with AttachableApi { this: Tree => + trait TreeContextApi extends TreeApi with AttachableApi { self: Tree => /** ... */ def pos_=(pos: Position): Unit /** ... */ - def setPos(newpos: Position): this.type + def setPos(newpos: Position): Tree /** ... */ def tpe_=(t: Type): Unit /** Set tpe to give `tp` and return this. */ - def setType(tp: Type): this.type + def setType(tp: Type): Tree /** Like `setType`, but if this is a previously empty TypeTree that * fact is remembered so that resetAllAttrs will snap back. @@ -73,13 +73,13 @@ abstract class Universe extends scala.reflect.api.Universe { * and therefore should be abandoned if the current line of type * inquiry doesn't work out. */ - def defineType(tp: Type): this.type + def defineType(tp: Type): Tree /** ... */ def symbol_=(sym: Symbol): Unit /** ... */ - def setSymbol(sym: Symbol): this.type + def setSymbol(sym: Symbol): Tree } override type SymTree >: Null <: Tree with SymTreeContextApi diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check index a6a1a1fad4..0f2fe6f2d1 100644 --- a/test/files/neg/t4425.check +++ b/test/files/neg/t4425.check @@ -1,5 +1,4 @@ -t4425.scala:3: error: error during expansion of this match (this is a scalac bug). -The underlying error was: value _1 is not a member of object Foo.X +t4425.scala:3: error: isInstanceOf cannot test if value types are references. 42 match { case _ X _ => () } - ^ + ^ one error found diff --git a/test/files/neg/t4425.flags b/test/files/neg/t4425.flags new file mode 100644 index 0000000000..1182725e86 --- /dev/null +++ b/test/files/neg/t4425.flags @@ -0,0 +1 @@ +-optimize
\ No newline at end of file diff --git a/test/files/pos/inline-access-levels.flags b/test/files/pos/inline-access-levels.flags new file mode 100644 index 0000000000..882f40f050 --- /dev/null +++ b/test/files/pos/inline-access-levels.flags @@ -0,0 +1 @@ +-optimise -Xfatal-warnings -Yinline-warnings diff --git a/test/files/pos/inline-access-levels/A_1.scala b/test/files/pos/inline-access-levels/A_1.scala new file mode 100644 index 0000000000..479fe0fc71 --- /dev/null +++ b/test/files/pos/inline-access-levels/A_1.scala @@ -0,0 +1,10 @@ +package test + +object A { + + private var x: Int = 0 + + @inline def actOnX(f: Int => Int) = { + x = f(x) + } +} diff --git a/test/files/pos/inline-access-levels/Test_2.scala b/test/files/pos/inline-access-levels/Test_2.scala new file mode 100644 index 0000000000..12c9eb540f --- /dev/null +++ b/test/files/pos/inline-access-levels/Test_2.scala @@ -0,0 +1,11 @@ +package test + +object Test { + + def main(args: Array[String]) { + + A.actOnX(_ + 1) + + } + +} diff --git a/test/files/pos/t5756.scala b/test/files/pos/t5756.scala new file mode 100644 index 0000000000..45960fa8bd --- /dev/null +++ b/test/files/pos/t5756.scala @@ -0,0 +1,6 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + def tagme[T: TypeTag](x: T) = typeTag[T] + val foo = tagme{object Bar; Bar} +}
\ No newline at end of file diff --git a/test/files/pos/t6145.scala b/test/files/pos/t6145.scala new file mode 100644 index 0000000000..28334d4420 --- /dev/null +++ b/test/files/pos/t6145.scala @@ -0,0 +1,11 @@ +object Test { + // the existential causes a cast and the cast makes searchClass not be in tail position + // can we get rid of the useless cast? + @annotation.tailrec + final def searchClass: Class[_] = { + "packageName" match { + case _ => + searchClass + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t6204-a.scala b/test/files/pos/t6204-a.scala new file mode 100644 index 0000000000..bd8d5c437e --- /dev/null +++ b/test/files/pos/t6204-a.scala @@ -0,0 +1,9 @@ +import scala.reflect.runtime.universe._ + +object Bish { + def m { + object Bash { + typeOf[Option[_]] + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t6204-b.scala b/test/files/pos/t6204-b.scala new file mode 100644 index 0000000000..86094d1a19 --- /dev/null +++ b/test/files/pos/t6204-b.scala @@ -0,0 +1,10 @@ +import scala.reflect.runtime.universe._ + +object Bosh { + def Besh { + new { + val t = typeOf[Option[_]] + val x = t + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t6205.scala b/test/files/pos/t6205.scala new file mode 100644 index 0000000000..02d924fe85 --- /dev/null +++ b/test/files/pos/t6205.scala @@ -0,0 +1,18 @@ +// original code by reporter +class A[T] +class Test1 { + def x(backing: Map[A[_], Any]) = + for( (k: A[kt], v) <- backing) + yield (k: A[kt]) +} + +// this tests same thing as above, but independent of library classes, +// earlier expansions eliminated as well as variance (everything's invariant) +case class Holder[A](a: A) +class Mapped[A] { def map[T](f: Holder[A] => T): Iterable[T] = ??? } +class Test2 { + def works(backing: Mapped[A[_]]): Iterable[A[_]] + = backing.map(x => + x match {case Holder(k: A[kt]) => (k: A[kt])} + ) +}
\ No newline at end of file diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check index 25e1b2a4dd..a4c9f215e8 100644 --- a/test/files/run/inline-ex-handlers.check +++ b/test/files/run/inline-ex-handlers.check @@ -13,6 +13,10 @@ < 92 JUMP 2 < < 2: +383c382 +< locals: value args, variable result, value ex6, value x4, value x5, value message, value x +--- +> locals: value args, variable result, value ex6, value x4, value x5, value x 385c384 < blocks: [1,2,3,4,5,8,11,13,14,16] --- @@ -34,11 +38,21 @@ < 101 JUMP 4 < < 4: -515c520 +438,441d442 +< 106 LOAD_LOCAL(value x5) +< 106 CALL_METHOD MyException.message (dynamic) +< 106 STORE_LOCAL(value message) +< 106 SCOPE_ENTER value message +443c444,445 +< 106 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +515c517 < blocks: [1,2,3,4,6,7,8,9,10] --- > blocks: [1,2,3,4,6,7,8,9,10,11,12,13] -544c549,554 +544c546,551 < 306 THROW(MyException) --- > ? JUMP 11 @@ -47,7 +61,7 @@ > ? LOAD_LOCAL(variable monitor4) > 305 MONITOR_EXIT > ? JUMP 12 -550c560,566 +550c557,563 < ? THROW(Throwable) --- > ? JUMP 12 @@ -57,7 +71,7 @@ > 304 MONITOR_EXIT > ? STORE_LOCAL(value t) > ? JUMP 13 -556c572,585 +556c569,582 < ? THROW(Throwable) --- > ? STORE_LOCAL(value t) @@ -74,19 +88,19 @@ > 310 CALL_PRIMITIVE(EndConcat) > 310 CALL_METHOD scala.Predef.println (dynamic) > 310 JUMP 2 -580c609 +580c606 < catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6 --- > catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6 -583c612 +583c609 < catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3 --- > catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3 -615c644 +615c641 < blocks: [1,2,3,4,5,6,7,9,10] --- > blocks: [1,2,3,4,5,6,7,9,10,11,12] -639c668,674 +639c665,671 < 78 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -96,7 +110,7 @@ > 81 LOAD_LOCAL(value e) > ? STORE_LOCAL(variable exc1) > ? JUMP 12 -668c703,717 +668c700,714 < 81 THROW(Exception) --- > ? STORE_LOCAL(variable exc1) @@ -114,15 +128,19 @@ > 84 STORE_LOCAL(variable result) > 84 LOAD_LOCAL(variable exc1) > 84 THROW(Throwable) -690c739 +690c736 < catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3 --- > catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3 -716c765 +714c760 +< locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x +--- +> locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x +716c762 < blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31] --- > blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34] -740c789,796 +740c786,793 < 172 THROW(MyException) --- > ? STORE_LOCAL(value ex6) @@ -133,12 +151,27 @@ > 170 STORE_LOCAL(value x4) > 170 SCOPE_ENTER value x4 > 170 JUMP 18 -798c854,855 +787,790d839 +< 175 LOAD_LOCAL(value x5) +< 175 CALL_METHOD MyException.message (dynamic) +< 175 STORE_LOCAL(value message) +< 175 SCOPE_ENTER value message +792c841,842 +< 176 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +796c846,847 +< 177 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +798c849,850 < 177 THROW(MyException) --- > ? STORE_LOCAL(value ex6) > ? JUMP 33 -802c859,866 +802c854,861 < 170 THROW(Throwable) --- > ? STORE_LOCAL(value ex6) @@ -149,17 +182,32 @@ > 169 STORE_LOCAL(value x4) > 169 SCOPE_ENTER value x4 > 169 JUMP 5 -837c901,902 +826,829d884 +< 180 LOAD_LOCAL(value x5) +< 180 CALL_METHOD MyException.message (dynamic) +< 180 STORE_LOCAL(value message) +< 180 SCOPE_ENTER value message +831c886,887 +< 181 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +835c891,892 +< 182 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +837c894,895 < 182 THROW(MyException) --- > ? STORE_LOCAL(variable exc2) > ? JUMP 34 -841c906,907 +841c899,900 < 169 THROW(Throwable) --- > ? STORE_LOCAL(variable exc2) > ? JUMP 34 -842a909,921 +842a902,914 > 34: > 184 LOAD_MODULE object Predef > 184 CONSTANT("finally") @@ -173,19 +221,23 @@ > 185 LOAD_LOCAL(variable exc2) > 185 THROW(Throwable) > -863c942 +863c935 < catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4 --- > catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4 -866c945 +866c938 < catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3 --- > catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3 -892c971 +890c962 +< locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x +--- +> locals: value args, variable result, value e, value ex6, value x4, value x5, value x +892c964 < blocks: [1,2,3,6,7,8,11,14,16,17,19] --- > blocks: [1,2,3,6,7,8,11,14,16,17,19,20] -916c995,1002 +916c988,995 < 124 THROW(MyException) --- > ? STORE_LOCAL(value ex6) @@ -196,15 +248,29 @@ > 122 STORE_LOCAL(value x4) > 122 SCOPE_ENTER value x4 > 122 JUMP 7 -979c1065 +945,948d1023 +< 127 LOAD_LOCAL(value x5) +< 127 CALL_METHOD MyException.message (dynamic) +< 127 STORE_LOCAL(value message) +< 127 SCOPE_ENTER value message +950c1025,1026 +< 127 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +979c1055 < catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3 --- > catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19, 20) starting at: 3 -1005c1091 +1003c1079 +< locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e +--- +> locals: value args, variable result, value ex6, value x4, value x5, value x, value e +1005c1081 < blocks: [1,2,3,4,5,8,11,15,16,17,19] --- > blocks: [1,2,3,5,8,11,15,16,17,19,20] -1029c1115,1124 +1029c1105,1114 < 148 THROW(MyException) --- > ? STORE_LOCAL(value ex6) @@ -217,15 +283,25 @@ > 154 LOAD_LOCAL(value x4) > 154 IS_INSTANCE REF(class MyException) > 154 CZJUMP (BOOL)NE ? 5 : 11 -1050,1052d1144 +1050,1052d1134 < 145 JUMP 4 < < 4: -1288c1380 +1066,1069d1147 +< 154 LOAD_LOCAL(value x5) +< 154 CALL_METHOD MyException.message (dynamic) +< 154 STORE_LOCAL(value message) +< 154 SCOPE_ENTER value message +1071c1149,1150 +< 154 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +1288c1367 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1312c1404,1411 +1312c1391,1398 < 38 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -236,16 +312,20 @@ > 42 CONSTANT("IllegalArgumentException") > 42 CALL_METHOD scala.Predef.println (dynamic) > 42 JUMP 2 -1361c1460 +1359c1445 +< locals: value args, variable result, value ex6, value x4, value x5, value message, value x +--- +> locals: value args, variable result, value ex6, value x4, value x5, value x +1361c1447 < blocks: [1,2,3,4,5,8,11,13,14,16,17,19] --- > blocks: [1,2,3,5,8,11,13,14,16,17,19,20] -1385c1484,1485 +1385c1471,1472 < 203 THROW(MyException) --- > ? STORE_LOCAL(value ex6) > ? JUMP 20 -1405c1505,1514 +1405c1492,1501 < 209 THROW(MyException) --- > ? STORE_LOCAL(value ex6) @@ -258,15 +338,25 @@ > 212 LOAD_LOCAL(value x4) > 212 IS_INSTANCE REF(class MyException) > 212 CZJUMP (BOOL)NE ? 5 : 11 -1418,1420d1526 +1418,1420d1513 < 200 JUMP 4 < < 4: -1483c1589 +1434,1437d1526 +< 212 LOAD_LOCAL(value x5) +< 212 CALL_METHOD MyException.message (dynamic) +< 212 STORE_LOCAL(value message) +< 212 SCOPE_ENTER value message +1439c1528,1529 +< 213 LOAD_LOCAL(value message) +--- +> ? LOAD_LOCAL(value x5) +> ? CALL_METHOD MyException.message (dynamic) +1483c1573 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1507c1613,1620 +1507c1597,1604 < 58 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -277,11 +367,11 @@ > 62 CONSTANT("RuntimeException") > 62 CALL_METHOD scala.Predef.println (dynamic) > 62 JUMP 2 -1556c1669 +1556c1653 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1576c1689,1694 +1576c1673,1678 < 229 THROW(MyException) --- > ? JUMP 5 @@ -290,19 +380,19 @@ > ? LOAD_LOCAL(variable monitor1) > 228 MONITOR_EXIT > 228 THROW(Throwable) -1582c1700 +1582c1684 < ? THROW(Throwable) --- > 228 THROW(Throwable) -1610c1728 +1610c1712 < locals: value args, variable result, variable monitor2, variable monitorResult1 --- > locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1 -1612c1730 +1612c1714 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1635c1753,1761 +1635c1737,1745 < 245 THROW(MyException) --- > ? STORE_LOCAL(value exception$1) @@ -314,7 +404,7 @@ > ? LOAD_LOCAL(variable monitor2) > 244 MONITOR_EXIT > 244 THROW(Throwable) -1641c1767 +1641c1751 < ? THROW(Throwable) --- > 244 THROW(Throwable) |