diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-05-23 09:25:11 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-05-31 13:40:27 +0200 |
commit | d2faeb9ae60389668f1b5f45eb91c73127401e40 (patch) | |
tree | 5a2448d8a6a3bbc14ce81d90c68300a31c56b3b9 | |
parent | 681f2070053bc6f3133425b44083fe056bfeb1fa (diff) | |
download | scala-d2faeb9ae60389668f1b5f45eb91c73127401e40.tar.gz scala-d2faeb9ae60389668f1b5f45eb91c73127401e40.tar.bz2 scala-d2faeb9ae60389668f1b5f45eb91c73127401e40.zip |
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.
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 12 | ||||
-rw-r--r-- | test/files/neg/t7507.check | 4 | ||||
-rw-r--r-- | test/files/neg/t7507.scala | 7 | ||||
-rw-r--r-- | test/files/run/t7507.scala | 31 |
4 files changed, 52 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index ee584bed2c..fc3f5de77f 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/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) diff --git a/test/files/neg/t7507.check b/test/files/neg/t7507.check new file mode 100644 index 0000000000..d402869fd4 --- /dev/null +++ b/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 diff --git a/test/files/neg/t7507.scala b/test/files/neg/t7507.scala new file mode 100644 index 0000000000..1b4756d955 --- /dev/null +++ b/test/files/neg/t7507.scala @@ -0,0 +1,7 @@ +trait Cake extends Slice { + private[this] val bippy = () +} + +trait Slice { self: Cake => + locally(bippy) +} diff --git a/test/files/run/t7507.scala b/test/files/run/t7507.scala new file mode 100644 index 0000000000..6c1959ddac --- /dev/null +++ b/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)) +} |