Mangle function names with inline class parameters

Avoid name clashes in cases such as

  inline class Login(val login: String)
  inline class Password(val password: String)

  fun validate(login: Login) { ... }
  fun validate(password: Password) { ... }
This commit is contained in:
Dmitry Petrov
2018-08-15 10:25:49 +03:00
committed by Ilya Gorbunov
parent ff9ba97d66
commit a56d1d3ce8
45 changed files with 1273 additions and 30 deletions
@@ -0,0 +1,13 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class S(val string: String)
fun foo(s: S): String {
val anon = object {
fun bar() = s.string
}
return anon.bar()
}
fun box() = foo(S("OK"))
@@ -0,0 +1,50 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Id(val id: String)
inline class Name(val name: String)
inline class Password(val password: String)
fun Id.test() {
if (id != "OK") throw AssertionError()
}
fun Name.test() {
if (name != "OK") throw AssertionError()
}
fun test(password: Password) {
if (password.password != "OK") throw AssertionError()
}
class Outer {
fun Id.testExn() {
if (id != "OK") throw AssertionError()
}
fun Name.testExn() {
if (name != "OK") throw AssertionError()
}
fun testExn(password: Password) {
if (password.password != "OK") throw AssertionError()
}
fun testExns() {
Id("OK").testExn()
Name("OK").testExn()
testExn(Password("OK"))
}
}
fun box(): String {
Id("OK").test()
Name("OK").test()
test(Password("OK"))
Outer().testExns()
return "OK"
}
@@ -0,0 +1,19 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Id(val id: String)
fun test(id: Id) {
if (id.id != "OK") throw AssertionError()
}
fun test(id: Id?) {
if (id != null) throw AssertionError()
}
fun box(): String {
test(Id("OK"))
test(null)
return "OK"
}
@@ -0,0 +1,23 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class S1(val s1: String)
inline class S2(val s2: String)
object X1
object X2
fun <T> test(s1: S1, x: T) {
if (s1.s1 != "OK" && x != X1) throw AssertionError()
}
fun <T> test(s2: S2, x: T) {
if (s2.s2 != "OK" && x != X2) throw AssertionError()
}
fun box(): String {
test(S1("OK"), X1)
test(S2("OK"), X2)
return "OK"
}
@@ -0,0 +1,13 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class S(val string: String)
fun foo(s: S): String {
class Local {
fun bar() = s.string
}
return Local().bar()
}
fun box() = foo(S("OK"))
@@ -0,0 +1,89 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Id(val id: String)
inline class Name(val name: String)
interface IA {
fun fromInterface(id: Id)
fun fromInterface(name: Name)
fun fromBoth(id: Id)
fun fromBoth(name: Name)
fun withDefaultImpl(id: Id) {
if (id.id != "OK") throw AssertionError()
}
fun withDefaultImpl(name: Name) {
if (name.name != "OK") throw AssertionError()
}
}
abstract class Base {
abstract fun fromClass(id: Id)
abstract fun fromClass(name: Name)
abstract fun fromBoth(id: Id)
abstract fun fromBoth(name: Name)
}
class C : Base(), IA {
override fun fromInterface(id: Id) {
if (id.id != "OK") throw AssertionError()
}
override fun fromInterface(name: Name) {
if (name.name != "OK") throw AssertionError()
}
override fun fromClass(id: Id) {
if (id.id != "OK") throw AssertionError()
}
override fun fromClass(name: Name) {
if (name.name != "OK") throw AssertionError()
}
override fun fromBoth(id: Id) {
if (id.id != "OK") throw AssertionError()
}
override fun fromBoth(name: Name) {
if (name.name != "OK") throw AssertionError()
}
}
fun testIA(a: IA) {
a.fromInterface(Id("OK"))
a.fromInterface(Name("OK"))
a.fromBoth(Id("OK"))
a.fromBoth(Name("OK"))
a.withDefaultImpl(Id("OK"))
a.withDefaultImpl(Name("OK"))
}
fun testBase(b: Base) {
b.fromClass(Id("OK"))
b.fromClass(Name("OK"))
b.fromBoth(Id("OK"))
b.fromBoth(Name("OK"))
}
fun testC(c: C) {
c.withDefaultImpl(Id("OK"))
c.withDefaultImpl(Name("OK"))
}
fun box(): String {
testIA(C())
testBase(C())
testC(C())
return "OK"
}
@@ -0,0 +1,28 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Id(val id: String)
inline class Name(val name: String)
inline class Password(val password: String)
fun test(id: Id) {
if (id.id != "OK") throw AssertionError()
}
fun test(name: Name) {
if (name.name != "OK") throw AssertionError()
}
fun test(password: Password) {
if (password.password != "OK") throw AssertionError()
}
fun box(): String {
test(Id("OK"))
test(Name("OK"))
test(Password("OK"))
return "OK"
}
@@ -0,0 +1,35 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR, JS, JS_IR
// FULL_JDK
// WITH_RUNTIME
inline class Id(val id: String)
fun throws() {
throw RuntimeException()
}
fun test(id: Id) {
throws()
}
fun foo() {
test(Id("id"))
}
fun box(): String {
val stackTrace = try {
foo()
throw AssertionError()
} catch (e: RuntimeException) {
e.stackTrace
}
for (entry in stackTrace) {
if (entry.methodName.startsWith("test$")) {
return "OK"
}
}
throw AssertionError()
}
@@ -0,0 +1,19 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Id(val id: String)
fun test(id: Id, str: String) {
if (id.id != "OK" && str != "1") throw AssertionError()
}
fun test(str: String, id: Id) {
if (id.id != "OK" && str != "2") throw AssertionError()
}
fun box(): String {
test(Id("OK"), "1")
test("2", Id("OK"))
return "OK"
}
@@ -0,0 +1,14 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
abstract class GenericBase<T> {
abstract fun foo(x: T): T
}
inline class Str(val str: String)
class Derived : GenericBase<Str>() {
override fun foo(x: Str): Str = x
}
fun box() = Derived().foo(Str("OK")).str
@@ -0,0 +1,24 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
abstract class GenericBase<T> {
abstract fun foo(x: T): T
}
interface IFoo {
fun foo(x: String): String
}
inline class Str(val str: String)
class Derived : GenericBase<Str>(), IFoo {
override fun foo(x: Str): Str = x
override fun foo(x: String): String = x
}
fun box(): String {
if (Derived().foo(Str("OK")).str != "OK") throw AssertionError()
if (Derived().foo("OK") != "OK") throw AssertionError()
return "OK"
}
@@ -0,0 +1,14 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Str(val string: String)
class C {
var s = Str("")
}
fun box(): String {
val x = C()
x.s = Str("OK")
return x.s.string
}
@@ -0,0 +1,17 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR, JS, JS_IR
// WITH_RUNTIME
import kotlin.test.*
inline class S(val string: String)
fun foo(s: S) = s
fun box(): String {
val fooRef = ::foo
assertEquals("abc", fooRef.invoke(S("abc")).string)
assertEquals("foo", fooRef.name)
return "OK"
}
@@ -0,0 +1,26 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR, JS, JS_IR
// WITH_REFLECT
import kotlin.test.*
import kotlin.test.*
inline class S(val string: String)
fun test(s: S) {
class Local
val localKClass = Local::class
val localJClass = localKClass.java
assertEquals("test\$Local", localKClass.simpleName)
assertTrue { localJClass.isLocalClass }
assertEquals("test\$Local", localJClass.simpleName)
}
fun box(): String {
test(S(""))
return "OK"
}
@@ -0,0 +1,21 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR, JS, JS_IR
// WITH_RUNTIME
import kotlin.test.*
inline class S(val string: String)
var prop = S("")
fun box(): String {
val propRef = ::prop
assertEquals(S(""), propRef.get())
propRef.set(S("abc"))
assertEquals(S("abc"), propRef.get())
assertEquals("prop", propRef.name)
return "OK"
}
@@ -0,0 +1,14 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class S(val string: String)
class Outer {
private fun foo(s: S) = s.string
inner class Inner(val string: String) {
fun bar() = foo(S(string))
}
}
fun box(): String = Outer().Inner("OK").bar()
@@ -0,0 +1,18 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class S(val string: String)
class Outer {
private var pr = S("")
inner class Inner() {
fun updateOuter(string: String): String {
pr = S(string)
return pr.string
}
}
}
fun box(): String =
Outer().Inner().updateOuter("OK")