Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,10 @@ private static OutputBuilder methodCall(MethodCall mc, Qualification q) {
.add(SymbolEnum.DOT).add(new TextImpl(mc.methodInfo().name()))
.add(arguments(mc.parameterExpressions(), mc.methodInfo(), q));
}
if (object != null && !mc.objectIsImplicit() && expectedElement(mc) == null && (toArrayOf(mc.methodInfo())
// super.toArray() in a subclass of a Java collection class (AbstractCollection): Kotlin sees Java's toArray as
// the superclass's member, and `super` is no value to cast or to call an extension on
boolean onSuper = object instanceof VariableExpression sv && sv.variable() instanceof This st && st.writeSuper();
if (object != null && !mc.objectIsImplicit() && !onSuper && expectedElement(mc) == null && (toArrayOf(mc.methodInfo())
&& mc.parameterExpressions().getFirst().parameterizedType() != null
&& mc.parameterExpressions().getFirst().parameterizedType().arrays() == 1
&& mc.parameterExpressions().getFirst().parameterizedType().componentType().typeParameter() != null
Expand Down Expand Up @@ -379,7 +382,7 @@ private static OutputBuilder methodCall(MethodCall mc, Qualification q) {
if (KotlinMappedMembers.isRemoveAt(mc.methodInfo())) {
return b.add(new TextImpl("removeAt")).add(arguments(mc.parameterExpressions(), q));
}
if (toArrayOf(mc.methodInfo()) && object != null && !mc.objectIsImplicit()) {
if (toArrayOf(mc.methodInfo()) && object != null && !mc.objectIsImplicit() && !onSuper) {
// c.toArray(new X[0]): Kotlin's collections have no toArray(T[]); toTypedArray<X>() types the array as
// Java's argument does (Kotlin's arrays are invariant, its Collection<out E> is not), with the element
// state of what it initializes
Expand All @@ -390,7 +393,7 @@ private static OutputBuilder methodCall(MethodCall mc, Qualification q) {
.withNullable(io.codelaser.maddi.cst.api.type.NullableState.NONNULL), q);
return b.add(new TextImpl(element == null ? "toTypedArray()" : "toTypedArray<" + element + ">()"));
}
if (toArray(mc.methodInfo()) && object != null && !mc.objectIsImplicit()) {
if (toArray(mc.methodInfo()) && object != null && !mc.objectIsImplicit() && !onSuper) {
// c.toArray(): Kotlin's collections have no toArray() either. toTypedArray<Any?>() or <Any>(), as Java's
// Object[] prints here (a Collection<out E> is a Collection of either): typed by the collection, a local
// would be an Array<String> where Java declares an Object[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,29 @@ abstract class Fwd<E> implements Collection<E> {
compiles(kotlin);
}

/**
* A subclass of AbstractCollection, a Java class: Kotlin sees its toArray() and toArray(T[]) as members, so
* {@code super.toArray()} stays a call to the superclass's member. Kotlin's {@code super} is no value: it can be
* neither cast ({@code (super as java.util.Collection<*>)}) nor the receiver of the extension toTypedArray.
*/
@Test
public void toArrayOnSuper() {
String kotlin = kotlin("""
package a;
import java.util.*;
class Bag<E> extends AbstractCollection<E> {
private final List<E> items = new ArrayList<>();
@Override public Iterator<E> iterator() { return items.iterator(); }
@Override public int size() { return items.size(); }
@Override public Object[] toArray() { return super.toArray(); }
@Override public <T> T[] toArray(T[] array) { return super.toArray(array); }
}
""");
contains(kotlin, "super.toArray()");
contains(kotlin, "super.toArray(array)");
compiles(kotlin);
}

/**
* guava's Optional.toJavaUtil(), AbstractValueGraph.edgeValue: java.util.Optional.ofNullable(t) into an
* Optional<T>. Kotlin's Optional bounds its T non-null, so the call is an Optional<T & Any>; the cast is unchecked.
Expand Down
Loading