Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

SI-7507 Fix lookup of private[this] member in presence of self type.

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...
commit d2faeb9ae60389668f1b5f45eb91c73127401e40 1 parent 681f207
@retronym retronym authored
View
12 src/reflect/scala/reflect/internal/Types.scala
@@ -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)
@@ -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)
View
4 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
View
7 test/files/neg/t7507.scala
@@ -0,0 +1,7 @@
+trait Cake extends Slice {
+ private[this] val bippy = ()
+}
+
+trait Slice { self: Cake =>
+ locally(bippy)
+}
View
31 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))
+}
Please sign in to comment.
Something went wrong with that request. Please try again.