summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala7
-rw-r--r--src/library/scala/collection/TraversableLike.scala2
-rw-r--r--src/library/scala/collection/immutable/Stream.scala24
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala44
4 files changed, 39 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index fa53ef48b5..4662ef6224 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -77,8 +77,11 @@ abstract class Flatten extends InfoTransform {
if (sym.isTerm && !sym.isStaticModule) {
decls1 enter sym
if (sym.isModule) {
- // Nested, non-static moduls are transformed to methods.
- assert(sym.isMethod, s"Non-static $sym should have the lateMETHOD flag from RefChecks")
+ // In theory, we could assert(sym.isMethod), because nested, non-static moduls are
+ // transformed to methods (lateMETHOD flag added in RefChecks). But this requires
+ // forcing sym.info (see comment on isModuleNotMethod), which forces stub symbols
+ // too eagerly (SI-8907).
+
// Note that module classes are not entered into the 'decls' of the ClassInfoType
// of the outer class, only the module symbols are. So the current loop does
// not visit module classes. Therefore we set the LIFTED flag here for module
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index a8731a51b1..d3a7db6968 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -253,7 +253,7 @@ trait TraversableLike[+A, +Repr] extends Any
b.result
}
- private[scala] def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = {
+ private def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x) != isFlipped) b += x
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 91a4e1c43d..714d5117d3 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -499,16 +499,6 @@ self =>
)
else super.flatMap(f)(bf)
- override private[scala] def filterImpl(p: A => Boolean, isFlipped: Boolean): Stream[A] = {
- // optimization: drop leading prefix of elems for which f returns false
- // var rest = this dropWhile (!p(_)) - forget DRY principle - GC can't collect otherwise
- var rest = this
- while (!rest.isEmpty && p(rest.head) == isFlipped) rest = rest.tail
- // private utility func to avoid `this` on stack (would be needed for the lazy arg)
- if (rest.nonEmpty) Stream.filteredTail(rest, p, isFlipped)
- else Stream.Empty
- }
-
/** Returns all the elements of this `Stream` that satisfy the predicate `p`
* in a new `Stream` - i.e., it is still a lazy data structure. The order of
* the elements is preserved
@@ -522,7 +512,15 @@ self =>
* // produces
* }}}
*/
- override def filter(p: A => Boolean): Stream[A] = filterImpl(p, isFlipped = false) // This override is only left in 2.11 because of binary compatibility, see PR #3925
+ override def filter(p: A => Boolean): Stream[A] = {
+ // optimization: drop leading prefix of elems for which f returns false
+ // var rest = this dropWhile (!p(_)) - forget DRY principle - GC can't collect otherwise
+ var rest = this
+ while (!rest.isEmpty && !p(rest.head)) rest = rest.tail
+ // private utility func to avoid `this` on stack (would be needed for the lazy arg)
+ if (rest.nonEmpty) Stream.filteredTail(rest, p)
+ else Stream.Empty
+ }
override final def withFilter(p: A => Boolean): StreamWithFilter = new StreamWithFilter(p)
@@ -1286,8 +1284,8 @@ object Stream extends SeqFactory[Stream] {
else cons(start, range(start + step, end, step))
}
- private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean, isFlipped: Boolean) = {
- cons(stream.head, stream.tail.filterImpl(p, isFlipped))
+ private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean) = {
+ cons(stream.head, stream.tail filter p)
}
private[immutable] def collectedTail[A, B, That](head: B, stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = {
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index b0c23ef45d..2c039ab5a7 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -735,31 +735,31 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def hasGetter = isTerm && nme.isLocalName(name)
- /** A little explanation for this confusing situation.
- * Nested modules which have no static owner when ModuleDefs
- * are eliminated (refchecks) are given the lateMETHOD flag,
- * which makes them appear as methods after refchecks.
- * Here's an example where one can see all four of FF FT TF TT
- * for (isStatic, isMethod) at various phases.
+ /**
+ * Nested modules which have no static owner when ModuleDefs are eliminated (refchecks) are
+ * given the lateMETHOD flag, which makes them appear as methods after refchecks.
+ *
+ * Note: the lateMETHOD flag is added lazily in the info transformer of the RefChecks phase.
+ * This means that forcing the `sym.info` may change the value of `sym.isMethod`. Forcing the
+ * info is in the responsability of the caller. Doing it eagerly here was tried (0ccdb151f) but
+ * has proven to lead to bugs (SI-8907).
*
- * trait A1 { case class Quux() }
- * object A2 extends A1 { object Flax }
- * // -- namer object Quux in trait A1
- * // -M flatten object Quux in trait A1
- * // S- flatten object Flax in object A2
- * // -M posterasure object Quux in trait A1
- * // -M jvm object Quux in trait A1
- * // SM jvm object Quux in object A2
+ * Here's an example where one can see all four of FF FT TF TT for (isStatic, isMethod) at
+ * various phases.
*
- * So "isModuleNotMethod" exists not for its achievement in
- * brevity, but to encapsulate the relevant condition.
+ * trait A1 { case class Quux() }
+ * object A2 extends A1 { object Flax }
+ * // -- namer object Quux in trait A1
+ * // -M flatten object Quux in trait A1
+ * // S- flatten object Flax in object A2
+ * // -M posterasure object Quux in trait A1
+ * // -M jvm object Quux in trait A1
+ * // SM jvm object Quux in object A2
+ *
+ * So "isModuleNotMethod" exists not for its achievement in brevity, but to encapsulate the
+ * relevant condition.
*/
- def isModuleNotMethod = {
- if (isModule) {
- if (phase.refChecked) this.info // force completion to make sure lateMETHOD is there.
- !isMethod
- } else false
- }
+ def isModuleNotMethod = isModule && !isMethod
// After RefChecks, the `isStatic` check is mostly redundant: all non-static modules should
// be methods (and vice versa). There's a corner case on the vice-versa with mixed-in module