Skip to content

Varargs with alternative array builders #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a782116
Add isVararg to candidate resolve
BlaBlaHuman Apr 7, 2024
fd04449
Update `irTypeUtils`
BlaBlaHuman Apr 8, 2024
46bcc52
Cast collections to the corresponding array on the front-end
BlaBlaHuman Apr 10, 2024
36b3dcb
Fix type inference
BlaBlaHuman Apr 12, 2024
cb870b5
Rename argument, fix bracket
BlaBlaHuman Apr 12, 2024
7a32a63
Revert file, fix bracket
BlaBlaHuman Apr 12, 2024
734613e
Fix argument
BlaBlaHuman Apr 14, 2024
ddffdad
Update argument type checking
BlaBlaHuman Apr 14, 2024
30478da
Rewrite type argument retrieval
BlaBlaHuman Apr 16, 2024
d3738c0
Rewrite type argument retrieval
BlaBlaHuman Apr 16, 2024
b4107c2
Check the type equality and not the primitiveness
BlaBlaHuman Apr 21, 2024
df6b7cc
Optimize code
BlaBlaHuman Apr 21, 2024
b48c76c
Fix conditions
BlaBlaHuman Apr 23, 2024
ff49010
Rewrite typechecking
BlaBlaHuman Apr 25, 2024
2b466f7
Add a roselve test for non-array spread arguments
BlaBlaHuman Apr 25, 2024
c7f57f3
Simplify the code
BlaBlaHuman Apr 30, 2024
260f14b
Reduce copying
BlaBlaHuman May 3, 2024
b947adf
Revert files
BlaBlaHuman May 8, 2024
502661c
Fix the support for Iterable collections
BlaBlaHuman May 12, 2024
82f3b24
Fix vararg argument checking for named form
BlaBlaHuman May 22, 2024
e6043d8
Add two tests
BlaBlaHuman Jun 2, 2024
14a1f20
Update spreadOperatorOnNonArrayTypes test
BlaBlaHuman Jun 18, 2024
55a1156
Fix named arguments and primitive types wrapping
BlaBlaHuman Jun 18, 2024
a00edb1
Fix bytecode generation
BlaBlaHuman Jun 18, 2024
ac0529f
Delete one invalid test
BlaBlaHuman Jun 21, 2024
8aad10f
Fix expected result for `varargWithImplicitCast`
BlaBlaHuman Jun 21, 2024
ce388d9
Somewhat fix diagnostics for non-array varargs
BlaBlaHuman Jun 21, 2024
bd77b8c
Add assigningNonArraysToVarargsInAnnotations test
BlaBlaHuman Jun 24, 2024
4412351
Remove redundant when branch
BlaBlaHuman Jun 26, 2024
9b7642c
Add support for String and CharSequence
BlaBlaHuman Jun 27, 2024
1c92af1
Add support for all iterable types
BlaBlaHuman Jun 27, 2024
21b1ac2
Add partial support for all iterables in K1 diagnostics pipelines
BlaBlaHuman Jul 2, 2024
6bc70bd
Optimize collection element type retrieval
BlaBlaHuman Jul 4, 2024
47c79f2
Add `callingJavaVarargsWithNonArrayCollections` test
BlaBlaHuman Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.boxType;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.BaseExpressionCodegenKt.putReifiedOperationMarkerIfTypeIsReifiedParameter;
Expand Down Expand Up @@ -3276,83 +3276,91 @@ public StackValue genVarargs(@NotNull VarargValueArgument valueArgument, @NotNul
: arguments.stream().anyMatch(argument -> argument.getSpreadElement() != null);

if (hasSpreadOperator) {
boolean arrayOfReferences = KotlinBuiltIns.isArray(outType);
boolean arrayOfReferences = isArray(outType);

if (size == 1) {
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
return StackValue.operation(type, outType, adapter -> {
KtExpression spreadArgument = arguments.get(0).getArgumentExpression();
gen(spreadArgument, type, outType);
if (!canSkipArrayCopyForSpreadArgument(spreadArgument)) {
v.dup();
v.arraylength();
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false);
}
if (arrayOfReferences) {
v.checkcast(type);
}
return Unit.INSTANCE;
});
KotlinType argumentType = kotlinType(arguments.get(0).getArgumentExpression());
if (isArrayOrPrimitiveArray(argumentType) && (isPrimitiveArray(argumentType) == isPrimitiveArray(outType))) {
Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType);
return StackValue.operation(type, outType, adapter -> {
KtExpression spreadArgument = arguments.get(0).getArgumentExpression();
gen(spreadArgument, type, outType);
if (!canSkipArrayCopyForSpreadArgument(spreadArgument)) {
v.dup();
v.arraylength();
v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE),
false);
}
if (arrayOfReferences) {
v.checkcast(type);
}
return Unit.INSTANCE;
});
}
}


