Skip to content

Commit 876590b

Browse files
committed
Merge pull request scala#3614 from retronym/ticket/8196
SI-8196 Runtime reflection robustness for STATIC impl details
2 parents daa77d1 + 540963f commit 876590b

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

bincompat-forward.whitelist.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ filter {
173173
{
174174
matchName="scala.reflect.runtime.SymbolLoaders.isInvalidClassName"
175175
problemName=MissingMethodProblem
176+
},
177+
{
178+
matchName="scala.reflect.runtime.JavaMirrors#JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$followStatic"
179+
problemName=MissingMethodProblem
176180
}
181+
177182
]
178183
}

src/reflect/scala/reflect/runtime/JavaMirrors.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
685685
module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
686686
}
687687

688-
def enter(sym: Symbol, mods: Int) =
689-
(if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
688+
def enter(sym: Symbol, mods: Int) = followStatic(clazz, module, mods).info.decls enter sym
690689

691690
def enterEmptyCtorIfNecessary(): Unit = {
692691
if (jclazz.getConstructors.isEmpty)
@@ -733,8 +732,12 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
733732
* If Java modifiers `mods` contain STATIC, return the module class
734733
* of the companion module of `clazz`, otherwise the class `clazz` itself.
735734
*/
736-
private def followStatic(clazz: Symbol, mods: Int) =
737-
if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz
735+
private def followStatic(clazz: Symbol, mods: Int): Symbol = followStatic(clazz, clazz.companionModule, mods)
736+
737+
private def followStatic(clazz: Symbol, module: Symbol, mods: Int): Symbol =
738+
// SI-8196 `orElse(clazz)` needed for implementation details of the backend, such as the static
739+
// field containing the cache for structural calls.
740+
if (jModifier.isStatic(mods)) module.moduleClass.orElse(clazz) else clazz
738741

739742
/** Methods which need to be treated with care
740743
* because they either are getSimpleName or call getSimpleName:

test/files/run/t8196.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Scope{
2+
final private val f1: Int
3+
}

test/files/run/t8196.scala

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import scala.reflect.runtime.{ universe => ru }
2+
3+
object Test extends App {
4+
5+
trait FormTrait {
6+
7+
val runtimeMirror = ru.runtimeMirror(this.getClass.getClassLoader)
8+
val instanceMirror = runtimeMirror.reflect(this)
9+
val members = instanceMirror.symbol.typeSignature.members
10+
def fields = members.filter(_.typeSignature <:< ru.typeOf[Int])
11+
}
12+
13+
val f = () => {
14+
15+
class Form1 extends FormTrait {
16+
val f1 = 5
17+
}
18+
val form1 = new Form1
19+
20+
println(form1.fields)
21+
22+
val form2 = new FormTrait {
23+
val g1 = new Form1
24+
}
25+
26+
form2.g1 // comment this line in order to make the test pass
27+
()
28+
}
29+
30+
val g = () => {
31+
// Reported as SI-8195, same root cause
32+
trait Form {
33+
34+
private val runtimeMirror = ru.runtimeMirror(this.getClass.getClassLoader)
35+
private val instanceMirror = runtimeMirror.reflect(this)
36+
private val members = instanceMirror.symbol.typeSignature.members
37+
38+
}
39+
40+
val f1 = new Form {
41+
val a = 1
42+
}
43+
44+
val f2 = new Form {
45+
val b = f1.a
46+
}
47+
}
48+
49+
f()
50+
g()
51+
}

0 commit comments

Comments
 (0)