Support bound function reference inlining
This commit is contained in:
+3
-1
@@ -185,8 +185,10 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
if (receiverValue != null) return receiverValue;
|
if (receiverValue != null) return receiverValue;
|
||||||
|
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
|
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
||||||
|
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
||||||
return StackValue.field(
|
return StackValue.field(
|
||||||
receiverType, Type.getObjectType(codegen.getParentCodegen().getClassName()), AsmUtil.CAPTURED_RECEIVER_FIELD,
|
receiverType, asmType, AsmUtil.CAPTURED_RECEIVER_FIELD,
|
||||||
/* isStatic = */ false, StackValue.LOCAL_0
|
/* isStatic = */ false, StackValue.LOCAL_0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
private final String newFieldName;
|
private final String newFieldName;
|
||||||
private final boolean skipInConstructor;
|
private final boolean skipInConstructor;
|
||||||
|
|
||||||
|
//Now used only for bound function reference receiver
|
||||||
|
private boolean synthetic;
|
||||||
|
|
||||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, int remapIndex) {
|
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, int remapIndex) {
|
||||||
super(desc.getType(), skipped, index, remapIndex, -1);
|
super(desc.getType(), skipped, index, remapIndex, -1);
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
@@ -63,6 +66,7 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex
|
desc, newFieldName, isSkipped, getIndex(), getRemapValue(), skipInConstructor, newDeclarationIndex
|
||||||
);
|
);
|
||||||
result.setLambda(getLambda());
|
result.setLambda(getLambda());
|
||||||
|
result.setSynthetic(synthetic);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,4 +78,16 @@ public class CapturedParamInfo extends ParameterInfo {
|
|||||||
public boolean isSkipInConstructor() {
|
public boolean isSkipInConstructor() {
|
||||||
return skipInConstructor;
|
return skipInConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSynthetic() {
|
||||||
|
return synthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSynthetic(boolean synthetic) {
|
||||||
|
this.synthetic = synthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSynthetic(@NotNull ParameterInfo info) {
|
||||||
|
return info instanceof CapturedParamInfo && ((CapturedParamInfo) info).isSynthetic();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -544,17 +544,17 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
if (expression instanceof KtCallableReferenceExpression) {
|
if (expression instanceof KtCallableReferenceExpression) {
|
||||||
KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
|
KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
|
||||||
KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
|
KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
|
||||||
StackValue receiverValue =
|
Type receiverValue =
|
||||||
receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
|
receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
|
||||||
? codegen.gen(receiverExpression)
|
? codegen.getState().getTypeMapper().mapType(codegen.getBindingContext().getType(receiverExpression))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
strategy = new FunctionReferenceGenerationStrategy(
|
strategy = new FunctionReferenceGenerationStrategy(
|
||||||
state,
|
state,
|
||||||
descriptor,
|
descriptor,
|
||||||
CallUtilKt.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
CallUtilKt.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
||||||
receiverValue != null ? receiverValue.type : null,
|
receiverValue,
|
||||||
receiverValue
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -640,16 +640,16 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
if (!asFunctionInline && Type.VOID_TYPE != type) {
|
||||||
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
//TODO remap only inlinable closure => otherwise we could get a lot of problem
|
||||||
boolean couldBeRemapped = !shouldPutValue(type, stackValue);
|
boolean couldBeRemapped = !shouldPutValue(type, stackValue);
|
||||||
StackValue remappedIndex = couldBeRemapped ? stackValue : null;
|
StackValue remappedValue = couldBeRemapped ? stackValue : null;
|
||||||
|
|
||||||
ParameterInfo info;
|
ParameterInfo info;
|
||||||
if (capturedParamIndex >= 0) {
|
if (capturedParamIndex >= 0) {
|
||||||
CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex);
|
CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex);
|
||||||
info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName(), false);
|
info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName(), false);
|
||||||
info.setRemapValue(remappedIndex);
|
info.setRemapValue(remappedValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
info = invocationParamBuilder.addNextValueParameter(type, false, remappedIndex, parameterIndex);
|
info = invocationParamBuilder.addNextValueParameter(type, false, remappedValue, parameterIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
recordParameterValueInLocalVal(info);
|
recordParameterValueInLocalVal(info);
|
||||||
@@ -707,7 +707,12 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
ParameterInfo info = infos[i];
|
ParameterInfo info = infos[i];
|
||||||
if (!info.isSkippedOrRemapped()) {
|
if (!info.isSkippedOrRemapped()) {
|
||||||
Type type = info.type;
|
Type type = info.type;
|
||||||
StackValue.local(index[i], type).store(StackValue.onStack(type), codegen.v);
|
StackValue.Local local = StackValue.local(index[i], type);
|
||||||
|
local.store(StackValue.onStack(type), codegen.v);
|
||||||
|
if (info instanceof CapturedParamInfo) {
|
||||||
|
info.setRemapValue(local);
|
||||||
|
((CapturedParamInfo) info).setSynthetic(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -734,7 +739,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
|
List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
|
||||||
for (ListIterator<? extends ParameterInfo> iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) {
|
for (ListIterator<? extends ParameterInfo> iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) {
|
||||||
ParameterInfo param = iterator.previous();
|
ParameterInfo param = iterator.previous();
|
||||||
if (!param.isSkippedOrRemapped()) {
|
if (!param.isSkippedOrRemapped() || CapturedParamInfo.isSynthetic(param)) {
|
||||||
codegen.getFrameMap().leaveTemp(param.type);
|
codegen.getFrameMap().leaveTemp(param.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,13 +754,6 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
// TODO: support inline of property references passed to inlinable function parameters
|
// TODO: support inline of property references passed to inlinable function parameters
|
||||||
SimpleFunctionDescriptor functionReference = state.getBindingContext().get(BindingContext.FUNCTION, deparenthesized);
|
SimpleFunctionDescriptor functionReference = state.getBindingContext().get(BindingContext.FUNCTION, deparenthesized);
|
||||||
if (functionReference == null) return false;
|
if (functionReference == null) return false;
|
||||||
|
|
||||||
KtExpression receiverExpression = ((KtCallableReferenceExpression) deparenthesized).getReceiverExpression();
|
|
||||||
if (receiverExpression != null) {
|
|
||||||
// TODO (!): support inline for bound function references
|
|
||||||
DoubleColonLHS lhs = state.getBindingContext().get(BindingContext.DOUBLE_COLON_LHS, receiverExpression);
|
|
||||||
if (lhs instanceof DoubleColonLHS.Expression) return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
||||||
@@ -768,7 +766,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
deparenthesized instanceof KtCallableReferenceExpression;
|
deparenthesized instanceof KtCallableReferenceExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rememberClosure(@NotNull KtExpression expression, @NotNull Type type, @NotNull ValueParameterDescriptor parameter) {
|
private LambdaInfo rememberClosure(@NotNull KtExpression expression, @NotNull Type type, @NotNull ValueParameterDescriptor parameter) {
|
||||||
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
||||||
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
||||||
|
|
||||||
@@ -777,6 +775,8 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
||||||
closureInfo.setLambda(info);
|
closureInfo.setLambda(info);
|
||||||
expressionMap.put(closureInfo.getIndex(), info);
|
expressionMap.put(closureInfo.getIndex(), info);
|
||||||
|
info.setBoundCallableReference(getBoundCallableReferenceReceiver(expression) != null);
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -801,9 +801,15 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
private void putClosureParametersOnStack() {
|
private void putClosureParametersOnStack() {
|
||||||
for (LambdaInfo next : expressionMap.values()) {
|
for (LambdaInfo next : expressionMap.values()) {
|
||||||
activeLambda = next;
|
//closure parameters for bounded callable references are generated inplace
|
||||||
codegen.pushClosureOnStack(next.getClassDescriptor(), true, this, /* functionReferenceReceiver = */ null);
|
if (next.isBoundCallableReference()) continue;
|
||||||
|
putClosureParametersOnStack(next, null);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putClosureParametersOnStack(@NotNull LambdaInfo next, @Nullable StackValue functionReferenceReceiver) {
|
||||||
|
activeLambda = next;
|
||||||
|
codegen.pushClosureOnStack(next.getClassDescriptor(), true, this, functionReferenceReceiver);
|
||||||
activeLambda = null;
|
activeLambda = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,7 +852,12 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
int parameterIndex
|
int parameterIndex
|
||||||
) {
|
) {
|
||||||
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
|
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
|
||||||
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor);
|
LambdaInfo lambdaInfo = rememberClosure(argumentExpression, parameterType, valueParameterDescriptor);
|
||||||
|
|
||||||
|
KtExpression receiver = getBoundCallableReferenceReceiver(argumentExpression);
|
||||||
|
if (receiver != null) {
|
||||||
|
putClosureParametersOnStack(lambdaInfo, codegen.gen(receiver));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StackValue value = codegen.gen(argumentExpression);
|
StackValue value = codegen.gen(argumentExpression);
|
||||||
@@ -854,6 +865,20 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KtExpression getBoundCallableReferenceReceiver(
|
||||||
|
@NotNull KtExpression argumentExpression
|
||||||
|
) {
|
||||||
|
KtExpression deparenthesized = KtPsiUtil.deparenthesize(argumentExpression);
|
||||||
|
if (deparenthesized instanceof KtCallableReferenceExpression) {
|
||||||
|
KtExpression receiverExpression = ((KtCallableReferenceExpression) deparenthesized).getReceiverExpression();
|
||||||
|
if (receiverExpression != null) {
|
||||||
|
DoubleColonLHS lhs = state.getBindingContext().get(BindingContext.DOUBLE_COLON_LHS, receiverExpression);
|
||||||
|
if (lhs instanceof DoubleColonLHS.Expression) return receiverExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) {
|
public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) {
|
||||||
putValueIfNeeded(parameterType, value, -1);
|
putValueIfNeeded(parameterType, value, -1);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class LambdaInfo implements LabelOwner {
|
|||||||
|
|
||||||
private SMAPAndMethodNode node;
|
private SMAPAndMethodNode node;
|
||||||
private List<CapturedParamDesc> capturedVars;
|
private List<CapturedParamDesc> capturedVars;
|
||||||
|
private boolean isBoundCallableReference;
|
||||||
|
|
||||||
public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline) {
|
public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline) {
|
||||||
this.isCrossInline = isCrossInline;
|
this.isCrossInline = isCrossInline;
|
||||||
@@ -165,4 +166,12 @@ public class LambdaInfo implements LabelOwner {
|
|||||||
public boolean isMyLabel(@NotNull String name) {
|
public boolean isMyLabel(@NotNull String name) {
|
||||||
return labels.contains(name);
|
return labels.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBoundCallableReference() {
|
||||||
|
return isBoundCallableReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoundCallableReference(boolean boundCallableReference) {
|
||||||
|
isBoundCallableReference = boundCallableReference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public class LocalVarRemapper {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
remapValues[shift] = info.isRemapped() ? info.getRemapValue() : null;
|
remapValues[shift] = info.isRemapped() ? info.getRemapValue() : null;
|
||||||
|
if (CapturedParamInfo.isSynthetic(info)) {
|
||||||
|
realSize += info.getType().getSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun test(a: String, b: String, c: () -> String): String {
|
||||||
|
return a + b + c();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
var res = ""
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
val receiver: String
|
||||||
|
get() {
|
||||||
|
res += "L"
|
||||||
|
return "L"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
res = ""
|
||||||
|
var call = test(b = { res += "K"; "K" }(), a = { res += "O"; "O" }(), c = receiver::id)
|
||||||
|
if (res != "KOL" || call != "OKL") return "fail 1: $res != KOL or $call != OKL"
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
call = test(b = { res += "K"; "K" }(), c = receiver::id, a = { res += "O"; "O" }())
|
||||||
|
if (res != "KLO" || call != "OKL") return "fail 2: $res != KLO or $call != OKL"
|
||||||
|
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
call = test(c = receiver::id, b = { res += "K"; "K" }(), a = { res += "O"; "O" }())
|
||||||
|
if (res != "LKO" || call != "OKL") return "fail 3: $res != LKO or $call != OKL"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun test(a: String, b: Long, c: () -> String): String {
|
||||||
|
return a + b + c();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
var res = ""
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
val receiver: String
|
||||||
|
get() {
|
||||||
|
res += "L"
|
||||||
|
return "L"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
res = ""
|
||||||
|
var call = test(b = { res += "K"; 1L }(), a = { res += "O"; "O" }(), c = receiver::id)
|
||||||
|
if (res != "KOL" || call != "O1L") return "fail 1: $res != KOL or $call != O1L"
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
call = test(b = { res += "K"; 1L }(), c = receiver::id, a = { res += "O"; "O" }())
|
||||||
|
if (res != "KLO" || call != "O1L") return "fail 2: $res != KLO or $call != O1L"
|
||||||
|
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
call = test(c = receiver::id, b = { res += "K"; 1L }(), a = { res += "O"; "O" }())
|
||||||
|
if (res != "LKO" || call != "O1L") return "fail 3: $res != LKO or $call != O1L"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun go(f: () -> String) = f()
|
||||||
|
|
||||||
|
fun String.id(): String = this
|
||||||
|
|
||||||
|
fun foo(x: String, y: String): String {
|
||||||
|
return go((x + y)::id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box() = foo("O", "K")
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun foo(x: () -> String, z: String) = x() + z
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun String.test() : String {
|
||||||
|
return foo(this::id, "K")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
return "O".test()
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun stub(f: () -> String): String = f()
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
class A(val z: String) {
|
||||||
|
fun filter(s: String) = z == s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A("OK")
|
||||||
|
val s = arrayOf("OK")
|
||||||
|
return s.filter(a::filter).first()
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun foo(x: (String) -> String, z: String) = x(z)
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
var zeroSlot = "fail";
|
||||||
|
val z = "O"
|
||||||
|
return foo(z::plus, "K")
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun stub(f: () -> String): String = f()
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
class A(val z: String) {
|
||||||
|
fun map(s: String) = z + s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A("O")
|
||||||
|
val s = arrayOf("K")
|
||||||
|
return s.map(a::map).first()
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun foo(x: () -> String, z: String) = x() + z
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
var zeroSlot = "fail";
|
||||||
|
val z = "O"
|
||||||
|
return foo(z::id, "K")
|
||||||
|
}
|
||||||
@@ -406,6 +406,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundFunctionReference.kt")
|
||||||
|
public void testBoundFunctionReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/boundFunctionReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundFunctionReference2.kt")
|
||||||
|
public void testBoundFunctionReference2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/boundFunctionReference2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("captured.kt")
|
@TestMetadata("captured.kt")
|
||||||
public void testCaptured() throws Exception {
|
public void testCaptured() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/captured.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/captured.kt");
|
||||||
@@ -564,6 +576,51 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Bound extends AbstractBlackBoxInlineCodegenTest {
|
||||||
|
public void testAllFilesPresentInBound() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expression.kt")
|
||||||
|
public void testExpression() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionReceiver.kt")
|
||||||
|
public void testExtensionReceiver() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/extensionReceiver.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filter.kt")
|
||||||
|
public void testFilter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/filter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("intrinsic.kt")
|
||||||
|
public void testIntrinsic() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("map.kt")
|
||||||
|
public void testMap() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/capture")
|
@TestMetadata("compiler/testData/codegen/boxInline/capture")
|
||||||
|
|||||||
+57
@@ -406,6 +406,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/argumentOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundFunctionReference.kt")
|
||||||
|
public void testBoundFunctionReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/boundFunctionReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundFunctionReference2.kt")
|
||||||
|
public void testBoundFunctionReference2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/boundFunctionReference2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("captured.kt")
|
@TestMetadata("captured.kt")
|
||||||
public void testCaptured() throws Exception {
|
public void testCaptured() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/captured.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/argumentOrder/captured.kt");
|
||||||
@@ -564,6 +576,51 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Bound extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||||
|
public void testAllFilesPresentInBound() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expression.kt")
|
||||||
|
public void testExpression() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionReceiver.kt")
|
||||||
|
public void testExtensionReceiver() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/extensionReceiver.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filter.kt")
|
||||||
|
public void testFilter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/filter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("intrinsic.kt")
|
||||||
|
public void testIntrinsic() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/intrinsic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("map.kt")
|
||||||
|
public void testMap() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/map.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/capture")
|
@TestMetadata("compiler/testData/codegen/boxInline/capture")
|
||||||
|
|||||||
Reference in New Issue
Block a user