Status Update
Comments
as...@google.com <as...@google.com>
as...@google.com <as...@google.com> #2
Chuck, the code we generate here looks correct, any ideas why it happens?
@Composable
public final void Arf(@NotNull String[] woof, @Nullable Composer $composer, int $changed) {
$composer = $composer.startRestartGroup(711302877);
ComposerKt.sourceInformation($composer, "C(Arf)*3977@105604L10:CompositionTests.kt#9igjgp");
int $dirty = $changed;
$composer.startMovableGroup(507628111, woof.length);
int var5 = 0;
int var6;
String bark;
for(var6 = woof.length; var5 < var6; ++var5) {
bark = woof[var5];
$dirty |= $composer.changed(bark) ? 4 : 0;
}
$composer.endMovableGroup();
if (($dirty & 14) == 0) {
$dirty |= 2;
}
if (($dirty & 11) == 2 && $composer.getSkipping()) {
$composer.skipToGroupEnd();
} else {
if (ComposerKt.isTraceInProgress()) {
ComposerKt.traceEventStart(711302877, $dirty, -1, "androidx.compose.runtime.CompositionTests.Arf (CompositionTests.kt:3975)");
}
var5 = 0;
for(var6 = woof.length; var5 < var6; ++var5) {
bark = woof[var5];
ViewsKt.Text(bark, $composer, 0);
}
if (ComposerKt.isTraceInProgress()) {
ComposerKt.traceEventEnd();
}
}
ScopeUpdateScope var10000 = $composer.endRestartGroup();
if (var10000 != null) {
var10000.updateScope((Function2)(new Arf.1(this, woof, $changed)));
}
}
as...@google.com <as...@google.com> #3
Dumping applier operations on removal shows slightly suspicious AdvanceSlotsBy
after the new group is inserted:
Executing AdvanceSlotsBy(
distance = 5
)
Executing EnsureRootGroupStarted
Executing EnsureGroupStarted(
anchor = androidx.compose.runtime.Anchor@4d33940d{ location = 4 }
)
Executing InsertSlots(
anchor = androidx.compose.runtime.Anchor@43cf6ea3{ location = 0 },
from = [[]]
)
Executing AdvanceSlotsBy( <-- It seems like this advance messes up group structure
distance = 10
)
Executing RemoveCurrentGroup
// crash
al...@google.com <al...@google.com> #4
Triage notes: Generated code must be incorrect. Bumping to P2
since this is a crasher.
ch...@google.com <ch...@google.com> #5
The generated code is incorrect as it doesn't detect that the varargs changed when the arguments go to 0. This is becuase the loop to check the parameters never executes and $dirty
is left as 0. The causes skipToEndGroup()
to execute which is unexpected as it puts the composer in a bad state where it doesn't correctly detect that it needs to delete the value. The code should be generated in a way where size changes in varargs
parameter ensure that $dirty
is non-zero.
Going to 0 is not the only case this will happen. The code is incorrect for any varargs that is shorter than the prior one but all the present paramters match their previous values (e.g. one or more values are removed from the end of the list). Going to 0 is a trivial way to get into this state.
Description
Steps to Reproduce or Code Sample to Reproduce:
Run the
CrashMe()
composable below:Stack trace (if applicable):