diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2012-10-25 08:00:16 +0200 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-11-02 12:27:54 -0700 |
commit | a525d371e10b2bb9b6a2228f67603aa318f97716 (patch) | |
tree | eea8a41a840d7971bc963b30464eb2e0bcae96bf /src | |
parent | f8ed076e251ff8b6e2b1d27f8c8a0dde2117308d (diff) | |
download | scala-a525d371e10b2bb9b6a2228f67603aa318f97716.tar.gz scala-a525d371e10b2bb9b6a2228f67603aa318f97716.tar.bz2 scala-a525d371e10b2bb9b6a2228f67603aa318f97716.zip |
SI-6562 Fix crash with class nested in @inline method
e6b4204604 moved access widenings from ExplicitOuter to
SuperAccessors to reflect them in pickled signatures so
that the inliner can take advantage of them under separate
compilation.
The followup discussion [1] determined that this wasn't
the right solution: while it enabled new separate compilation
inlinings, it failed to widen access of outer pointers and
hence prevented certain inlinings.
A better solution was proposed: modify the inliner to know
that access widening is guaranteed to have happened in
ExplicitOuter for any field accessed by an @inline-d method
body, rather than relying solely on the pickled types.
But this hasn't happened yet. In the meantime 07f94297 / #1121
reinstated the access widening to SuperAccessors, but took a
slightly different approach, using `Symbol#enclMethod` rather
than `closestEnclMethod`. That deviation triggers SI-6562.
This commit goes back to `closestEnclMethod`.
[1] https://groups.google.com/forum/#!topic/scala-internals/iPkMCygzws4
Diffstat (limited to 'src')
3 files changed, 17 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 77ad65957d..3ac19650eb 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -499,8 +499,11 @@ abstract class ExplicitOuter extends InfoTransform case Select(qual, name) => // make not private symbol acessed from inner classes, as well as // symbols accessed from @inline methods + // + // See SI-6552 for an example of why `sym.owner.enclMethod hasAnnotation ScalaInlineClass` + // is not suitable; if we make a method-local class non-private, it mangles outer pointer names. if (currentClass != sym.owner || - (sym.owner.enclMethod hasAnnotation ScalaInlineClass)) + (closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass)) sym.makeNotPrivate(sym.owner) val qsym = qual.tpe.widen.typeSymbol diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 981ba10183..6b9848a1c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -234,14 +234,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case sel @ Select(qual, name) => def transformSelect = { - /** 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) + // FIXME Once Inliners is modified with the "'meta-knowledge' that all fields accessed by @inline will be made public" [1] + // this can be removed; the correct place for this in in ExplicitOuter. + // + // [1] https://groups.google.com/forum/#!topic/scala-internals/iPkMCygzws4 + // if (closestEnclMethod(currentOwner) hasAnnotation definitions.ScalaInlineClass) sym.makeNotPrivate(sym.owner) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index a6f156f947..4afebab493 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3269,6 +3269,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) + /** Return closest enclosing method, unless shadowed by an enclosing class. */ + // TODO Move back to ExplicitOuter when the other call site is removed. + // no use of closures here in the interest of speed. + final def closestEnclMethod(from: Symbol): Symbol = + if (from.isSourceMethod) from + else if (from.isClass) NoSymbol + else closestEnclMethod(from.owner) + /** An exception for cyclic references of symbol definitions */ case class CyclicReference(sym: Symbol, info: Type) extends TypeError("illegal cyclic reference involving " + sym) { |