Open Lonami opened 1 year ago
If I comment out all offending FfiConverter
until the preview stops complaining (and replace their uses in method definitions with a TODO()
), the @Preview
starts working again. I don't think the implementation itself (read
, allocationSize
and write
) have any part on this. It might be the way the sub-classing is defined (as in FfiConverterTypeTextFormat : FfiConverterRustBuffer<TextFormat>
). But I really have no idea why it could possibly fail with VerifyError
… Maybe it's the way the interface is defined?
interface FfiConverterRustBuffer<KotlinType> : FfiConverter<KotlinType, RustBuffer.ByValue>
But this really seems like a bug in the compiler, perhaps being unable these generics.
What is most strange to me is that the application runs fine when not inside a @Preview
.
It's definitely not easily reproducable in just plain Kotlin. Could you put a full failing example into a repository so I can run and test it? Might be easier than me trying to piece together the parts to get it to build. I'm happy to take a look then.
Thanks a lot for taking the time to look into this. I've created a new project from a Compose template, and after configuring the Rust plugins and uniffi and setting up the NDK version, setup the code necessary to trigger the issue.
I've published the failing code at https://github.com/Lonami/VerifyError-Repro.
Please let me know if you need any more details to import or run the project, or if I can help in any other way. After importing the project, assuming both the NDK and uniffi are configured and installed in the system correctly, it should be possible to open MainActivity.kt
in Android Studio and select the Split or Design view (to the right) to trigger the VerifyError
during the @Preview
of DefaultPreview
:
(The squiggly line under Instant.now()
is Call requires API level 26 (current min is 21): java.time.Instant#now
, which can be safely ignored for this demo.)
The code generated by uniffi-bindgen
is placed at app/build/generated/source/uniffi/debug/java/uniffi/verifyerror
:
The code generation is done by app/build.gradle
(at the bottom of the file, android.applicationVariants.all { ...
) and invokes the following command:
commandLine 'uniffi-bindgen', 'generate', '../native/src/verifyerror.udl', '--language', 'kotlin', '--no-format', '--out-dir', "${buildDir}/generated/source/uniffi/${variant.name}/java"
I spent a bit of time on it this morning. I am able to reproduce it using the provided code. I'm fairly sure now this is some miscompilation in whatever does the preview rendering. I don't think the uniffi code is inherently wrong. But I also don't know where the buggy behavior is hiding.
Unfortunately I can't spent much more time on this right now.
Thanks, yeah, it's probably safe to close this issue as the bug is unlikely to be uniffi's fault (technically, I'm sure the code could be generated in a different way to not trigger this problem, but that's a workaround and not the right solution).
The repository I mentioned earlier was deleted but here's the main contents of the files:
Maybe this can be closed as stale.
My
uniffi
version is0.21.0
. I think there might be an issue when trying to construct uniffi types within a Jetpack Compose@Preview @Composable
, but I'm not sure if it's a problem with uniffi, the Kotlin compiler, the Jetpack library, or my own code.My
.udl
contains something like this:I have the following Kotlin code constructing the
Message
instance:Trimmed build.gradle
```gradle // using gradle-7.4 // project buildscript { ext { compose_ui_version = '1.2.1' } } plugins { id 'com.android.application' version '7.2.2' apply false id 'com.android.library' version '7.2.2' apply false id 'org.jetbrains.kotlin.android' version '1.6.10' apply false id "org.mozilla.rust-android-gradle.rust-android" version "0.9.3" } // module plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id "org.mozilla.rust-android-gradle.rust-android" } android { namespace 'com.example.myapp' compileSdk 33 defaultConfig { applicationId "com.example.myapp" minSdk 26 targetSdk 33 versionCode 1 versionName "0.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary true } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.1.1' } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } ndkVersion '25.1.8937393' } dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1" implementation 'androidx.activity:activity-compose:1.6.0' implementation "androidx.compose.ui:ui:$compose_ui_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version" implementation 'androidx.compose.material:material:1.2.1' implementation "androidx.navigation:navigation-compose:2.5.2" implementation "net.java.dev.jna:jna:5.12.0@aar" testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version" } ```The render preview fails as follows:
Stack Trace
``` java.lang.VerifyError: Bad type on operand stack Exception Details: Location: uniffi/myapp/LiveLiterals$MyappKt.Byte$arg-0$call-put$branch$if$fun-write$class-FfiConverterOptionalString()B @11: ireturn Reason: Type 'java/lang/Object' (current frame, stack[0]) is not assignable to integer Current Frame: bci: @11 flags: { } locals: { 'uniffi/myapp/LiveLiterals$MyappKt' } stack: { 'java/lang/Object' } Bytecode: 0000000: 2a13 030c 1303 7401 b803 1cac at uniffi.myapp.Message.Because the error says:
I assumed it might be an issue with uniffi, but I totally understand it might be some problem on my end. If that's the case, please don't hesitate to close this issue.
Generated FfiConverterOptionalString
```kotlin public object FfiConverterOptionalString: FfiConverterRustBufferGetting rid of
string? extra
inTextFormat
yields a similar error, but this time the location is different:Getting rid of that fails elsewhere in my project with a different unrelated optional. It might come down to the way Kotlin is initializing stuff, but I really have no idea.
┆Issue is synchronized with this Jira Task ┆friendlyId: UNIFFI-208