diff options
20 files changed, 398 insertions, 79 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 068836fe4f..d50d4cd125 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -320,7 +320,12 @@ trait BasicBlocks { else instrs.zipWithIndex collect { case (oldInstr, i) if map contains oldInstr => - code.touched |= replaceInstruction(i, map(oldInstr)) + // SI-6288 clone important here because `replaceInstruction` assigns + // a position to `newInstr`. Without this, a single instruction can + // be added twice, and the position last position assigned clobbers + // all previous positions in other usages. + val newInstr = map(oldInstr).clone() + code.touched |= replaceInstruction(i, newInstr) } ////////////////////// Emit ////////////////////// diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 22daf13e33..7ae8923e43 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1003,22 +1003,22 @@ trait Infer extends Checkable { */ /** error if arguments not within bounds. */ def checkBounds(tree: Tree, pre: Type, owner: Symbol, - tparams: List[Symbol], targs: List[Type], prefix: String): Boolean = { - //@M validate variances & bounds of targs wrt variances & bounds of tparams - //@M TODO: better place to check this? - //@M TODO: errors for getters & setters are reported separately - val kindErrors = checkKindBounds(tparams, targs, pre, owner) - - if(!kindErrors.isEmpty) { - if (targs contains WildcardType) true - else { KindBoundErrors(tree, prefix, targs, tparams, kindErrors); false } - } else if (!isWithinBounds(pre, owner, tparams, targs)) { - if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) { - NotWithinBounds(tree, prefix, targs, tparams, kindErrors) - false - } else true - } else true - } + tparams: List[Symbol], targs: List[Type], prefix: String): Boolean = + if ((targs exists (_.isErroneous)) || (tparams exists (_.isErroneous))) true + else { + //@M validate variances & bounds of targs wrt variances & bounds of tparams + //@M TODO: better place to check this? + //@M TODO: errors for getters & setters are reported separately + val kindErrors = checkKindBounds(tparams, targs, pre, owner) + kindErrors match { + case Nil => + def notWithinBounds() = NotWithinBounds(tree, prefix, targs, tparams, Nil) + isWithinBounds(pre, owner, tparams, targs) || {notWithinBounds(); false} + case errors => + def kindBoundErrors() = KindBoundErrors(tree, prefix, targs, tparams, errors) + (targs contains WildcardType) || {kindBoundErrors(); false} + } + } def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = { checkKindBounds0(tparams, targs, pre, owner, true) map { diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 834c64aaae..fa8aff5cdd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -801,8 +801,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL protected def spliceApply(binder: Symbol): Tree = { object splice extends Transformer { override def transform(t: Tree) = t match { - case Apply(x, List(Ident(nme.SELECTOR_DUMMY))) => - treeCopy.Apply(t, x, List(CODE.REF(binder))) + case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) => + treeCopy.Apply(t, x, List(CODE.REF(binder).setPos(i.pos))) case _ => super.transform(t) } } @@ -879,7 +879,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL override def transform(tree: Tree): Tree = { def subst(from: List[Symbol], to: List[Tree]): Tree = if (from.isEmpty) tree - else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate, tree.tpe) + else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate.setPos(tree.pos), tree.tpe) else subst(from.tail, to.tail) tree match { diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 0a1d3bfa7a..20db479463 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -19,16 +19,16 @@ trait StdAttachments { * by `parentTypes`. This attachment coordinates `parentTypes` and `typedTemplate` and * allows them to complete the synthesis. */ - case class SuperCallArgsAttachment(argss: List[List[Tree]]) + case class SuperArgsAttachment(argss: List[List[Tree]]) - /** Convenience method for `SuperCallArgsAttachment`. + /** Convenience method for `SuperArgsAttachment`. * Compared with `MacroRuntimeAttachment` this attachment has different a usage pattern, * so it really benefits from a dedicated extractor. */ - def superCallArgs(tree: Tree): Option[List[List[Tree]]] = - tree.attachments.get[SuperCallArgsAttachment] collect { case SuperCallArgsAttachment(argss) => argss } + def superArgs(tree: Tree): Option[List[List[Tree]]] = + tree.attachments.get[SuperArgsAttachment] collect { case SuperArgsAttachment(argss) => argss } - /** Determines whether the given tree has an associated SuperCallArgsAttachment. + /** Determines whether the given tree has an associated SuperArgsAttachment. */ - def hasSuperArgs(tree: Tree): Boolean = superCallArgs(tree).nonEmpty + def hasSuperArgs(tree: Tree): Boolean = superArgs(tree).nonEmpty }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8441d450a6..e4744de1b8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1512,7 +1512,7 @@ trait Typers extends Modes with Adaptations with Tags { * * Returns a `TypeTree` representing a resolved parent type. * If the typechecked parent reference implies non-nullary and non-empty argument list, - * this argument list is attached to the returned value in SuperCallArgsAttachment. + * this argument list is attached to the returned value in SuperArgsAttachment. * The attachment is necessary for the subsequent typecheck to fixup a super constructor call * in the body of the primary constructor (see `typedTemplate` for details). * @@ -1578,7 +1578,7 @@ trait Typers extends Modes with Adaptations with Tags { // this is the place where we tell the typer what argss should be used for the super call // if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`) // the super call dummy is already good enough, so we don't need to do anything - if (argssAreTrivial) supertpt else supertpt updateAttachment SuperCallArgsAttachment(argss) + if (argssAreTrivial) supertpt else supertpt updateAttachment SuperArgsAttachment(argss) } } @@ -1930,8 +1930,7 @@ trait Typers extends Modes with Adaptations with Tags { */ def typedTemplate(templ: Template, parents1: List[Tree]): Template = { val clazz = context.owner - // complete lazy annotations - val annots = clazz.annotations + clazz.annotations.map(_.completeInfo) if (templ.symbol == NoSymbol) templ setSymbol clazz.newLocalDummy(templ.pos) val self1 = templ.self match { @@ -1978,7 +1977,7 @@ trait Typers extends Modes with Adaptations with Tags { val primaryCtor = treeInfo.firstConstructor(body) val primaryCtor1 = primaryCtor match { case DefDef(_, _, _, _, _, Block(earlyVals :+ global.pendingSuperCall, unit)) => - val argss = superCallArgs(parents1.head) getOrElse Nil + val argss = superArgs(parents1.head) getOrElse Nil val pos = wrappingPos(parents1.head.pos, argss.flatten) val superCall = atPos(pos)(PrimarySuperCall(argss)) deriveDefDef(primaryCtor)(block => Block(earlyVals :+ superCall, unit) setPos pos) setPos pos @@ -2026,8 +2025,7 @@ trait Typers extends Modes with Adaptations with Tags { val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor) val typedMods = typedModifiers(vdef.mods) - // complete lazy annotations - val annots = sym.annotations + sym.annotations.map(_.completeInfo) var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt)) checkNonCyclic(vdef, tpt1) @@ -2270,8 +2268,7 @@ trait Typers extends Modes with Adaptations with Tags { val tparams1 = ddef.tparams mapConserve typedTypeDef val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef) - // complete lazy annotations - val annots = meth.annotations + meth.annotations.map(_.completeInfo) for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1) if (isRepeatedParamType(vparam1.symbol.tpe)) @@ -2346,8 +2343,7 @@ trait Typers extends Modes with Adaptations with Tags { reenterTypeParams(tdef.tparams) val tparams1 = tdef.tparams mapConserve typedTypeDef val typedMods = typedModifiers(tdef.mods) - // complete lazy annotations - val annots = tdef.symbol.annotations + tdef.symbol.annotations.map(_.completeInfo) // @specialized should not be pickled when compiling with -no-specialize if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) { @@ -5254,8 +5250,6 @@ trait Typers extends Modes with Adaptations with Tags { def typedPackageDef(pdef: PackageDef) = { val pid1 = typedQualifier(pdef.pid).asInstanceOf[RefTree] assert(sym.moduleClass ne NoSymbol, sym) - // complete lazy annotations - val annots = sym.annotations val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls)) .typedStats(pdef.stats, NoSymbol) treeCopy.PackageDef(tree, pid1, stats1) setType NoType diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 8c18809ad6..483cb491a1 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -39,6 +39,10 @@ abstract class DirectTest extends App { // new compiler def newCompiler(args: String*): Global = { val settings = newSettings((CommandLineParser tokenize ("-d \"" + testOutput.path + "\" " + extraSettings)) ++ args.toList) + newCompiler(settings) + } + + def newCompiler(settings: Settings): Global = { if (settings.Yrangepos.value) new Global(settings, reporter(settings)) with interactive.RangePositions else new Global(settings, reporter(settings)) } diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 7c12b5979d..6a5a742cc7 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -201,6 +201,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => override def toString = if (forced) forcedInfo.toString else "@<?>" override def pos: Position = if (forced) forcedInfo.pos else NoPosition + + override def completeInfo(): Unit = forcedInfo } /** Typed information about an annotation. It can be attached to either @@ -242,6 +244,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => this } + // Forces LazyAnnotationInfo, no op otherwise + def completeInfo(): Unit = () + /** Annotations annotating annotations are confusing so I drew * an example. Given the following code: * diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index d82692000d..119a57d268 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -6605,11 +6605,11 @@ trait Types extends api.Types { self: SymbolTable => case ExistentialType(qs, _) => qs case t => List() } - def stripType(tp: Type) = tp match { + def stripType(tp: Type): Type = tp match { case ExistentialType(_, res) => res case tv@TypeVar(_, constr) => - if (tv.instValid) constr.inst + if (tv.instValid) stripType(constr.inst) else if (tv.untouchable) tv else abort("trying to do lub/glb of typevar "+tp) case t => t diff --git a/test/files/neg/t3222.check b/test/files/neg/t3222.check index e724024f45..6170827cc9 100644 --- a/test/files/neg/t3222.check +++ b/test/files/neg/t3222.check @@ -1,7 +1,13 @@ -t3222.scala:4: error: not found: type D - def foo(@throws(classOf[D]) x: Int) {} - ^ t3222.scala:1: error: not found: type B @throws(classOf[B]) ^ -two errors found +t3222.scala:4: error: not found: type D + def foo(@throws(classOf[D]) x: Int) {} + ^ +t3222.scala:3: error: not found: type C + @throws(classOf[C]) + ^ +t3222.scala:6: error: not found: type E + @throws(classOf[E]) + ^ +four errors found diff --git a/test/files/neg/t4044.check b/test/files/neg/t4044.check index 41a04f69b9..0e1ea4f51d 100644 --- a/test/files/neg/t4044.check +++ b/test/files/neg/t4044.check @@ -1,11 +1,6 @@ t4044.scala:9: error: AnyRef takes no type parameters, expected: one M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *) ^ -t4044.scala:9: error: kinds of the type arguments (<error>) do not conform to the expected kinds of the type parameters (type N). -<error>'s type parameters do not match type N's expected parameters: -<none> has no type parameters, but type N has one - M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *) - ^ t4044.scala:11: error: kinds of the type arguments (Test.A) do not conform to the expected kinds of the type parameters (type N). Test.A's type parameters do not match type N's expected parameters: type _ has no type parameters, but type O has one @@ -16,4 +11,4 @@ Test.C's type parameters do not match type N's expected parameters: type _ has one type parameter, but type _ has none M[C] // error, (C :: (* -> * -> * -> *) not kind-conformant to (N :: * -> * -> *) ^ -four errors found +three errors found diff --git a/test/files/neg/t6558.check b/test/files/neg/t6558.check index 1b39ef9986..6ad3cecd50 100644 --- a/test/files/neg/t6558.check +++ b/test/files/neg/t6558.check @@ -1,10 +1,10 @@ -t6558.scala:19: error: not found: type classs +t6558.scala:4: error: not found: type classs @classs ^ -t6558.scala:22: error: not found: type typeparam +t6558.scala:7: error: not found: type typeparam class D[@typeparam T] ^ -t6558.scala:25: error: not found: type valueparam +t6558.scala:10: error: not found: type valueparam @valueparam x: Any ^ three errors found diff --git a/test/files/neg/t6558.scala b/test/files/neg/t6558.scala index bdc441698f..b4304ff686 100644 --- a/test/files/neg/t6558.scala +++ b/test/files/neg/t6558.scala @@ -1,21 +1,6 @@ class AnnotNotFound { def foo(a: Any) = () - foo { - // Not yet issued in the context of this file, see SI-6758 - // This error is issued in t6558b.scala - @inargument - def foo = 0 - foo - } - - () => { - // As per above - @infunction - def foo = 0 - () - } - @classs class C diff --git a/test/files/neg/t6758.check b/test/files/neg/t6758.check new file mode 100644 index 0000000000..2cdd6b8ae5 --- /dev/null +++ b/test/files/neg/t6758.check @@ -0,0 +1,28 @@ +t6758.scala:5: error: not found: type inargument + @inargument + ^ +t6758.scala:11: error: not found: type infunction + @infunction + ^ +t6758.scala:18: error: not found: type nested + @nested + ^ +t6758.scala:25: error: not found: type param + def func(@param x: Int): Int = 0 + ^ +t6758.scala:28: error: not found: type typealias + @typealias + ^ +t6758.scala:32: error: not found: type classs + @classs + ^ +t6758.scala:35: error: not found: type module + @module + ^ +t6758.scala:38: error: not found: type typeparam + class D[@typeparam T] + ^ +t6758.scala:41: error: not found: type valueparam + @valueparam x: Any + ^ +9 errors found diff --git a/test/files/neg/t6758.scala b/test/files/neg/t6758.scala new file mode 100644 index 0000000000..acf333bf90 --- /dev/null +++ b/test/files/neg/t6758.scala @@ -0,0 +1,43 @@ +class AnnotNotFound { + def foo(a: Any) = () + + foo { + @inargument + def foo = 0 + foo + } + + () => { + @infunction + def foo = 0 + () + } + + () => { + val bar: Int = { + @nested + val bar2: Int = 2 + 2 + } + () + } + + def func(@param x: Int): Int = 0 + + abstract class A { + @typealias + type B = Int + } + + @classs + class C + + @module + object D + + class D[@typeparam T] + + class E( + @valueparam x: Any + ) +} diff --git a/test/files/pos/strip-tvars-for-lubbasetypes.scala b/test/files/pos/strip-tvars-for-lubbasetypes.scala new file mode 100644 index 0000000000..2be8625bae --- /dev/null +++ b/test/files/pos/strip-tvars-for-lubbasetypes.scala @@ -0,0 +1,25 @@ +object Test { + + implicit final class EqualOps[T](val x: T) extends AnyVal { + def ===[T1, Ph >: T <: T1, Ph2 >: Ph <: T1](other: T1): Boolean = x == other + def !!![T1, Ph2 >: Ph <: T1, Ph >: T <: T1](other: T1): Boolean = x == other + } + + class A + class B extends A + class C extends A + + val a = new A + val b = new B + val c = new C + + val x1 = a === b + val x2 = b === a + val x3 = b === c // error, infers Object{} for T1 + val x4 = b.===[A, B, B](c) + + val x5 = b !!! c // always compiled due to the order of Ph2 and Ph + + + +} diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check index e786c780d6..45db7c3a15 100644 --- a/test/files/run/inline-ex-handlers.check +++ b/test/files/run/inline-ex-handlers.check @@ -47,7 +47,7 @@ < 106 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 106 CALL_METHOD MyException.message (dynamic) 502c504 < blocks: [1,2,3,4,6,7,8,9,10] --- @@ -162,12 +162,12 @@ < 176 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 176 CALL_METHOD MyException.message (dynamic) 783c833,834 < 177 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 177 CALL_METHOD MyException.message (dynamic) 785c836,837 < 177 THROW(MyException) --- @@ -194,12 +194,12 @@ < 181 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 181 CALL_METHOD MyException.message (dynamic) 822c878,879 < 182 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 182 CALL_METHOD MyException.message (dynamic) 824c881,882 < 182 THROW(MyException) --- @@ -260,7 +260,7 @@ < 127 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 127 CALL_METHOD MyException.message (dynamic) 966c1042 < catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3 --- @@ -299,7 +299,7 @@ < 154 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 154 CALL_METHOD MyException.message (dynamic) 1275c1354 < blocks: [1,2,3,4,5,7] --- @@ -354,22 +354,23 @@ < 213 LOAD_LOCAL(value message) --- > ? LOAD_LOCAL(value x5) -> ? CALL_METHOD MyException.message (dynamic) +> 213 CALL_METHOD MyException.message (dynamic) 1470c1560 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1494c1584,1591 +1494c1584,1585 < 58 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) > ? JUMP 8 -> +1495a1587,1592 > 8: > 62 LOAD_MODULE object Predef > 62 CONSTANT("RuntimeException") > 62 CALL_METHOD scala.Predef.println (dynamic) > 62 JUMP 2 +> 1543c1640 < blocks: [1,2,3,4] --- diff --git a/test/files/run/t6288.check b/test/files/run/t6288.check new file mode 100644 index 0000000000..af6bd5d269 --- /dev/null +++ b/test/files/run/t6288.check @@ -0,0 +1,85 @@ +[[syntax trees at end of patmat]] // newSource1 +[7]package [7]<empty> { + [7]object Case3 extends [13][106]scala.AnyRef { + [106]def <init>(): [13]Case3.type = [106]{ + [106][106][106]Case3.super.<init>(); + [13]() + }; + [21]def unapply([29]z: [32]<type: [32]scala.Any>): [21]Option[Int] = [56][52][52]scala.Some.apply[[52]Int]([58]-1); + [64]{ + [64]case <synthetic> val x1: [64]Any = [64]""; + [64]case5()[84]{ + [84]<synthetic> val o7: [84]Option[Int] = [84][84]Case3.unapply([84]x1); + [84]if ([84]o7.isEmpty.unary_!) + [84]{ + [90]val nr: [90]Int = [90]o7.get; + [97][97]matchEnd4([97]()) + } + else + [84][84]case6() + }; + [64]case6(){ + [64][64]matchEnd4([64]throw [64][64][64]new [64]MatchError([64]x1)) + }; + [64]matchEnd4(x: [NoPosition]Unit){ + [64]x + } + } + }; + [113]object Case4 extends [119][217]scala.AnyRef { + [217]def <init>(): [119]Case4.type = [217]{ + [217][217][217]Case4.super.<init>(); + [119]() + }; + [127]def unapplySeq([138]z: [141]<type: [141]scala.Any>): [127]Option[List[Int]] = [167]scala.None; + [175]{ + [175]case <synthetic> val x1: [175]Any = [175]""; + [175]case5()[195]{ + [195]<synthetic> val o7: [195]Option[List[Int]] = [195][195]Case4.unapplySeq([195]x1); + [195]if ([195]o7.isEmpty.unary_!) + [195]if ([195][195][195][195]o7.get.!=([195]null).&&([195][195][195][195]o7.get.lengthCompare([195]1).==([195]0))) + [195]{ + [201]val nr: [201]Int = [201][201]o7.get.apply([201]0); + [208][208]matchEnd4([208]()) + } + else + [195][195]case6() + else + [195][195]case6() + }; + [175]case6(){ + [175][175]matchEnd4([175]throw [175][175][175]new [175]MatchError([175]x1)) + }; + [175]matchEnd4(x: [NoPosition]Unit){ + [175]x + } + } + }; + [224]object Case5 extends [230][312]scala.AnyRef { + [312]def <init>(): [230]Case5.type = [312]{ + [312][312][312]Case5.super.<init>(); + [230]() + }; + [238]def unapply([246]z: [249]<type: [249]scala.Any>): [238]Boolean = [265]true; + [273]{ + [273]case <synthetic> val x1: [273]Any = [273]""; + [273]case5()[293]{ + [293]<synthetic> val o7: [293]Option[List[Int]] = [293][293]Case4.unapplySeq([293]x1); + [293]if ([293]o7.isEmpty.unary_!) + [293]if ([293][293][293][293]o7.get.!=([293]null).&&([293][293][293][293]o7.get.lengthCompare([293]0).==([195]0))) + [304][304]matchEnd4([304]()) + else + [293][293]case6() + else + [293][293]case6() + }; + [273]case6(){ + [273][273]matchEnd4([273]throw [273][273][273]new [273]MatchError([273]x1)) + }; + [273]matchEnd4(x: [NoPosition]Unit){ + [273]x + } + } + } +} + diff --git a/test/files/run/t6288.scala b/test/files/run/t6288.scala new file mode 100644 index 0000000000..cf5865e95a --- /dev/null +++ b/test/files/run/t6288.scala @@ -0,0 +1,41 @@ +import scala.tools.partest._ +import java.io.{Console => _, _} + +object Test extends DirectTest { + + override def extraSettings: String = "-usejavacp -Xprint:patmat -Xprint-pos -d " + testOutput.path + + override def code = + """ + |object Case3 { + | def unapply(z: Any): Option[Int] = Some(-1) + | + | "" match { + | case Case3(nr) => () + | } + |} + |object Case4 { + | def unapplySeq(z: Any): Option[List[Int]] = None + | + | "" match { + | case Case4(nr) => () + | } + |} + |object Case5 { + | def unapply(z: Any): Boolean = true + | + | "" match { + | case Case4() => () + | } + |} + | + |""".stripMargin.trim + + override def show(): Unit = { + // Now: [84][84]Case3.unapply([84]x1); + // Was: [84][84]Case3.unapply([64]x1); + Console.withErr(System.out) { + compile() + } + } +} diff --git a/test/files/run/t6288b-jump-position.check b/test/files/run/t6288b-jump-position.check new file mode 100644 index 0000000000..45ec31c308 --- /dev/null +++ b/test/files/run/t6288b-jump-position.check @@ -0,0 +1,80 @@ +object Case3 extends Object { + // fields: + + // methods + def unapply(z: Object (REF(class Object))): Option { + locals: value z + startBlock: 1 + blocks: [1] + + 1: + 2 NEW REF(class Some) + 2 DUP(REF(class Some)) + 2 CONSTANT(-1) + 2 BOX INT + 2 CALL_METHOD scala.Some.<init> (static-instance) + 2 RETURN(REF(class Option)) + + } + Exception handlers: + + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { + locals: value args, value x1, value x2, value x + startBlock: 1 + blocks: [1,2,3,6,7] + + 1: + 4 CONSTANT("") + 4 STORE_LOCAL(value x1) + 4 SCOPE_ENTER value x1 + 4 JUMP 2 + + 2: + 5 LOAD_LOCAL(value x1) + 5 IS_INSTANCE REF(class String) + 5 CZJUMP (BOOL)NE ? 3 : 6 + + 3: + 5 LOAD_LOCAL(value x1) + 5 CHECK_CAST REF(class String) + 5 STORE_LOCAL(value x2) + 5 SCOPE_ENTER value x2 + 6 LOAD_MODULE object Predef + 6 CONSTANT("case 0") + 6 CALL_METHOD scala.Predef.println (dynamic) + 6 LOAD_FIELD scala.runtime.BoxedUnit.UNIT + 6 STORE_LOCAL(value x) + 6 JUMP 7 + + 6: + 8 LOAD_MODULE object Predef + 8 CONSTANT("default") + 8 CALL_METHOD scala.Predef.println (dynamic) + 8 LOAD_FIELD scala.runtime.BoxedUnit.UNIT + 8 STORE_LOCAL(value x) + 8 JUMP 7 + + 7: + 10 LOAD_MODULE object Predef + 10 CONSTANT("done") + 10 CALL_METHOD scala.Predef.println (dynamic) + 10 RETURN(UNIT) + + } + Exception handlers: + + def <init>(): Case3.type { + locals: + startBlock: 1 + blocks: [1] + + 1: + 12 THIS(Case3) + 12 CALL_METHOD java.lang.Object.<init> (super()) + 12 RETURN(UNIT) + + } + Exception handlers: + + +} diff --git a/test/files/run/t6288b-jump-position.scala b/test/files/run/t6288b-jump-position.scala new file mode 100644 index 0000000000..e22a1ab120 --- /dev/null +++ b/test/files/run/t6288b-jump-position.scala @@ -0,0 +1,22 @@ +import scala.tools.partest.IcodeTest + +object Test extends IcodeTest { + override def code = + """object Case3 { // 01 + | def unapply(z: Any): Option[Int] = Some(-1) // 02 + | def main(args: Array[String]) { // 03 + | ("": Any) match { // 04 + | case x : String => // 05 Read: <linenumber> JUMP <target basic block id> + | println("case 0") // 06 expecting "6 JUMP 7", was "8 JUMP 7" + | case _ => // 07 + | println("default") // 08 expecting "8 JUMP 7" + | } // 09 + | println("done") // 10 + | } + |}""".stripMargin + + override def show() { + val lines1 = collectIcode("") + println(lines1 mkString "\n") + } +} |