String owner;
String addDescriptor;
String toArrayDescriptor;
if (arrayOfReferences) {
owner = "kotlin/jvm/internal/SpreadBuilder";
addDescriptor = "(Ljava/lang/Object;)V";
toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;";
}
else {
String owner;
String addDescriptor;
String toArrayDescriptor;
if (arrayOfReferences) {
owner = "kotlin/jvm/internal/SpreadBuilder";
addDescriptor = "(Ljava/lang/Object;)V";
toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;";
}
else {
String spreadBuilderClassName = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(elementType).getTypeName().getIdentifier() + "SpreadBuilder";
owner = "kotlin/jvm/internal/" + spreadBuilderClassName;
addDescriptor = "(" + elementType.getDescriptor() + ")V";
toArrayDescriptor = "()" + type.getDescriptor();
}
String spreadBuilderClassName = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(elementType).getTypeName().getIdentifier() + "SpreadBuilder";
owner = "kotlin/jvm/internal/" + spreadBuilderClassName;
addDescriptor = "(" + elementType.getDescriptor() + ")V";
toArrayDescriptor = "()" + type.getDescriptor();
}

return StackValue.operation(type, adapter -> {
v.anew(Type.getObjectType(owner));
return StackValue.operation(type, adapter -> {
v.anew(Type.getObjectType(owner));
v.dup();
v.iconst(size);
v.invokespecial(owner, "<init>", "(I)V", false);
for (int i = 0; i != size; ++i) {
v.dup();
v.iconst(size);
v.invokespecial(owner, "<init>", "(I)V", false);
for (int i = 0; i != size; ++i) {
v.dup();
ValueArgument argument = arguments.get(i);
KtExpression argumentExpression = argument.getArgumentExpression();
KotlinType argumentKotlinType = kotlinType(argumentExpression);
if (argument.getSpreadElement() != null) {
gen(argumentExpression, OBJECT_TYPE, argumentKotlinType);

if (argumentKotlinType != null && InlineClassesUtilsKt.isInlineClassType(argumentKotlinType)) {
// we're going to pass value of inline class type to j/l/Object, which would result in boxing and then
// will cause check cast error on toArray() call. To mitigate this problem, we unbox this value and pass
// primitive array to the method. Note that bytecode optimisations will remove box/unbox calls.
StackValue.coerce(
OBJECT_TYPE, argumentKotlinType,
asmType(argumentKotlinType), argumentKotlinType,
v
);
}

v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false);
ValueArgument argument = arguments.get(i);
KtExpression argumentExpression = argument.getArgumentExpression();
KotlinType argumentKotlinType = kotlinType(argumentExpression);

if (argument.getSpreadElement() != null || (argument.isNamed() && state.getLanguageVersionSettings()
.supportsFeature(LanguageFeature.AllowAssigningArrayElementsToVarargsInNamedFormForFunctions))) {
gen(argumentExpression, OBJECT_TYPE, argumentKotlinType);

if (argumentKotlinType != null && InlineClassesUtilsKt.isInlineClassType(argumentKotlinType)) {
// we're going to pass value of inline class type to j/l/Object, which would result in boxing and then
// will cause check cast error on toArray() call. To mitigate this problem, we unbox this value and pass
// primitive array to the method. Note that bytecode optimisations will remove box/unbox calls.
StackValue.coerce(
OBJECT_TYPE, argumentKotlinType,
asmType(argumentKotlinType), argumentKotlinType,
v
);
}
else {
gen(argumentExpression, elementType, argumentKotlinType);
v.invokevirtual(owner, "add", addDescriptor, false);
}
}
if (arrayOfReferences) {
v.dup();
v.invokevirtual(owner, "size", "()I", false);
newArrayInstruction(outType);
v.invokevirtual(owner, "toArray", toArrayDescriptor, false);
v.checkcast(type);

v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false);
}
else {
v.invokevirtual(owner, "toArray", toArrayDescriptor, false);
gen(argumentExpression, elementType, argumentKotlinType);
v.invokevirtual(owner, "add", addDescriptor, false);
}
return Unit.INSTANCE;
});
}
}
if (arrayOfReferences) {
v.dup();
v.invokevirtual(owner, "size", "()I", false);
newArrayInstruction(outType);
v.invokevirtual(owner, "toArray", toArrayDescriptor, false);
v.checkcast(type);
}
else {
v.invokevirtual(owner, "toArray", toArrayDescriptor, false);
}
return Unit.INSTANCE;
});

}
else {
return StackValue.operation(type, outType, adapter -> {
Expand Down Expand Up @@ -4840,7 +4848,7 @@ public StackValue generateNewArray(
}

public void newArrayInstruction(@NotNull KotlinType arrayType) {
if (KotlinBuiltIns.isArray(arrayType)) {
if (isArray(arrayType)) {
KotlinType elementKotlinType = arrayType.getArguments().get(0).getType();
putReifiedOperationMarkerIfTypeIsReifiedParameter(this, elementKotlinType, ReifiedTypeInliner.OperationKind.NEW_ARRAY);
v.newarray(boxType(typeMapper.mapTypeAsDeclaration(elementKotlinType)));
Expand Down Expand Up @@ -4868,7 +4876,7 @@ public StackValue visitArrayAccessExpression(@NotNull KtArrayAccessExpression ex
assert arrayKotlinType != null;
KotlinType elementKotlinType = state.getModule().getBuiltIns().getArrayElementType(arrayKotlinType);
Type elementType;
if (KotlinBuiltIns.isArray(arrayKotlinType)) {
if (isArray(arrayKotlinType)) {
elementType = boxType(asmType(elementKotlinType), elementKotlinType, typeMapper);
}
else {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ object FirNamedVarargChecker : FirCallChecker() {
if (type is ConeErrorType) return
if (argument.expression is FirArrayLiteral) return

if (allowAssignArray && type.isArrayType) return
if (allowAssignArray && type.spreadableCollectionElementType(
context.session.typeContext.newTypeCheckerState(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
)
) != null
) return

if (isAnnotation) {
reporter.reportOn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ val ConeKotlinType.isThrowableOrNullableThrowable: Boolean get() = isAnyOfBuilti
val ConeKotlinType.isChar: Boolean get() = isBuiltinType(StandardClassIds.Char, false)
val ConeKotlinType.isCharOrNullableChar: Boolean get() = isAnyOfBuiltinType(setOf(StandardClassIds.Char))
val ConeKotlinType.isString: Boolean get() = isBuiltinType(StandardClassIds.String, false)
val ConeKotlinType.isCharSequence: Boolean get() = isBuiltinType(StandardClassIds.CharSequence, false)

val ConeKotlinType.isNullableString: Boolean get() = isBuiltinType(StandardClassIds.String, true)

val ConeKotlinType.isEnum: Boolean get() = isBuiltinType(StandardClassIds.Enum, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ class CallAndReferenceGenerator(
if (argument.arguments[0] is FirNamedArgumentExpression &&
// IrVarargElement can be either IrSpreadElement (then nothing to do) or IrExpression
irVarargElement is IrExpression &&
(irVarargElement.type.isArray() || irVarargElement.type.isPrimitiveArray() || irVarargElement.type.isUnsignedArray())
(irVarargElement.type.isSpreadable())
) {
elements[0] = IrSpreadElementImpl(irVarargElement.startOffset, irVarargElement.endOffset, irVarargElement)
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading