Fix for-in iterator over list of boxed inline class values

#KT-25325 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-07-11 02:47:05 +03:00
parent 0308e10c11
commit 4e3674b330
9 changed files with 92 additions and 6 deletions
@@ -44,6 +44,7 @@ abstract class AbstractForLoopGenerator(
protected var loopParameterVar: Int = -1 protected var loopParameterVar: Int = -1
protected lateinit var loopParameterType: Type protected lateinit var loopParameterType: Type
protected lateinit var loopParameterKotlinType: KotlinType
override fun beforeLoop() { override fun beforeLoop() {
val loopParameter = forExpression.loopParameter ?: return val loopParameter = forExpression.loopParameter ?: return
@@ -51,11 +52,13 @@ abstract class AbstractForLoopGenerator(
if (multiParameter != null) { if (multiParameter != null) {
// E tmp<e> = tmp<iterator>.next() // E tmp<e> = tmp<iterator>.next()
loopParameterType = asmElementType loopParameterType = asmElementType
loopParameterKotlinType = elementType
loopParameterVar = createLoopTempVariable(asmElementType) loopParameterVar = createLoopTempVariable(asmElementType)
} else { } else {
// E e = tmp<iterator>.next() // E e = tmp<iterator>.next()
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter) val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter)
loopParameterType = codegen.asmType(parameterDescriptor!!.type) loopParameterKotlinType = parameterDescriptor!!.type
loopParameterType = codegen.asmType(loopParameterKotlinType)
loopParameterVar = codegen.myFrameMap.enter(parameterDescriptor, loopParameterType) loopParameterVar = codegen.myFrameMap.enter(parameterDescriptor, loopParameterType)
scheduleLeaveVariable(Runnable { scheduleLeaveVariable(Runnable {
codegen.myFrameMap.leave(parameterDescriptor) codegen.myFrameMap.leave(parameterDescriptor)
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull import org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
@@ -33,6 +34,7 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
private var iteratorVarIndex: Int = 0 private var iteratorVarIndex: Int = 0
private val iteratorCall: ResolvedCall<FunctionDescriptor> private val iteratorCall: ResolvedCall<FunctionDescriptor>
private val nextCall: ResolvedCall<FunctionDescriptor> private val nextCall: ResolvedCall<FunctionDescriptor>
private val iteratorType: KotlinType
private val asmTypeForIterator: Type private val asmTypeForIterator: Type
init { init {
@@ -43,7 +45,7 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
"No .iterator() function " + PsiDiagnosticUtils.atLocation(loopRange) "No .iterator() function " + PsiDiagnosticUtils.atLocation(loopRange)
) )
val iteratorType = iteratorCall.resultingDescriptor.returnType!! this.iteratorType = iteratorCall.resultingDescriptor.returnType!!
this.asmTypeForIterator = codegen.asmType(iteratorType) this.asmTypeForIterator = codegen.asmType(iteratorType)
this.nextCall = getNotNull( this.nextCall = getNotNull(
@@ -58,7 +60,9 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
// Iterator<E> tmp<iterator> = c.iterator() // Iterator<E> tmp<iterator> = c.iterator()
iteratorVarIndex = createLoopTempVariable(asmTypeForIterator) iteratorVarIndex = createLoopTempVariable(asmTypeForIterator)
StackValue.local(iteratorVarIndex, asmTypeForIterator).store(codegen.invokeFunction(iteratorCall, StackValue.none()), v) StackValue
.local(iteratorVarIndex, asmTypeForIterator, iteratorType)
.store(codegen.invokeFunction(iteratorCall, StackValue.none()), v)
} }
override fun checkEmptyLoop(loopExit: Label) {} override fun checkEmptyLoop(loopExit: Label) {}
@@ -73,7 +77,7 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
"No hasNext() function " + PsiDiagnosticUtils.atLocation(loopRange) "No hasNext() function " + PsiDiagnosticUtils.atLocation(loopRange)
) )
val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!)) val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!))
val result = codegen.invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)) val result = codegen.invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator, iteratorType))
result.put(Type.BOOLEAN_TYPE, v) result.put(Type.BOOLEAN_TYPE, v)
v.ifeq(loopExit) v.ifeq(loopExit)
@@ -81,9 +85,9 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
override fun assignToLoopParameter() { override fun assignToLoopParameter() {
val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!)) val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!))
val value = codegen.invokeFunction(fakeCall, nextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)) val value = codegen.invokeFunction(fakeCall, nextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator, iteratorType))
StackValue.local(loopParameterVar, loopParameterType).store(value, v) StackValue.local(loopParameterVar, loopParameterType, loopParameterKotlinType).store(value, v)
} }
override fun checkPostConditionAndIncrement(loopExit: Label) {} override fun checkPostConditionAndIncrement(loopExit: Label) {}
@@ -0,0 +1,16 @@
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
inline class Foo(val arg: String)
fun box(): String {
val ls = listOf(Foo("abc"), Foo("def"))
var res = ""
for (el in ls) {
res += el.arg
}
return if (res != "abcdef") "Fail" else "OK"
}
@@ -0,0 +1,13 @@
// WITH_UNSIGNED
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
fun box(): String {
var sum = 0u
val ls = listOf(1u, 2u, 3u)
for (el in ls) {
sum += el
}
return if (sum != 6u) "Fail" else "OK"
}
@@ -11131,6 +11131,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt"); runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt");
} }
@TestMetadata("iterateOverListOfInlineClassValues.kt")
public void testIterateOverListOfInlineClassValues() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt") @TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception { public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt"); runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -21252,6 +21257,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt");
} }
@TestMetadata("iterateOverListOfBoxedUnsignedValues.kt")
public void testIterateOverListOfBoxedUnsignedValues() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt") @TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
public void testUnsignedLiteralsWithSignedOverflow() throws Exception { public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
@@ -11131,6 +11131,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt"); runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt");
} }
@TestMetadata("iterateOverListOfInlineClassValues.kt")
public void testIterateOverListOfInlineClassValues() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt") @TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception { public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt"); runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -21252,6 +21257,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt");
} }
@TestMetadata("iterateOverListOfBoxedUnsignedValues.kt")
public void testIterateOverListOfBoxedUnsignedValues() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt") @TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
public void testUnsignedLiteralsWithSignedOverflow() throws Exception { public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
@@ -11131,6 +11131,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt"); runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt");
} }
@TestMetadata("iterateOverListOfInlineClassValues.kt")
public void testIterateOverListOfInlineClassValues() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt") @TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception { public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt"); runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -21252,6 +21257,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt");
} }
@TestMetadata("iterateOverListOfBoxedUnsignedValues.kt")
public void testIterateOverListOfBoxedUnsignedValues() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt") @TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
public void testUnsignedLiteralsWithSignedOverflow() throws Exception { public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
@@ -9781,6 +9781,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt"); runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt");
} }
@TestMetadata("iterateOverListOfInlineClassValues.kt")
public void testIterateOverListOfInlineClassValues() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt") @TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception { public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt"); runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -19262,6 +19267,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt");
} }
@TestMetadata("iterateOverListOfBoxedUnsignedValues.kt")
public void testIterateOverListOfBoxedUnsignedValues() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("varargsOfUnsignedTypes.kt") @TestMetadata("varargsOfUnsignedTypes.kt")
public void testVarargsOfUnsignedTypes() throws Exception { public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
@@ -10776,6 +10776,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt"); runTest("compiler/testData/codegen/box/inlineClasses/iterateOverArrayOfInlineClassValues.kt");
} }
@TestMetadata("iterateOverListOfInlineClassValues.kt")
public void testIterateOverListOfInlineClassValues() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt") @TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception { public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt"); runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -20257,6 +20262,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverArrayOfUnsignedValues.kt");
} }
@TestMetadata("iterateOverListOfBoxedUnsignedValues.kt")
public void testIterateOverListOfBoxedUnsignedValues() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("varargsOfUnsignedTypes.kt") @TestMetadata("varargsOfUnsignedTypes.kt")
public void testVarargsOfUnsignedTypes() throws Exception { public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");