Skip to content

Commit 681f207

Browse files
committed
Merge pull request scala#2578 from retronym/ticket/6138
SI-6138 Centralize and refine detection of `getClass` calls
2 parents 9eb63c5 + b941551 commit 681f207

File tree

7 files changed

+39
-9
lines changed

7 files changed

+39
-9
lines changed

bincompat-backward.whitelist.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ filter {
219219
{
220220
matchName="scala.concurrent.forkjoin.ForkJoinPool.helpJoinOnce"
221221
problemName=IncompatibleResultTypeProblem
222+
},
223+
{
224+
matchName="scala.reflect.internal.Definitions#DefinitionsClass.getClassMethods"
225+
problemName=MissingMethodProblem
226+
},
227+
{
228+
matchName="scala.reflect.internal.Definitions#DefinitionsClass.primitiveGetClassMethods"
229+
problemName=MissingMethodProblem
222230
}
223231
]
224232
}

bincompat-forward.whitelist.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,14 @@ filter {
471471
{
472472
matchName="scala.concurrent.impl.Promise$CompletionLatch"
473473
problemName=MissingClassProblem
474+
},
475+
{
476+
matchName="scala.reflect.internal.Definitions#DefinitionsClass.getClassMethods"
477+
problemName=MissingMethodProblem
478+
},
479+
{
480+
matchName="scala.reflect.internal.Definitions#DefinitionsClass.primitiveGetClassMethods"
481+
problemName=MissingMethodProblem
474482
}
475483
]
476484
}

src/compiler/scala/tools/nsc/transform/Erasure.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,6 @@ abstract class Erasure extends AddInterfaces
341341
}
342342
}
343343

344-
// Each primitive value class has its own getClass for ultra-precise class object typing.
345-
private lazy val primitiveGetClassMethods = Set[Symbol](Any_getClass, AnyVal_getClass) ++ (
346-
ScalaValueClasses map (_.tpe member nme.getClass_)
347-
)
348-
349344
// ## requires a little translation
350345
private lazy val poundPoundMethods = Set[Symbol](Any_##, Object_##)
351346

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,7 @@ trait Typers extends Modes with Adaptations with Tags {
656656
// To fully benefit from special casing the return type of
657657
// getClass, we have to catch it immediately so expressions
658658
// like x.getClass().newInstance() are typed with the type of x.
659-
else if ( tree.symbol.name == nme.getClass_
660-
&& tree.tpe.params.isEmpty
659+
else if ( isGetClass(tree.symbol)
661660
// TODO: If the type of the qualifier is inaccessible, we can cause private types
662661
// to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this
663662
// so for now it requires the type symbol be public.

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,10 @@ trait Definitions extends api.StandardDefinitions {
110110
/** Is symbol a numeric value class? */
111111
def isNumericValueClass(sym: Symbol) = ScalaNumericValueClasses contains sym
112112

113-
def isGetClass(sym: Symbol) =
114-
(sym.name == nme.getClass_) && flattensToEmpty(sym.paramss)
113+
def isGetClass(sym: Symbol) = (
114+
sym.name == nme.getClass_ // this condition is for performance only, this is called from `Typer#stabliize`.
115+
&& getClassMethods(sym)
116+
)
115117

116118
lazy val UnitClass = valueClassSymbol(tpnme.Unit)
117119
lazy val ByteClass = valueClassSymbol(tpnme.Byte)
@@ -805,6 +807,12 @@ trait Definitions extends api.StandardDefinitions {
805807
lazy val Any_isInstanceOf = newT1NullaryMethod(AnyClass, nme.isInstanceOf_, FINAL)(_ => booltype)
806808
lazy val Any_asInstanceOf = newT1NullaryMethod(AnyClass, nme.asInstanceOf_, FINAL)(_.typeConstructor)
807809

810+
lazy val primitiveGetClassMethods = Set[Symbol](Any_getClass, AnyVal_getClass) ++ (
811+
ScalaValueClasses map (_.tpe member nme.getClass_)
812+
)
813+
814+
lazy val getClassMethods: Set[Symbol] = primitiveGetClassMethods + Object_getClass
815+
808816
// A type function from T => Class[U], used to determine the return
809817
// type of getClass calls. The returned type is:
810818
//

test/files/neg/t6138.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
t6138.scala:4: error: ambiguous reference to overloaded definition,
2+
both method getClass in object definitions of type (s: Int)Any
3+
and method getClass in object definitions of type (s: String)Any
4+
match argument types (Nothing)
5+
getClass(???): String
6+
^
7+
one error found

test/files/neg/t6138.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object definitions {
2+
def getClass(s: String): Any = ???
3+
def getClass(s: Int): Any = ???
4+
getClass(???): String
5+
}

0 commit comments

Comments
 (0)