From 286dafbd45caa2b85f8113845105aaaec98be71a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 16 Jan 2015 13:25:31 +1000 Subject: SI-9050 Fix crasher with value classes, recursion From the "Substitution is hard to do" department. In 7babdab9a, TreeSymSubstitutor was modified to mutate the info of symbols defined in the tree, if that symbol's info referred to one of the `from` symbols in the substitution. It would have been more principled to create a cloned symbol with the updated info, and add that to the substitution. But I wasn't able implement that correctly (let alone efficiently.) The in-place mutation of the info of a symbol led to the crasher in this bug: a singleton type over that symbol ends up with a stale cached value of 'underlying'. In the enclosed test case, this leads to a type error in the `SubstituteRecursion` of the extension methods phase. This commit performs a cleanup job at the end of `substituteSymbols` by invalidating the cache of any `SingleType`-s in the tree that refer to one of the mutated symbols. --- test/files/pos/t9050.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/files/pos/t9050.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t9050.scala b/test/files/pos/t9050.scala new file mode 100644 index 0000000000..b1ab09f901 --- /dev/null +++ b/test/files/pos/t9050.scala @@ -0,0 +1,13 @@ +final class Mu[F](val value: Any) extends AnyVal { + def cata(f: F) { + // crash + ((y: Mu[F]) => y.cata(f)) + // crash + def foo(x : Mu[F]) = x.cata(f) + + // // okay + def x: Mu[F] = ??? + (() => x.cata(f)) + assert(true, cata(f)) + } +} -- cgit v1.2.3 From 3c97888ab896e7ffc63e44515902aba1c5022072 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 15 Jan 2015 11:16:05 +1000 Subject: SI-9086 Fix regression in implicit search Implicit search declines to force the info of candidate implicits that either a) are defined beyond the position of the implicit search site, or b) enclose the implicit search site. The second criterion used to prevent consideration of `O` in the super constructor call: implicit object O extends C( { implicitly[X] }) However, after https://github.com/scala/scala/pull/4043, the block containing the implicit search is typechecked in a context owned by a local dummy symbol rather than by `O`. (The dummy and `O` share an owner.) This led to `O` being considered as a candidate for this implicit search. This search is undertaken during completion of the info of `O`, which leads to it being excluded on account of the LOCKED flag. Unfortunately, this also excludes it from use in implicit search sites subsequent to `O`, as `ImplicitInfo` caches `isCyclicOrErroneous`. This commit adjusts the position of the local dummy to be identical to that of the object. This serves to exclude `O` as a candidate during the super call on account of criterion a). --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 6 +++++- test/files/pos/t9086.scala | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t9086.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e6fa9a0142..d33f98109d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1536,7 +1536,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1) val clazz = context.owner assert(clazz != NoSymbol, templ) - val dummy = context.outer.owner.newLocalDummy(templ.pos) + // SI-9086 The position of this symbol is material: implicit search will avoid triggering + // cyclic errors in an implicit search in argument to the super constructor call on + // account of the "ignore symbols without complete info that succeed the implicit search" + // in this source file. See `ImplicitSearch#isValid` and `ImplicitInfo#isCyclicOrErroneous`. + val dummy = context.outer.owner.newLocalDummy(context.owner.pos) val cscope = context.outer.makeNewScope(ctor, dummy) if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file val cbody2 = { // called both during completion AND typing. diff --git a/test/files/pos/t9086.scala b/test/files/pos/t9086.scala new file mode 100644 index 0000000000..fba34ee226 --- /dev/null +++ b/test/files/pos/t9086.scala @@ -0,0 +1,8 @@ +class X[A](a: A) +object Test { + implicit val ImplicitBoolean: Boolean = true + def local = { + implicit object X extends X({ implicitly[Boolean] ; "" }) + implicitly[X[String]] // failed in 2.11.5 + } +} -- cgit v1.2.3 From 9735108e9bb13b7b5a48bd2a051a5ec3e8a2f2ac Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 29 Jan 2015 16:01:32 +1000 Subject: SI-9123 More coherent trees with patmat, dependent types The pattern matcher needs to substitute references to bound variables with references to either a) synthetic temporary vals, or to b) selections. The latter occurs under -optimize to avoid to be frugal with local variable slots. For instance: ``` def test(s: Some[String]) = s match { case Some(elem) => elem.length } ``` Is translated to: ``` def test(s: Some[String]): Int = { case val x1: Some[String] = s; case4(){ if (x1.ne(null)) matchEnd3(x1.x.length()) else case5() }; case5(){ matchEnd3(throw new MatchError(x1)) }; matchEnd3(x: Int){ x } } ``` However, for a long time this translation failed to consider references to the binder in types. #4122 tried to address this by either using standard substitution facilities where available (references to temp vals), and by expanding the patmat's home grown substitution to handle the more complex case of referencing a selection. However, this left the tree in an incoherent state; while it patched up the `.tpe` field of `Tree`s, it failed to modify the info of `Symbol`-s. This led to a crash in the later uncurry phase under `-Ydelambdafy:method`. This commit modifies the info of such symbols to get rid of stray refeferences to the pattern binder symbols. --- .../scala/tools/nsc/transform/patmat/PatternMatching.scala | 5 +++++ test/files/pos/t9123.flags | 1 + test/files/pos/t9123.scala | 10 ++++++++++ 3 files changed, 16 insertions(+) create mode 100644 test/files/pos/t9123.flags create mode 100644 test/files/pos/t9123.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index d35aad964d..b2f2516b5b 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -239,6 +239,11 @@ trait Interface extends ast.TreeDSL { case Ident(_) => subst(from, to) case _ => super.transform(tree) } + tree1 match { + case _: DefTree => + tree1.symbol.modifyInfo(_.substituteTypes(from, toTypes)) + case _ => + } tree1.modifyType(_.substituteTypes(from, toTypes)) } } diff --git a/test/files/pos/t9123.flags b/test/files/pos/t9123.flags new file mode 100644 index 0000000000..c16e2f71dc --- /dev/null +++ b/test/files/pos/t9123.flags @@ -0,0 +1 @@ +-optimize -Ydelambdafy:method diff --git a/test/files/pos/t9123.scala b/test/files/pos/t9123.scala new file mode 100644 index 0000000000..22d55b4351 --- /dev/null +++ b/test/files/pos/t9123.scala @@ -0,0 +1,10 @@ +trait Setting { + type T + def value: T +} + +object Test { + def test(x: Some[Setting]) = x match { + case Some(dep) => Some(dep.value) map (_ => true) + } +} -- cgit v1.2.3 From 6b26f3b6a187c4c8f606b8f7e4b0ae84dc9cdebe Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 5 Feb 2015 12:23:21 +1000 Subject: SI-9135 Fix NPE, a regression in the pattern matcher The community build discovered that #4252 introduced the possibility for a NullPointerException. The tree with a null type was a synthetic `Apply(<>)` created by the pattern matcher. This commit adds a null check. --- src/reflect/scala/reflect/internal/Trees.scala | 2 +- test/files/pos/t9135.scala | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t9135.scala (limited to 'test/files/pos') diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index ccf907e05d..fd918b8595 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1622,7 +1622,7 @@ trait Trees extends api.Trees { } private def invalidateSingleTypeCaches(tree: Tree): Unit = { if (mutatedSymbols.nonEmpty) - for (t <- tree) + for (t <- tree if t.tpe != null) for (tp <- t.tpe) { tp match { case s: SingleType if mutatedSymbols contains s.sym => diff --git a/test/files/pos/t9135.scala b/test/files/pos/t9135.scala new file mode 100644 index 0000000000..1e2c97baf9 --- /dev/null +++ b/test/files/pos/t9135.scala @@ -0,0 +1,16 @@ + +class Free[A] { + + + this match { + case a @ Gosub() => gosub(a.a)(x => gosub(???)(???)) + } + def gosub[A, B](a0: Free[A])(f0: A => Any): Free[B] = ??? +} + + + + case class Gosub[B]() extends Free[B] { + type C + def a: Free[C] = ??? + } -- cgit v1.2.3 From 5412766a834fa730865628a57c767f36eb1b4dc4 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 26 Jan 2015 22:35:44 -0800 Subject: SI-9116 Set.subsets has a param list Now both of the overloaded variants have a parameter list. This seems to make type inference happier. Or it makes someone happier. The user is unaware whether `subsets()` takes a default arg. But happily, empty application still kicks in. --- src/library/scala/collection/SetLike.scala | 2 +- test/files/pos/t9116.scala | 7 +++++++ test/files/run/settings-parse.scala | 5 ++--- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 test/files/pos/t9116.scala (limited to 'test/files/pos') diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala index 3e549f72cd..31465bb619 100644 --- a/src/library/scala/collection/SetLike.scala +++ b/src/library/scala/collection/SetLike.scala @@ -171,7 +171,7 @@ self => * * @return the iterator. */ - def subsets: Iterator[This] = new AbstractIterator[This] { + def subsets(): Iterator[This] = new AbstractIterator[This] { private val elms = self.toIndexedSeq private var len = 0 private var itr: Iterator[This] = Iterator.empty diff --git a/test/files/pos/t9116.scala b/test/files/pos/t9116.scala new file mode 100644 index 0000000000..16b04c2e6b --- /dev/null +++ b/test/files/pos/t9116.scala @@ -0,0 +1,7 @@ + +trait X { + List(1, 2, 3).toSet.subsets.map(_.toList) // ok now + + List(1, 2, 3).toSet.subsets().map(_.toList) // now also + List(1, 2, 3).toSet.subsets(2).map(_.toList) // still ok +} diff --git a/test/files/run/settings-parse.scala b/test/files/run/settings-parse.scala index 2754feb972..8d83caf68f 100644 --- a/test/files/run/settings-parse.scala +++ b/test/files/run/settings-parse.scala @@ -3,9 +3,8 @@ import scala.language.postfixOps import scala.tools.nsc._ object Test { - val tokens = List("", "-deprecation", "foo.scala") - val subsets = tokens.toSet.subsets.toList - val permutations0 = subsets.flatMap(_.toList.permutations).distinct + val tokens = "" :: "-deprecation" :: "foo.scala" :: Nil + val permutations0 = tokens.toSet.subsets.flatMap(_.toList.permutations).toList.distinct def runWithCp(cp: String) = { val permutations = permutations0 flatMap ("-cp CPTOKEN" :: _ permutations) -- cgit v1.2.3 From b6cbee9d81320524aa2e8a3d80dbf2062dd43fd2 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 18 Feb 2015 14:02:08 +1000 Subject: SI-9157 Avoid exponential blowup with chained type projections Calling `findMember` in the enclosed test was calling into `NonClassTypeRef#relativeInfo` an exponentially-increasing number of times, with respect to the length of the chained type projections. The numbers of calls increased as: 26, 326, 3336, 33446, 334556. Can any pattern spotters in the crowd that can identify the sequence? (I can't.) Tracing the calls saw we were computing the same `memberType` repeatedly. This part of the method was not guarded by the cache. I have changed the method to use the standard idiom of using the current period for cache invalidation. The enclosed test now compiles promptly, rather than in geological time. --- src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala | 1 - src/reflect/scala/reflect/internal/Types.scala | 10 +++++----- test/files/pos/t9157.scala | 13 +++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 test/files/pos/t9157.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 743bbe53bd..02356580cc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -266,7 +266,6 @@ abstract class TreeCheckers extends Analyzer { if (tree ne typed) treesDiffer(tree, typed) - tree } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index ce36f7efa3..8f114caac0 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1976,13 +1976,13 @@ trait Types * usage scenario. */ private var relativeInfoCache: Type = _ - private var memberInfoCache: Type = _ + private var relativeInfoPeriod: Period = NoPeriod - private[Types] def relativeInfo = { - val memberInfo = pre.memberInfo(sym) - if (relativeInfoCache == null || (memberInfo ne memberInfoCache)) { - memberInfoCache = memberInfo + private[Types] def relativeInfo = /*trace(s"relativeInfo(${safeToString}})")*/{ + if (relativeInfoPeriod != currentPeriod) { + val memberInfo = pre.memberInfo(sym) relativeInfoCache = transformInfo(memberInfo) + relativeInfoPeriod = currentPeriod } relativeInfoCache } diff --git a/test/files/pos/t9157.scala b/test/files/pos/t9157.scala new file mode 100644 index 0000000000..e178b5d84d --- /dev/null +++ b/test/files/pos/t9157.scala @@ -0,0 +1,13 @@ +trait Flow[-In, +Out] { + type Repr[+O] <: Flow[In, O] + def map: Repr[String] +} + +class Test { + // typechecking was exponentially slow wrt the number of projections here. + def slowFlow( + f: Flow[String,String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String]#Repr[String] + ) = { + f.map + } +} -- cgit v1.2.3 From cbdb95f9cd266beba3640368548a413690c40b8d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 20 Feb 2015 08:03:12 +1000 Subject: SI-8801 Another test for fixed exponential-time compilation Turns out that SI-9157 was a duplicate of SI-8801. This commit adds Paul's test, whose compile time is now back in the troposphere. % time qscalac test/files/pos/t8801.scala real 0m1.294s user 0m3.978s sys 0m0.240s --- test/files/pos/t8801.scala | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/files/pos/t8801.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t8801.scala b/test/files/pos/t8801.scala new file mode 100644 index 0000000000..695b456e12 --- /dev/null +++ b/test/files/pos/t8801.scala @@ -0,0 +1,21 @@ +sealed trait Nat { + type Prev <: Nat { type Succ = Nat.this.type } + type Succ <: Nat { type Prev = Nat.this.type } +} + +object Nat { + object Zero extends Nat { + type Prev = Nothing + } + + type _0 = Zero.type + type _1 = _0#Succ + type _2 = _1#Succ + type _3 = _2#Succ + type _4 = _3#Succ + type _5 = _4#Succ + type _6 = _5#Succ + type _7 = _6#Succ + type _8 = _7#Succ + type _9 = _8#Succ +} -- cgit v1.2.3 From 027e97981d9b6a3783e9ab247cc898017b3de821 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 11 Mar 2015 11:34:08 -0700 Subject: Workaround for SI-9111 The inliner forces some method symbols to complete that would not be completed otherwise. This triggers SI-9111, in which the completer of a valid Java method definition reports an error in mixed compilation. The workaround disables error reporting while completing lazy method and class symbols in the backend. --- .../scala/tools/nsc/backend/jvm/BTypes.scala | 6 +- .../tools/nsc/backend/jvm/BTypesFromSymbols.scala | 69 +++++++++++++++++----- .../nsc/backend/jvm/opt/OptimizerReporting.scala | 1 + test/files/pos/t9111-inliner-workaround.flags | 1 + test/files/pos/t9111-inliner-workaround/A_1.java | 13 ++++ .../pos/t9111-inliner-workaround/Test_1.scala | 10 ++++ 6 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 test/files/pos/t9111-inliner-workaround.flags create mode 100644 test/files/pos/t9111-inliner-workaround/A_1.java create mode 100644 test/files/pos/t9111-inliner-workaround/Test_1.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index e617c86b23..81d8adb7de 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -12,7 +12,7 @@ import asm.Opcodes import scala.tools.asm.tree.{InnerClassNode, ClassNode} import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InlineInfo} import scala.tools.nsc.backend.jvm.opt.{CallGraph, ByteCodeRepository, Inliner} -import OptimizerReporting._ +import opt.OptimizerReporting._ import scala.collection.convert.decorateAsScala._ /** @@ -736,8 +736,10 @@ abstract class BTypes { /** * A ClassBType represents a class or interface type. The necessary information to build a * ClassBType is extracted from compiler symbols and types, see BTypesFromSymbols. + * + * Currently non-final due to SI-9111 */ - final case class ClassBType(internalName: InternalName) extends RefBType { + /*final*/ case class ClassBType(internalName: InternalName) extends RefBType { /** * Write-once variable allows initializing a cyclic graph of infos. This is required for * nested classes. Example: for the definition `class A { class B }` we have diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index d94bd77851..9fdb92b47c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -146,13 +146,48 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { else { val internalName = classSym.javaBinaryName.toString classBTypeFromInternalName.getOrElse(internalName, { - // The new ClassBType is added to the map in its constructor, before we set its info. This - // allows initializing cyclic dependencies, see the comment on variable ClassBType._info. - setClassInfo(classSym, ClassBType(internalName)) + if (completeSilentlyAndCheckErroneous(classSym)) { + new ErroneousClassBType(internalName) + } else { + // The new ClassBType is added to the map in its constructor, before we set its info. This + // allows initializing cyclic dependencies, see the comment on variable ClassBType._info. + setClassInfo(classSym, ClassBType(internalName)) + } }) } } + /** + * Part of the workaround for SI-9111. Makes sure that the compiler only fails if the ClassInfo + * of the symbol that could not be completed is actually required. + */ + private class ErroneousClassBType(internalName: InternalName) extends ClassBType(internalName) { + def msg = s"The class info for $internalName could not be completed due to SI-9111." + override def info: ClassInfo = opt.OptimizerReporting.assertionError(msg) + override def info_=(i: ClassInfo): Unit = opt.OptimizerReporting.assertionError(msg) + } + + /** + * This is a hack to work around SI-9111. The completer of `methodSym` may report type errors. We + * cannot change the typer context of the completer at this point and make it silent: the context + * captured when creating the completer in the namer. However, we can temporarily replace + * global.reporter (it's a var) to store errors. + */ + def completeSilentlyAndCheckErroneous(sym: Symbol): Boolean = { + if (sym.rawInfo.isComplete) false + else { + val originalReporter = global.reporter + val storeReporter = new reporters.StoreReporter() + try { + global.reporter = storeReporter + sym.info + } finally { + global.reporter = originalReporter + } + storeReporter.infos.exists(_.severity == storeReporter.ERROR) + } + } + /** * Builds a [[MethodBType]] for a method symbol. */ @@ -428,18 +463,24 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { else { // Primitve methods cannot be inlined, so there's no point in building an InlineInfo. Also, some // primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]]. - classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).map({ + classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).flatMap({ case methodSym => - val methodBType = methodBTypeFromSymbol(methodSym) - val name = methodSym.javaSimpleName.toString // same as in genDefDef - val signature = name + methodBType.descriptor - val info = MethodInlineInfo( - effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden, - traitMethodWithStaticImplementation = false, // temporary, fixed in future commit - annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), - annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass) - ) - (signature, info) + if (completeSilentlyAndCheckErroneous(methodSym)) { + // Happens due to SI-9111. Just don't provide any InlineInfo for that method, we don't + // need fail the compiler. + None + } else { + val methodBType = methodBTypeFromSymbol(methodSym) + val name = methodSym.javaSimpleName.toString // same as in genDefDef + val signature = name + methodBType.descriptor + val info = MethodInlineInfo( + effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden, + traitMethodWithStaticImplementation = false, // temporary, fixed in future commit + annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), + annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass) + ) + Some((signature, info)) + } }).toMap } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala index 53c00c7724..5b47bc88c2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala @@ -5,6 +5,7 @@ package scala.tools.nsc package backend.jvm +package opt import scala.tools.asm import asm.tree._ diff --git a/test/files/pos/t9111-inliner-workaround.flags b/test/files/pos/t9111-inliner-workaround.flags new file mode 100644 index 0000000000..63b5558cfd --- /dev/null +++ b/test/files/pos/t9111-inliner-workaround.flags @@ -0,0 +1 @@ +-Ybackend:GenBCode -Yopt:l:classpath \ No newline at end of file diff --git a/test/files/pos/t9111-inliner-workaround/A_1.java b/test/files/pos/t9111-inliner-workaround/A_1.java new file mode 100644 index 0000000000..bc60b68ea6 --- /dev/null +++ b/test/files/pos/t9111-inliner-workaround/A_1.java @@ -0,0 +1,13 @@ +public class A_1 { + public static class T { } + + public static class Inner { + public static class T { } + + public void foo(T t) { } + + public T t = null; + + public class Deeper extends T { } + } +} diff --git a/test/files/pos/t9111-inliner-workaround/Test_1.scala b/test/files/pos/t9111-inliner-workaround/Test_1.scala new file mode 100644 index 0000000000..1a00fff833 --- /dev/null +++ b/test/files/pos/t9111-inliner-workaround/Test_1.scala @@ -0,0 +1,10 @@ +object Test extends App { + println(new A_1.Inner()) + + // Accessing foo or Deeper triggers the error of SI-9111. + // However, when not referring to those definitions, compilation should + // succeed, also if the inliner is enabled. + + // println(i.foo(null)) + // new i.Deeper() +} -- cgit v1.2.3 From d0181ab3810f1e063b33e79b43f183a098de2aab Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 17 Mar 2015 18:14:08 -0700 Subject: Resurrect a test for type inference This test was removed in ... when case class extension was disallowed. But the intent of the test was actually to exercise a path through type inference, described in `Infer#exprTypeArgs`. When I remove that special case, the test still fails: ``` test/files/pos/jesper.scala:29: error: No implicit view available from Pair.Cons[Int,Pair.Cons[Boolean,Pair.End]] => Boolean. val x2 : Boolean = p.find[Boolean] // Doesn't compile ^ one error found ``` This special case is important to understand when deciphering the inference in this program: ``` object Test { trait Cov[+A] def cov[A](implicit ev: Cov[A]): A = ??? implicit def covImp[A]: Cov[A] = ??? trait Inv[A] def inv[A](implicit ev: Inv[A]): A = ??? implicit def invImp[A]: Inv[A] = ??? trait Con[-A] def con[A](implicit ev: Con[A]): A = ??? implicit def conImp[A]: Con[A] = ??? cov : String // (Test.this.cov[String](Test.this.covImp[Nothing]): String); // (Test.this.cov[Nothing](Test.this.covImp[Nothing]): String) (or, without the special case in exprTypeArgs) inv : String // (Test.this.inv[Nothing](Test.this.invImp[Nothing]): String); con : String // (Test.this.con[Any](Test.this.conImp[Any]): String) } ``` --- test/files/pos/jesper.scala | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/files/pos/jesper.scala (limited to 'test/files/pos') diff --git a/test/files/pos/jesper.scala b/test/files/pos/jesper.scala new file mode 100644 index 0000000000..82623e4a24 --- /dev/null +++ b/test/files/pos/jesper.scala @@ -0,0 +1,30 @@ +object Pair { + sealed trait Pair { + type First + type Second <: Pair + } + + case class End() extends Pair { + type First = Nothing + type Second = End + + def ::[T](v : T) : Cons[T, End] = Cons(v, this) + } + + object End extends End() + + final case class Cons[T1, T2 <: Pair](_1 : T1, _2 : T2) extends Pair { + type First = T1 + type Second = T2 + + def ::[T](v : T) : Cons[T, Cons[T1, T2]] = Cons(v, this) + def find[T](implicit finder : Cons[T1, T2] => T) = finder(this) + } + + implicit def findFirst[T1, T2 <: Pair] : Cons[T1, T2] => T1 = (p : Cons[T1, T2]) => p._1 + implicit def findSecond[T, T1, T2 <: Pair](implicit finder : T2 => T) : Cons[T1, T2] => T = (p : Cons[T1, T2]) => finder(p._2) + + val p : Cons[Int, Cons[Boolean, End]] = 10 :: false :: End +// val x : Boolean = p.find[Boolean](findSecond(findFirst)) + val x2 : Boolean = p.find[Boolean] // Doesn't compile +} -- cgit v1.2.3