Skip to content

Commit

Permalink
SI-7507 Fix lookup of private[this] member in presence of self type.
Browse files Browse the repository at this point in the history
In the following code:

	trait Cake extends Slice

	trait Slice { self: Cake =>    // must have self type that extends `Slice`
	  private[this] val bippy = () // must be private[this]
	  locally(bippy)
	}

`ThisType(<Slice>)`.findMember(bippy)` excluded the private local member on
the grounds that the first class in the base type sequence, `Cake`, was
not contained in `Slice`.

	scala> val thisType = typeOf[Slice].typeSymbol.thisType
	thisType: $r.intp.global.Type = Slice.this.type

	scala> thisType.baseClasses
	res6: List[$r.intp.global.Symbol] = List(trait Cake, trait Slice, class Object, class Any)

This commit changes `findMember` to use the symbol of the `ThisType`, rather
than the first base class, as the location of the selection.
  • Loading branch information
retronym committed May 31, 2013
1 parent 681f207 commit d2faeb9
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/reflect/scala/reflect/internal/Types.scala
Expand Up @@ -1172,6 +1172,14 @@ trait Types extends api.Types { self: SymbolTable =>
continue = false
val bcs0 = baseClasses
var bcs = bcs0
// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
def admitPrivateLocal(owner: Symbol): Boolean = {
val selectorClass = this match {
case tt: ThisType => tt.sym // SI-7507 the first base class is not necessarily the selector class.
case _ => bcs0.head
}
selectorClass.hasTransOwner(owner)
}
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
var entry = decls.lookupEntry(name)
Expand All @@ -1181,10 +1189,10 @@ trait Types extends api.Types { self: SymbolTable =>
if ((flags & required) == required) {
val excl = flags & excluded
if (excl == 0L &&
(// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
(
(bcs eq bcs0) ||
(flags & PrivateLocal) != PrivateLocal ||
(bcs0.head.hasTransOwner(bcs.head)))) {
admitPrivateLocal(bcs.head))) {
if (name.isTypeName || stableOnly && sym.isStable) {
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
if (suspension ne null) suspension foreach (_.suspended = false)
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/t7507.check
@@ -0,0 +1,4 @@
t7507.scala:6: error: value bippy in trait Cake cannot be accessed in Cake
locally(bippy)
^
one error found
7 changes: 7 additions & 0 deletions test/files/neg/t7507.scala
@@ -0,0 +1,7 @@
trait Cake extends Slice {
private[this] val bippy = ()
}

trait Slice { self: Cake =>
locally(bippy)
}
31 changes: 31 additions & 0 deletions test/files/run/t7507.scala
@@ -0,0 +1,31 @@
trait Cake extends Slice

// Minimization
trait Slice { self: Cake => // must have self type that extends `Slice`
private[this] val bippy = () // must be private[this]
locally(bippy)
}

// Originally reported bug:
trait Cake1 extends Slice1
trait Slice1 { self: Cake1 =>
import java.lang.String // any import will do!
val Tuple2(x, y) = ((1, 2))
}


// Nesting
trait Cake3 extends Outer.Slice3

// Minimization
object Outer {
private[this] val bippy = ()
trait Slice3 { self: Cake3 =>
locally(bippy)
}
}

object Test extends App {
val s1 = new Cake1 {}
assert((s1.x, s1.y) == (1, 2), (s1.x, s1.y))
}

0 comments on commit d2faeb9

Please sign in to comment.