Skip to content

Conversation

@smowton
Copy link
Contributor

@smowton smowton commented Dec 2, 2022

No description provided.

@smowton smowton requested review from a team as code owners December 2, 2022 20:18
Comment on lines 1098 to 1103
if (f is IrConstructor && f.valueParameters.isNotEmpty() && f.valueParameters.all { it.defaultValue != null }) {
// Per https://kotlinlang.org/docs/classes.html#creating-instances-of-classes, a single default overload gets created specifically
// when we have all default parameters, regardless of `@JvmOverloads`.
extractGeneratedOverload(f.valueParameters.map { _ -> null })
}
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we only generating a single parameterless constructor in this case?
The following code:

public class AllDefaultsConstructor(val x: Int=1, val y: Int = 2)

shows up as the below in bytecode:

public <init>(II)V
public synthetic <init>(IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public <init>()V

Are we still generating the second overload?

In the below

fun fn() {
    AllDefaultsConstructor()
    AllDefaultsConstructor(1)
    AllDefaultsConstructor(1,2)
}

The first two instances are created through public synthetic <init>(IIILkotlin/jvm/internal/DefaultConstructorMarker;)V, do I understand it correctly that the parameterless constructor is only added for interop with Java?

Copy link
Contributor Author

@smowton smowton Dec 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's right.

The rules:

Scenario Generated functions
Constructor, all default params, no @JvmOverloads No-arg constructor, DefaultConstructorMarker constructor
Constructor, some default params, no @JvmOverloads DefaultConstructorMarker constructor
Constructor, @JvmOverloads annotation A constructor that omits all default parameters ... one that omits only the rightmost default parameter, plus the DefaultConstructorMarker constructor
Method, some/all default params, no @JvmOverloads A $default method
Method, some/all default params, has @JvmOverloads A method that omits all default parameters ... one that omits only the rightmost default parameter, plus a $default method

extractGeneratedOverloads is responsible for producing the @JvmOverloads variants + the no-arg constructor; extractDefaultsFunction produces the $defaults method or DefaultConstructorMarker constructor.

AFAICT Kotlin will always call via the $defaults / DefaultConstructorMarker variant even if a more "natural" Java interop version is available.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this table is super useful. Are there tests that cover all use cases? I think there might be no unit tests that cover the Constructor, all default params, no @JvmOverloads scenario, which is introduced in this PR, but hopefully the integration test would report an issue if the constructor was not added by the kotlin extractor.

Copy link
Contributor Author

@smowton smowton Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I figured the integration test could be more direct since Java can actually use the generated constructor -- if it was missing, we'd see a database inconsistency because callableBinding would point at a non-existent symbol. Test coverage: yes I think we've got all those cases; the missing one was the top one, for which this PR introduces coverage.

@smowton smowton merged commit 3b5b121 into github:main Dec 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants