[JVM] Introduce StringRef type for captured string variables

Previously captured string variables were represented as
`ObjectRef<String>`. After the 'captured vars optimization', these
variables were assigned the type `Object`, which could lead to confusion
when debugging an application as the effective type of such variable is
`String`. This commit adds a new `Ref` type for captured
strings - `StringRef`. This makes it possible to put these variables as
`String`s in LVT after the 'captured vars optimization'.

^KT-70527 fixed
diff --git a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java
index b88b646..4c6cbf5 100644
--- a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java
+++ b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java
@@ -70,6 +70,7 @@
 
     private static final String REF_TYPE_PREFIX = "kotlin/jvm/internal/Ref$";
     public static final Type OBJECT_REF_TYPE = Type.getObjectType(REF_TYPE_PREFIX + "ObjectRef");
+    public static final Type STRING_REF_TYPE = Type.getObjectType(REF_TYPE_PREFIX + "StringRef");
 
     public static final Type ENUM_ENTRIES = Type.getObjectType("kotlin/enums/EnumEntries");
 
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/CapturedVarsOptimizationMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/CapturedVarsOptimizationMethodTransformer.kt
index 773204d..d91fd4a 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/CapturedVarsOptimizationMethodTransformer.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/CapturedVarsOptimizationMethodTransformer.kt
@@ -227,6 +227,7 @@
 
 internal val REF_TYPE_TO_ELEMENT_TYPE = HashMap<String, Type>().apply {
     put(AsmTypes.OBJECT_REF_TYPE.internalName, AsmTypes.OBJECT_TYPE)
+    put(AsmTypes.STRING_REF_TYPE.internalName, AsmTypes.JAVA_STRING_TYPE)
     PrimitiveType.entries.forEach {
         put(AsmTypes.sharedTypeForPrimitive(it).internalName, AsmTypes.valueTypeForPrimitive(it))
     }
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt
index 3768c8b..18a3e77 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt
@@ -45,7 +45,7 @@
  *
  * becomes
  *
- *     var x = ObjectRef<String>()
+ *     var x = StringRef()
  *     x.element = "a"
  *     run {
  *         x.element = "b"
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt
index 56cbfcd..73c35cb 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt
@@ -61,7 +61,17 @@
         primitiveType.classifierOrFail to RefProvider(refClass, primitiveType)
     }
 
-    private val objectRefProvider = run {
+    private val stringRefProvider = run {
+        val refClass = irFactory.addClass(refNamespaceClass) {
+            origin = IrDeclarationOrigin.IR_BUILTINS_STUB
+            name = Name.identifier("StringRef")
+        }.apply {
+            createThisReceiverParameter()
+        }
+        RefProvider(refClass, irBuiltIns.stringType)
+    }
+
+    val objectRefProvider = run {
         val refClass = irFactory.addClass(refNamespaceClass) {
             origin = IrDeclarationOrigin.IR_BUILTINS_STUB
             name = Name.identifier("ObjectRef")
@@ -76,10 +86,11 @@
     }
 
     fun getProvider(valueType: IrType): RefProvider =
-        if (valueType.isPrimitiveType())
-            primitiveRefProviders.getValue(valueType.classifierOrFail)
-        else
-            objectRefProvider
+        when {
+            valueType.isPrimitiveType() -> primitiveRefProviders.getValue(valueType.classifierOrFail)
+            valueType.isString() -> stringRefProvider
+            else -> objectRefProvider
+        }
 
     override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable {
         val valueType = originalDeclaration.type
diff --git a/compiler/testData/codegen/box/coroutines/bridges/lambdaWithLongReceiver.ir.txt b/compiler/testData/codegen/box/coroutines/bridges/lambdaWithLongReceiver.ir.txt
index 58fd007..452bde5 100644
--- a/compiler/testData/codegen/box/coroutines/bridges/lambdaWithLongReceiver.ir.txt
+++ b/compiler/testData/codegen/box/coroutines/bridges/lambdaWithLongReceiver.ir.txt
@@ -19,17 +19,17 @@
 final class LambdaWithLongReceiverKt$box$1 {
     // source: 'lambdaWithLongReceiver.kt'
     enclosing method LambdaWithLongReceiverKt.box()Ljava/lang/String;
-    synthetic final field $res: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $res: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field label: int
     inner (anonymous) class LambdaWithLongReceiverKt$box$1
     inner (anonymous) class LambdaWithLongReceiverKt$box$1$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -39,5 +39,5 @@
     public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
     public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
     public final static @org.jetbrains.annotations.Nullable method call(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
diff --git a/compiler/testData/codegen/box/coroutines/bridges/lambdaWithMultipleParameters.ir.txt b/compiler/testData/codegen/box/coroutines/bridges/lambdaWithMultipleParameters.ir.txt
index 8e0c96a..770da94 100644
--- a/compiler/testData/codegen/box/coroutines/bridges/lambdaWithMultipleParameters.ir.txt
+++ b/compiler/testData/codegen/box/coroutines/bridges/lambdaWithMultipleParameters.ir.txt
@@ -23,17 +23,17 @@
 final class LambdaWithMultipleParametersKt$box$1 {
     // source: 'lambdaWithMultipleParameters.kt'
     enclosing method LambdaWithMultipleParametersKt.box()Ljava/lang/String;
-    synthetic final field $res: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $res: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field label: int
     inner (anonymous) class LambdaWithMultipleParametersKt$box$1
     inner (anonymous) class LambdaWithMultipleParametersKt$box$1$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -43,5 +43,5 @@
     public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
     public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
     public final static @org.jetbrains.annotations.Nullable method call(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function7, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.fir.txt b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.fir.txt
index ed47ac6..8f32698 100644
--- a/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.fir.txt
+++ b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.fir.txt
@@ -4,15 +4,15 @@
     // source: 'onInlineArgument.kt'
     enclosing method OnInlineArgumentKt.box()Ljava/lang/String;
     synthetic final field $lambda: kotlin.jvm.functions.Function1
-    synthetic final field $test: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $test: kotlin.jvm.internal.Ref$StringRef
     field label: int
     inner (anonymous) class OnInlineArgumentKt$box$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function1, p2: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: kotlin.jvm.functions.Function1, p2: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -23,5 +23,5 @@
     public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
     private final static method runS$$forInline(p0: kotlin.jvm.functions.Function2, p1: kotlin.coroutines.Continuation): java.lang.Object
     public final static @org.jetbrains.annotations.Nullable method runS(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.ir.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.ir.txt
index 6d91d55..b2f8feb 100644
--- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.ir.txt
+++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithoutStateMachine.ir.txt
@@ -3,17 +3,17 @@
 final class InlineWithoutStateMachineKt$box$1 {
     // source: 'inlineWithoutStateMachine.kt'
     enclosing method InlineWithoutStateMachineKt.box()Ljava/lang/String;
-    synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $result: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field L$1: java.lang.Object
     field label: int
     inner (anonymous) class InlineWithoutStateMachineKt$box$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -26,5 +26,5 @@
     public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
     private final static method suspendThere$$forInline(p0: java.lang.String, p1: kotlin.coroutines.Continuation): java.lang.Object
     public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
diff --git a/compiler/testData/codegen/box/jvm8/defaults/enable/privateFunWithDefaultArg.ir.txt b/compiler/testData/codegen/box/jvm8/defaults/enable/privateFunWithDefaultArg.ir.txt
index 0a3dc43..22b1a1b 100644
--- a/compiler/testData/codegen/box/jvm8/defaults/enable/privateFunWithDefaultArg.ir.txt
+++ b/compiler/testData/codegen/box/jvm8/defaults/enable/privateFunWithDefaultArg.ir.txt
@@ -10,17 +10,17 @@
 final class Foo$bar$1 {
     // source: 'privateFunWithDefaultArg.kt'
     enclosing method Foo.bar()Ljava/lang/String;
-    synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $result: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field label: int
     synthetic final field this$0: Foo
     inner (anonymous) class Foo$bar$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: Foo, p2: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: Foo, p2: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -35,7 +35,7 @@
     public synthetic static method fooSuspend$default(p0: Foo, p1: java.lang.String, p2: kotlin.coroutines.Continuation, p3: int, p4: java.lang.Object): java.lang.Object
     private method fooSuspend(p0: java.lang.String, p1: kotlin.coroutines.Continuation): java.lang.Object
     public final inner class Foo$DefaultImpls
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
diff --git a/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/privateFunWithDefaultArg.ir.txt b/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/privateFunWithDefaultArg.ir.txt
index e883fca..c23f889 100644
--- a/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/privateFunWithDefaultArg.ir.txt
+++ b/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/privateFunWithDefaultArg.ir.txt
@@ -3,17 +3,17 @@
 final class Foo$bar$1 {
     // source: 'privateFunWithDefaultArg.kt'
     enclosing method Foo.bar()Ljava/lang/String;
-    synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $result: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field label: int
     synthetic final field this$0: Foo
     inner (anonymous) class Foo$bar$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: Foo, p2: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: Foo, p2: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -26,7 +26,7 @@
     private method foo(p0: java.lang.String): java.lang.String
     public synthetic static method fooSuspend$default(p0: Foo, p1: java.lang.String, p2: kotlin.coroutines.Continuation, p3: int, p4: java.lang.Object): java.lang.Object
     private method fooSuspend(p0: java.lang.String, p1: kotlin.coroutines.Continuation): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
diff --git a/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/withCompatibility/suspend.txt b/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/withCompatibility/suspend.txt
index 29091a9..41fcd35 100644
--- a/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/withCompatibility/suspend.txt
+++ b/compiler/testData/codegen/box/jvm8/defaults/noCompatibility/withCompatibility/suspend.txt
@@ -3,17 +3,17 @@
 final class SuspendKt$box$1 {
     // source: 'suspend.kt'
     enclosing method SuspendKt.box()Ljava/lang/String;
-    synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
+    synthetic final field $result: kotlin.jvm.internal.Ref$StringRef
     field L$0: java.lang.Object
     field L$1: java.lang.Object
     field label: int
     inner (anonymous) class SuspendKt$box$1
-    method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
+    method <init>(p0: kotlin.jvm.internal.Ref$StringRef, p1: kotlin.coroutines.Continuation): void
     public final method create(p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
     public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
     public final method invoke(p0: kotlin.coroutines.Continuation): java.lang.Object
     public final method invokeSuspend(p0: java.lang.Object): java.lang.Object
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
@@ -22,7 +22,7 @@
     inner (anonymous) class SuspendKt$box$1
     public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
     public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
-    public final inner class kotlin/jvm/internal/Ref$ObjectRef
+    public final inner class kotlin/jvm/internal/Ref$StringRef
 }
 
 @kotlin.Metadata
diff --git a/compiler/testData/codegen/bytecodeText/capturedVarsOptimization/capturedValInLambdaInitializedInside.kt b/compiler/testData/codegen/bytecodeText/capturedVarsOptimization/capturedValInLambdaInitializedInside.kt
index efee7b8..2e62ce8 100644
--- a/compiler/testData/codegen/bytecodeText/capturedVarsOptimization/capturedValInLambdaInitializedInside.kt
+++ b/compiler/testData/codegen/bytecodeText/capturedVarsOptimization/capturedValInLambdaInitializedInside.kt
@@ -2,12 +2,17 @@
 
 fun box(): String {
     val x: String
+    val y: Any
     run {
         x = "OK"
-        val y = x
+        y = Any()
+        val a = x
+        val b = y
     }
     return x
 }
 
 // 2 ObjectRef
 // 1 INNERCLASS kotlin.jvm.internal.Ref\$ObjectRef kotlin.jvm.internal.Ref ObjectRef
+// 1 LOCALVARIABLE x Ljava/lang/String;
+// 1 INNERCLASS kotlin.jvm.internal.Ref\$StringRef kotlin.jvm.internal.Ref StringRef
diff --git a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt
index d1783ba..8f536d4 100644
--- a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt
+++ b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt
@@ -51,7 +51,7 @@
 /* 1 load in the catch (e: Throwable) { throw e } block which is implicitly wrapped around try/finally */
 // 1 ALOAD 3\s+ATHROW
 /* 1 load in result = s */
-// 1 ALOAD 3\s+PUTFIELD kotlin/jvm/internal/Ref\$ObjectRef\.element
+// 1 ALOAD 3\s+PUTFIELD kotlin/jvm/internal/Ref\$StringRef\.element
 /* 1 load in spill */
 // 1 ALOAD 3\s+PUTFIELD VarValueConflictsWithTableSameSortKt\$box\$1\.L\$1 : Ljava/lang/Object;
 /* 2 loads in println(s) */
diff --git a/compiler/testData/codegen/bytecodeText/kt10259.kt b/compiler/testData/codegen/bytecodeText/kt10259.kt
index 6947f70..2ace841 100644
--- a/compiler/testData/codegen/bytecodeText/kt10259.kt
+++ b/compiler/testData/codegen/bytecodeText/kt10259.kt
@@ -26,4 +26,4 @@
 // 8 INNERCLASS
 // 3 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1 null null
 // 2 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1\$lam2\$1
-// 3 INNERCLASS kotlin.jvm.internal.Ref\$ObjectRef kotlin.jvm.internal.Ref ObjectRef
+// 3 INNERCLASS kotlin.jvm.internal.Ref\$StringRef kotlin.jvm.internal.Ref StringRef
diff --git a/compiler/testData/codegen/bytecodeText/kt10259_2.kt b/compiler/testData/codegen/bytecodeText/kt10259_2.kt
index 13e96b1..3a48ded 100644
--- a/compiler/testData/codegen/bytecodeText/kt10259_2.kt
+++ b/compiler/testData/codegen/bytecodeText/kt10259_2.kt
@@ -19,5 +19,5 @@
 // 2 INNERCLASS Kt10259_2Kt\$test\$1\$1
 // 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1\s
 // 2 INNERCLASS Kt10259_2Kt\$box\$\$inlined\$test\$1\$1
-// 1 INNERCLASS kotlin.jvm.internal.Ref\$ObjectRef kotlin.jvm.internal.Ref ObjectRef
+// 1 INNERCLASS kotlin.jvm.internal.Ref\$StringRef kotlin.jvm.internal.Ref StringRef
 // 10 INNERCLASS
diff --git a/compiler/testData/codegen/bytecodeText/kt10259_3.kt b/compiler/testData/codegen/bytecodeText/kt10259_3.kt
index 4bd702d..8c38293 100644
--- a/compiler/testData/codegen/bytecodeText/kt10259_3.kt
+++ b/compiler/testData/codegen/bytecodeText/kt10259_3.kt
@@ -36,4 +36,4 @@
 // 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1 null null
 // 3 INNERCLASS Kt10259_3Kt\$test\$1 null null
 // 2 INNERCLASS Kt10259_3Kt\$test\$1\$1 null null
-// 3 INNERCLASS kotlin.jvm.internal.Ref\$ObjectRef kotlin.jvm.internal.Ref ObjectRef
+// 3 INNERCLASS kotlin.jvm.internal.Ref\$StringRef kotlin.jvm.internal.Ref StringRef
diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Ref.java b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Ref.java
index 4765b02..7058c08 100644
--- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Ref.java
+++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Ref.java
@@ -19,6 +19,15 @@
         }
     }
 
+    public static final class StringRef implements Serializable {
+        public String element;
+
+        @Override
+        public String toString() {
+            return element;
+        }
+    }
+
     public static final class ByteRef implements Serializable {
         public byte element;