Skip to content

[Xamain.Android.Tools.Bytecode] Hide private Kotlin default constructors. #1206

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

Merged
merged 1 commit into from
Apr 15, 2024

Conversation

jpobst
Copy link
Contributor

@jpobst jpobst commented Mar 18, 2024

Kotlin.Stdlib contains the public class kotlin.io.encoding.Base64 which is not intended to be instantiated by external users. Thus it only contains a private default constructor.

https://github.com/JetBrains/kotlin/blob/3fbb7bc92086bdf3bde123a8f774bce25b19ef37/libraries/stdlib/src/kotlin/io/encoding/Base64.kt

public open class Base64 private constructor (internal val isUrlSafe: Boolean, internal val isMimeScheme: Boolean) {
   public companion object Default : Base64(isUrlSafe = false, isMimeScheme = false) { ... }
}

This compiles into the following Java constructors:

private <init> (Boolean isUrlSafe, Boolean isMimeScheme) { ... }

public <init> (Boolean isUrlSafe, Boolean isMimeScheme, kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker) { ... }
// ^ synthetic constructor

Previously we believed that a synthetic default constructor would always end in an int and a DefaultConstructorMarker parameter, however this one does not.

https://github.com/xamarin/java.interop/blob/651de42732d194cee5a45fae45feda37706a8c16/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs#L100-L103

This synthetic constructor causes us to generate some bizarre constructors:

[Register (".ctor", "(ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V", "")]
public unsafe Base64 (bool isUrlSafe, bool isMimeScheme, global::Kotlin.Jvm.Internal.DefaultConstructorMarker? _constructor_marker) 
    : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) { ... }

This commit extends our Kotlin default constructor marker detection logic to look for any synthetic constructor whose final parameter is DefaultConstructorMarker to handle this additional case.

With the change, Kotlin.IO.Encoding.Base64 no longer generates a public constructor.

@jpobst
Copy link
Contributor Author

jpobst commented Apr 3, 2024

Ran this change against our AndroidX repo to ensure only intended constructors were getting removed. Diff file looks good.

output.txt

@jpobst jpobst marked this pull request as ready for review April 3, 2024 23:32
@jpobst jpobst requested a review from jonpryor April 3, 2024 23:32
@jonpryor jonpryor merged commit 06214ff into main Apr 15, 2024
@jonpryor jonpryor deleted the kotlin-constructor-fix branch April 15, 2024 23:27
@github-actions github-actions bot locked and limited conversation to collaborators May 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants