From 28483739c365b1a3b748ebab50b03bd66a4db61d Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Sat, 14 Apr 2012 19:50:21 +0200 Subject: restore typedMatchAnonFun in all its glory detect partialfunction in cpsannotationchecker emit apply/isDefinedAt if PF has @cps targs (applyOrElse can't be typed) further hacky improvements to selective anf better try/catch support in selective cps using freshly minted anonfun match make virtpatmat resilient to scaladoc (after uncurry, don't translate matches TODO: factor out translation all together so presentation compiler/scaladoc can skip it) --- .../scala/reflect/internal/Definitions.scala | 7 +++ .../scala/tools/nsc/transform/UnCurry.scala | 6 +- .../tools/nsc/typechecker/PatMatVirtualiser.scala | 6 +- .../scala/tools/nsc/typechecker/Typers.scala | 73 ++++++++++++++-------- 4 files changed, 61 insertions(+), 31 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 72fca5da12..4d1dc69afc 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -400,6 +400,8 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.tpe) lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe)) lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe)) + + lazy val MarkerCPSTypes = getClassIfDefined("scala.util.continuations.cpsParam") def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass @@ -655,6 +657,11 @@ trait Definitions extends reflect.api.StandardDefinitions { false } + def isPartialFunctionType(tp: Type): Boolean = { + val sym = tp.typeSymbol + (sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass) + } + def isSeqType(tp: Type) = elementType(SeqClass, tp.normalize) != NoType def elementType(container: Symbol, tp: Type): Type = tp match { diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 57cd51ad35..6b894a724f 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -446,8 +446,10 @@ abstract class UnCurry extends InfoTransform } val members = - if (isPartial) List(applyOrElseMethodDef, isDefinedAtMethodDef) - else List(applyMethodDef) + if (isPartial) { + assert(!opt.virtPatmat, "PartialFunction should have been synthesized during typer "+ fun); + List(applyOrElseMethodDef, isDefinedAtMethodDef) + } else List(applyMethodDef) // println("MEMBERS "+ members) val res = localTyper.typedPos(fun.pos) { diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index 1fd9f6fc13..82e2442ba8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -135,7 +135,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => // we don't transform after uncurry // (that would require more sophistication when generating trees, // and the only place that emits Matches after typers is for exception handling anyway) - assert(phase.id < currentRun.uncurryPhase.id, phase) + if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ scrut +" match "+ cases) val scrutSym = freshSym(scrut.pos, pureType(scrutType)) setFlag SYNTH_CASE // pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental @@ -1107,7 +1107,9 @@ class Foo(x: Other) { x._1 } // no error in this order // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree - private def mkCast(t: Tree, tp: Type) = Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp) + private def mkCast(t: Tree, tp: Type) = + 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(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0541f85f31..ff54c11af8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2193,6 +2193,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def adaptCase(cdef: CaseDef, mode: Int, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe)) + // takes untyped sub-trees of a match and type checks them def typedMatch(selector0: Tree, cases: List[CaseDef], mode: Int, resTp: Type) = { val (selector, doTranslation) = selector0 match { case Annotated(Ident(nme.synthSwitch), selector) => (selector, false) @@ -2210,6 +2211,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { (selector1, selectorTp, casesAdapted, ownType, doTranslation) } + // match has been typed, now translate it def translatedMatch(selector1: Tree, selectorTp: Type, casesAdapted: List[CaseDef], ownType: Type, doTranslation: Boolean, matchFailGen: Option[Tree => Tree] = None) = { def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match { case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg) @@ -2271,11 +2273,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => TRUE_typed).duplicate) else Nil + def parentsPartial(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe) def applyMethod = { // rig the show so we can get started typing the method body -- later we'll correct the infos... anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass) - val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL) + val methodSym = anonClass.newMethod(nme.apply, tree.pos, if(isPartial) (FINAL | OVERRIDE) else FINAL) val (paramSyms, selector) = mkParams(methodSym) if (selector eq EmptyTree) EmptyTree @@ -2288,7 +2291,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, cases, mode, ptRes) val methFormals = paramSyms map (_.tpe) - val parents = List(abstractFunctionType(methFormals, resTp), SerializableClass.tpe) + val parents = + if (isPartial) parentsPartial(List(methFormals.head, resTp)) + else List(abstractFunctionType(methFormals, resTp), SerializableClass.tpe) anonClass setInfo ClassInfoType(parents, newScope, anonClass) methodSym setInfoAndEnter MethodType(paramSyms, resTp) @@ -2301,9 +2306,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def applyOrElseMethodDef = { // rig the show so we can get started typing the method body -- later we'll correct the infos... // targs were type arguments for PartialFunction, so we know they will work for AbstractPartialFunction as well - def parents(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe) - - anonClass setInfo ClassInfoType(parents(targs), newScope, anonClass) + anonClass setInfo ClassInfoType(parentsPartial(targs), newScope, anonClass) val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE) // create the parameter that corresponds to the function's parameter @@ -2325,7 +2328,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, cases, mode, ptRes) - anonClass setInfo ClassInfoType(parents(List(argTp, resTp)), newScope, anonClass) + anonClass setInfo ClassInfoType(parentsPartial(List(argTp, resTp)), newScope, anonClass) B1 setInfo TypeBounds.lower(resTp) anonClass.info.decls enter methodSym // methodSym's info need not change (B1's bound has been updated instead) @@ -2354,7 +2357,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - val members = if (!isPartial) List(applyMethod) else List(applyOrElseMethodDef, isDefinedAtMethod) + val members = if (isPartial) { + if ((MarkerCPSTypes ne NoSymbol) && (targs exists (_ hasAnnotation MarkerCPSTypes))) List(applyMethod, isDefinedAtMethod) + else List(applyOrElseMethodDef, isDefinedAtMethod) + } else List(applyMethod) + if (members.head eq EmptyTree) setError(tree) else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt) } @@ -2409,21 +2416,31 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - val vparamSyms = fun.vparams map { vparam => - enterSym(context, vparam) - if (context.retyping) context.scope enter vparam.symbol - vparam.symbol + fun.body match { + // later phase indicates scaladoc is calling (where shit is messed up, I tell you) + // -- so fall back to old patmat, which is more forgiving + case Match(sel, cases) if opt.virtPatmat && (phase.id < currentRun.uncurryPhase.id) => + // go to outer context -- must discard the context that was created for the Function since we're discarding the function + // thus, its symbol, which serves as the current context.owner, is not the right owner + // you won't know you're using the wrong owner until lambda lift crashes (unless you know better than to use the wrong owner) + newTyper(context.outer).typedMatchAnonFun(fun, cases, mode, pt, Some((fun.vparams, sel))) + case _ => + val vparamSyms = fun.vparams map { vparam => + enterSym(context, vparam) + if (context.retyping) context.scope enter vparam.symbol + vparam.symbol + } + val vparams = fun.vparams mapConserve (typedValDef) + // for (vparam <- vparams) { + // checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); () + // } + val formals = vparamSyms map (_.tpe) + val body1 = typed(fun.body, respt) + val restpe = packedType(body1, fun.symbol).deconst.resultType + val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) + // body = checkNoEscaping.locals(context.scope, restpe, body) + treeCopy.Function(fun, vparams, body1).setType(funtpe) } - val vparams = fun.vparams mapConserve (typedValDef) -// for (vparam <- vparams) { -// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); () -// } - val formals = vparamSyms map (_.tpe) - val body1 = typed(fun.body, respt) - val restpe = packedType(body1, fun.symbol).deconst.resultType - val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) -// body = checkNoEscaping.locals(context.scope, restpe, body) - treeCopy.Function(fun, vparams, body1).setType(funtpe) } } @@ -3795,9 +3812,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - // translation only happens when (selector != EmptyTree) && !isPastTyper && opt.virtPatmat def typedTranslatedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree = { - if (selector == EmptyTree) { + if (opt.virtPatmat && (phase.id < currentRun.uncurryPhase.id)) { + if (selector ne EmptyTree) { + val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = typedMatch(selector, cases, mode, pt) + typed(translatedMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt) + } else typedMatchAnonFun(tree, cases, mode, pt) + } else if (selector == EmptyTree) { + if (opt.virtPatmat) debugwarn("virtpatmat should not encounter empty-selector matches "+ tree) val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1 val params = for (i <- List.range(0, arity)) yield atPos(tree.pos.focusStart) { @@ -3808,7 +3830,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) } val body = treeCopy.Match(tree, selector1, cases) typed1(atPos(tree.pos) { Function(params, body) }, mode, pt) - } else if (!((phase.id < currentRun.uncurryPhase.id) && opt.virtPatmat)) { + } else { val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType)) var cases1 = typedCases(cases, packCaptured(selector1.tpe.widen), pt) val (owntype, needAdapt) = ptOrLub(cases1 map (_.tpe)) @@ -3816,9 +3838,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { cases1 = cases1 map (adaptCase(_, mode, owntype)) } treeCopy.Match(tree, selector1, cases1) setType owntype - } else { - val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = typedMatch(selector, cases, mode, pt) - typed(translatedMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt) } } -- cgit v1.2.3 From c2cd6acf993d66eac6f6917ee3b7300eeaceb8a3 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Sat, 14 Apr 2012 15:43:33 +0200 Subject: don't emit tiny switches: optimizer chokes on them workaround for inliner bug in run/t3835 see SI-5672 for the optimizer bug tiny switches (2 cases or less) don't make sense anyway, so this is not a big deal the annotDepMethType.flags contained -Xexperimental, which causes Any* to be considered as a valid return type, before we weren't exposed to this, because the product methods used (tiny) switches; with this change, they went back to pattern matches in any case, the -Xexperimental was intended to turn on dependent method types, not Any* as valid type (I can only assume), and they are now on by default the other tests were affected by our refusal to emit tiny switches --- .../tools/nsc/typechecker/PatMatVirtualiser.scala | 2 +- test/files/pos/annotDepMethType.flags | 1 - test/files/run/inline-ex-handlers.check | 109 +++++++++++---------- test/files/run/t5272_1.flags | 1 + test/files/run/t5272_2.flags | 1 + 5 files changed, 60 insertions(+), 54 deletions(-) delete mode 100644 test/files/pos/annotDepMethType.flags create mode 100644 test/files/run/t5272_1.flags create mode 100644 test/files/run/t5272_2.flags (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index 82e2442ba8..88cea2231f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -1570,7 +1570,7 @@ class Foo(x: Other) { x._1 } // no error in this order // TODO: if patterns allow switch but the type of the scrutinee doesn't, cast (type-test) the scrutinee to the corresponding switchable type and switch on the result if (regularSwitchMaker.switchableTpe(scrutSym.tpe)) { val caseDefsWithDefault = regularSwitchMaker(cases map {c => (scrutSym, c)}, pt) - if (caseDefsWithDefault isEmpty) None + if (caseDefsWithDefault.length <= 2) None // not worth emitting a switch... also, the optimizer has trouble digesting tiny switches, apparently, so let's be nice and not generate them else { // match on scrutSym -- converted to an int if necessary -- not on scrut directly (to avoid duplicating scrut) val scrutToInt: Tree = diff --git a/test/files/pos/annotDepMethType.flags b/test/files/pos/annotDepMethType.flags deleted file mode 100644 index e1b37447c9..0000000000 --- a/test/files/pos/annotDepMethType.flags +++ /dev/null @@ -1 +0,0 @@ --Xexperimental \ 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 708fcc6985..a5d7e93334 100644 --- a/test/files/run/inline-ex-handlers.check +++ b/test/files/run/inline-ex-handlers.check @@ -1,23 +1,27 @@ 172c172 -< locals: value x$1, value x1 +< locals: value x$1, value x1, value x2, value x --- -> locals: value x$1, value x1, variable boxed1 +> locals: value x$1, value x1, value x2, value x, variable boxed1 174c174 -< blocks: [1,2,3,4] +< blocks: [1,2,3,5,6,7] --- -> blocks: [1,3,4] -186a187,188 -> 92 STORE_LOCAL(variable boxed1) -> 92 LOAD_LOCAL(variable boxed1) -195,197d196 +> blocks: [1,3,5,6] +180,182d179 < 92 JUMP 2 < < 2: -385c384 +194,196d190 +< 92 JUMP 7 +< +< 7: +204a199,200 +> 92 STORE_LOCAL(variable boxed1) +> 92 LOAD_LOCAL(variable boxed1) +395c391 < blocks: [1,2,3,4,5,8,11,13,14,16] --- > blocks: [1,2,3,5,8,11,13,14,16,17] -409c408,417 +419c415,424 < 103 THROW(MyException) --- > ? STORE_LOCAL(value ex5) @@ -30,15 +34,15 @@ > 106 LOAD_LOCAL(value x3) > 106 IS_INSTANCE REF(class MyException) > 106 CZJUMP (BOOL)NE ? 5 : 11 -422,424d429 +432,434d436 < 101 JUMP 4 < < 4: -512c517 +522c524 < blocks: [1,2,3,4,6,7,8,9,10] --- > blocks: [1,2,3,4,6,7,8,9,10,11,12,13] -541c546,551 +551c553,558 < 306 THROW(MyException) --- > ? JUMP 11 @@ -47,7 +51,7 @@ > ? LOAD_LOCAL(variable monitor4) > 305 MONITOR_EXIT > ? JUMP 12 -547c557,563 +557c564,570 < ? THROW(Throwable) --- > ? JUMP 12 @@ -57,7 +61,7 @@ > 304 MONITOR_EXIT > ? STORE_LOCAL(value t) > ? JUMP 13 -553c569,582 +563c576,589 < ? THROW(Throwable) --- > ? STORE_LOCAL(value t) @@ -74,29 +78,30 @@ > 310 CALL_PRIMITIVE(EndConcat) > 310 CALL_METHOD scala.Predef.println (dynamic) > 310 JUMP 2 -577c606 +587c613 < catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6 --- > catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6 -580c609 +590c616 < 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 -612c641 +622c648 < blocks: [1,2,3,4,5,6,7,9,10] --- > blocks: [1,2,3,4,5,6,7,9,10,11,12] -636c665,671 +646c672,673 < 78 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) > ? JUMP 11 -> +647a675,679 > 11: > 81 LOAD_LOCAL(value e) > ? STORE_LOCAL(variable exc1) > ? JUMP 12 -665c700,714 +> +675c707,721 < 81 THROW(Exception) --- > ? STORE_LOCAL(variable exc1) @@ -114,15 +119,15 @@ > 84 STORE_LOCAL(variable result) > 84 LOAD_LOCAL(variable exc1) > 84 THROW(Throwable) -687c736 +697c743 < catch () in ArrayBuffer(4, 6, 7, 9) starting at: 3 --- > catch () in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3 -713c762 +723c769 < 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] -737c786,793 +747c793,800 < 172 THROW(MyException) --- > ? STORE_LOCAL(value ex5) @@ -133,12 +138,12 @@ > 170 STORE_LOCAL(value x3) > 170 SCOPE_ENTER value x3 > 170 JUMP 18 -793c849,850 +803c856,857 < 177 THROW(MyException) --- > ? STORE_LOCAL(value ex5) > ? JUMP 33 -797c854,861 +807c861,868 < 170 THROW(Throwable) --- > ? STORE_LOCAL(value ex5) @@ -149,17 +154,17 @@ > 169 STORE_LOCAL(value x3) > 169 SCOPE_ENTER value x3 > 169 JUMP 5 -830c894,895 +840c901,902 < 182 THROW(MyException) --- > ? STORE_LOCAL(variable exc2) > ? JUMP 34 -834c899,900 +844c906,907 < 169 THROW(Throwable) --- > ? STORE_LOCAL(variable exc2) > ? JUMP 34 -835a902,914 +845a909,921 > 34: > 184 LOAD_MODULE object Predef > 184 CONSTANT("finally") @@ -173,19 +178,19 @@ > 185 LOAD_LOCAL(variable exc2) > 185 THROW(Throwable) > -856c935 +866c942 < 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 -859c938 +869c945 < catch () in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3 --- > catch () in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3 -885c964 +895c971 < 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] -909c988,995 +919c995,1002 < 124 THROW(MyException) --- > ? STORE_LOCAL(value ex5) @@ -196,15 +201,15 @@ > 122 STORE_LOCAL(value x3) > 122 SCOPE_ENTER value x3 > 122 JUMP 7 -969c1055 +979c1062 < 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 -995c1081 +1005c1088 < blocks: [1,2,3,4,5,8,11,15,16,17,19] --- > blocks: [1,2,3,5,8,11,15,16,17,19,20] -1019c1105,1114 +1029c1112,1121 < 148 THROW(MyException) --- > ? STORE_LOCAL(value ex5) @@ -217,15 +222,15 @@ > 154 LOAD_LOCAL(value x3) > 154 IS_INSTANCE REF(class MyException) > 154 CZJUMP (BOOL)NE ? 5 : 11 -1040,1042d1134 +1050,1052d1141 < 145 JUMP 4 < < 4: -1275c1367 +1285c1374 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1299c1391,1398 +1309c1398,1405 < 38 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -236,16 +241,16 @@ > 42 CONSTANT("IllegalArgumentException") > 42 CALL_METHOD scala.Predef.println (dynamic) > 42 JUMP 2 -1348c1447 +1358c1454 < 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] -1372c1471,1472 +1382c1478,1479 < 203 THROW(MyException) --- > ? STORE_LOCAL(value ex5) > ? JUMP 20 -1392c1492,1501 +1402c1499,1508 < 209 THROW(MyException) --- > ? STORE_LOCAL(value ex5) @@ -258,15 +263,15 @@ > 212 LOAD_LOCAL(value x3) > 212 IS_INSTANCE REF(class MyException) > 212 CZJUMP (BOOL)NE ? 5 : 11 -1405,1407d1513 +1415,1417d1520 < 200 JUMP 4 < < 4: -1467c1573 +1477c1580 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1491c1597,1604 +1501c1604,1611 < 58 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -277,11 +282,11 @@ > 62 CONSTANT("RuntimeException") > 62 CALL_METHOD scala.Predef.println (dynamic) > 62 JUMP 2 -1540c1653 +1550c1660 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1560c1673,1678 +1570c1680,1685 < 229 THROW(MyException) --- > ? JUMP 5 @@ -290,19 +295,19 @@ > ? LOAD_LOCAL(variable monitor1) > 228 MONITOR_EXIT > 228 THROW(Throwable) -1566c1684 +1576c1691 < ? THROW(Throwable) --- > 228 THROW(Throwable) -1594c1712 +1604c1719 < locals: value args, variable result, variable monitor2, variable monitorResult1 --- > locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1 -1596c1714 +1606c1721 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1619c1737,1745 +1629c1744,1752 < 245 THROW(MyException) --- > ? STORE_LOCAL(value exception$1) @@ -314,7 +319,7 @@ > ? LOAD_LOCAL(variable monitor2) > 244 MONITOR_EXIT > 244 THROW(Throwable) -1625c1751 +1635c1758 < ? THROW(Throwable) --- > 244 THROW(Throwable) diff --git a/test/files/run/t5272_1.flags b/test/files/run/t5272_1.flags new file mode 100644 index 0000000000..cb8324a345 --- /dev/null +++ b/test/files/run/t5272_1.flags @@ -0,0 +1 @@ +-Xoldpatmat \ No newline at end of file diff --git a/test/files/run/t5272_2.flags b/test/files/run/t5272_2.flags new file mode 100644 index 0000000000..cb8324a345 --- /dev/null +++ b/test/files/run/t5272_2.flags @@ -0,0 +1 @@ +-Xoldpatmat \ No newline at end of file -- cgit v1.2.3 From 23ae258c37bd5de050ae9d8b4287dc8c309af8de Mon Sep 17 00:00:00 2001 From: Vlad Ureche Date: Mon, 16 Apr 2012 02:32:20 +0200 Subject: Inliner won't touch private/protected fields anymore And we'll need a separate mechanism for making internal fields public. --- src/compiler/scala/tools/nsc/CompilationUnits.scala | 3 +++ src/compiler/scala/tools/nsc/Global.scala | 3 ++- .../scala/tools/nsc/backend/opt/Inliners.scala | 18 +++++++++++------- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 92a0efff1e..369c59cd43 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -93,6 +93,9 @@ trait CompilationUnits { self: Global => def uncheckedWarning(pos: Position, msg: String) = currentRun.uncheckedWarnings.warn(pos, msg) + def inlinerWarning(pos: Position, msg: String) = + currentRun.inlinerWarnings.warn(pos, msg) + def incompleteInputError(pos: Position, msg:String) = reporter.incompleteInputError(pos, msg) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 403b5717b0..7cfccf3baf 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -964,7 +964,8 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S val deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation) val uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked) val featureWarnings = new ConditionalWarning("feature", settings.feature) - val allConditionalWarnings = List(deprecationWarnings, uncheckedWarnings, featureWarnings) + val inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings) + val allConditionalWarnings = List(deprecationWarnings, uncheckedWarnings, featureWarnings, inlinerWarnings) var reportedFeature = Set[Symbol]() diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index cf51a5b926..05d8c632c0 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -135,7 +135,7 @@ abstract class Inliners extends SubComponent { /** The current iclass */ private var currentIClazz: IClass = _ - private def warn(pos: Position, msg: String) = currentIClazz.cunit.warning(pos, msg) + private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg) val recentTFAs = mutable.Map.empty[Symbol, Tuple2[Boolean, analysis.MethodTFA]] private def getRecentTFA(incm: IMethod): (Boolean, analysis.MethodTFA) = { @@ -759,12 +759,16 @@ abstract class Inliners extends SubComponent { private def helperIsSafeToInline(stackLength: Int): Boolean = { def makePublic(f: Symbol): Boolean = - (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && { - debuglog("Making not-private symbol out of synthetic: " + f) - - f setNotFlag Flags.PRIVATE - true - } + /* + * Completely disabling member publifying. This shouldn't have been done in the first place. :| + */ + false + // (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && { + // debuglog("Making not-private symbol out of synthetic: " + f) + + // f setNotFlag Flags.PRIVATE + // true + // } if (!inc.m.hasCode || inc.isRecursive) { return false } if (inc.m.symbol.hasFlag(Flags.SYNCHRONIZED)) { return false } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index d4c2ffa832..6a5c4c92bc 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -138,6 +138,7 @@ trait ScalaSettings extends AbsScalaSettings val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.") val inlineHandlers = BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.") + val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)") val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") val log = PhasesSetting ("-Ylog", "Log operations during") val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.") -- cgit v1.2.3