= 10, ) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 high l ow x 1 :de f a ul t va lu e p r esent 0 :no de f a ul t va lu e @Composable fun A( x: Int, $default: Int, )
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 high l ow x 1 :de f a ul t va lu e p r esent 0 :no de f a ul t va lu e y @Composable fun A( x: Int = 10, y: Int, ) @Composable fun A( x: Int, y: Int, $default: Int, )
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 high l ow x 1 :de f a ul t va lu e p r esent 0 :no de f a ul t va lu e y z @Composable fun A( x: Int = 10, y: Int, z: Int = 20, ) @Composable fun A( x: Int, y: Int, z: Int, $default: Int, )
y: Int, $changed: Int, ) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y x high l ow <this> ※B Rese r ved bit (1: f o r ce r ecomposition)
x: Int, y: Int, $changed: Int, ) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y x high l ow <this> ※B z Rese r ved bit (1: f o r ce r ecomposition)
@Composable fun B.A( x: Int, y: Int, $changed: Int, ) } high l ow <this> ※C Rese r ved bit (1: f o r ce r ecomposition) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y x <this> ※B z
$changed: Int, $default: Int) { var $dirty = $changed if ($default and 0b0001 != 0) { // default value presents $dirty = $dirty and 0b0110 // Static } // f(x) } 0 0 0 Unce r tain 0 1 0 Di ff e r ent 0 0 1 Same 0 1 1 Static 1 0 0 Un k nown
$changed: Int, $default: Int) { var $dirty = $changed if ($default and 0b0001 != 0) { // default value presents $dirty = $dirty and 0b0110 // Static } else if ($changed and 0b0110 == 0) { // Uncertain or Unknown } // f(x) } 0 0 0 Unce r tain 0 1 0 Di ff e r ent 0 0 1 Same 0 1 1 Static 1 0 0 Un k nown
$changed: Int, $default: Int) { var $dirty = $changed if ($default and 0b0001 != 0) { // default value presents $dirty = $dirty and 0b0110 // Static } else if ($changed and 0b0110 == 0) { // Uncertain or Unknown $dirty = $dirty or if ($composer.changed(x)) 0b0100 // Different else 0b0010 // Same } // f(x) } 0 0 0 Unce r tain 0 1 0 Di ff e r ent 0 0 1 Same 0 1 1 Static 1 0 0 Un k nown
{ var $dirty = } var $dirty = … // calculate $dirty bitmask… if ( $composer.shouldExecute( $dirty and 0b0011 != 0b0010, // state of x was changed $dirty and 0b0001 // force recomposition ) ) { } } Recompose with $dirty 34 0 0 0 Unce r tain 0 1 0 Di ff e r ent 0 0 1 Same 0 1 1 Static 1 0 0 Un k nown
{ var $dirty = … // calculate $dirty bitmask… if ( $composer.shouldExecute( $dirty and 0b0011 != 0b0010, // state of x was changed $dirty and 0b0001 // force recomposition ) ) { } } Recompose with $dirty 35 0 0 0 Unce r tain 0 1 0 Di ff e r ent 0 0 1 Same 0 1 1 Static 1 0 0 Un k nown @Composable fun A(x: Int, $composer: Composer?, $changed: Int, $default: Int) { var $dirty = … // calculate $dirty bitmask… if ( $composer.shouldExecute( $dirty and 0b0011 != 0b0010, // state of x was changed $dirty and 0b0001 // force recomposition ) ) { if ($default and 0b0001 != 0) x = 10 f(x, $composer, 0b0110) // x is Static from here } }
r o u p • ؔͷ࠶࣮ߦڥքɺεΩοϓՄೳͳάϧʔϓ • Rep l aceab l e G r o u p • ஔՄೳͳ୯Ґʢi f -e l se, whenͳͲ੍ޚϑϩʔʹඥͮ͘άϧʔϓʣ • Movab l e G r o u pʢ k e y ͳͲͰੜʣ • ݺͼग़͠ॱʹґଘͤͣɺS l otͷҐஔΛॊೈʹҠಈͰ͖Δάϧʔϓ 40
{ var $dirty = … // calculate $dirty bitmask… if ( $composer.shouldExecute( $dirty and 0b0011 != 0b0010, // state of x was changed $dirty and 0b0001 // force recomposition ) ) { if ($default and 0b0001 != 0) x = 10 f(x, $composer, 0b0110) // x is Static from here } } 45
not • ҆ఆʢStab l eʣ • $changed ΛͬͨߴͳՁఆ͕Մೳ • ঢ়ଶมԽΛ҆શʹͰ͖Δ → εΩοϓՄೳ • ෆ҆ఆʢUnstab l eʣ • ࣮͔֬ͭߴͳൺֱखஈ͕ͳ͘ݪଇεΩοϓෆՄೳ • ྫ֎ɿSt r ong S k ipping Mode༗ޮ࣌ࢀরൺֱʹΑΓεΩοϓ͞ΕΔ 53
l fu nction: F u nction <* > / / va l k f : (St r ing) -> Boo l ean = St r ing :: isEmpt y va l k F u nction: K F u nction <*> All Stable Function type? … ❌No ✅Yes Stable …
l ean: Boo l ean va l cha r : Cha r va l b y te: B y te va l sho r t: Sho r t va l int: Int va l fl oat: F l oat va l l ong: Long va l do u b l e: Do u b l e … All Stable
e { boo l is_enab l ed = 1; } Is Protobuf type? … ❌No ✅Yes … Stable Stable p u b l ic f ina l c l ass Samp l e p r ivate const ru cto r ( va l name: St r ing = "", va l id: Long = 0L, ): com.goog l e.p r otob uf .Gene r ateMessageLite <Samp l e,Samp l e.B u i l de r > (DEFAULT_INSTANCE),
r .stabi l it y O f (I r C l ass, …) va l dec l a r ation: I r C l ass i f ( canIn f e r Stabi l it y (dec l a r ation) | | dec l a r ation.isExte r na l Stab l eType() ) { … } Can infer stability or external stable type? … ❌No ✅Yes … Extra Logic
l stab l eT y pes = mapO f ( Pai r :: c l ass.q u a l i f iedName !! to 0b11, … // G u ava "com.goog l e.common.co ll ect.Imm u tab l eList" to 0b1, … // K ot l inx imm u tab l e " k ot l inx.co ll ections.imm u tab l e.Imm u tab l eCo ll ection" to 0b1, " k ot l inx.co ll ections.imm u tab l e.Imm u tab l eList" to 0b1, … // Dagge r "dagge r .Laz y " to 0b1, // Co r o u tines Empt y Co r o u tineContext :: c l ass.q u a l i f iedName !! to 0, // Java t y pes BigIntege r:: c l ass.q u a l i f iedName !! to 0, BigDecima l:: c l ass.q u a l i f iedName !! to 0, ) Can infer stability or external stable type? ✅Yes Is known stable type? ✅Yes (maybe)Stable … ❌No
e.Exte r na l T y pe // Pac k age wi l dca r d com.examp l e.mode l s.** // Sing l e-segment wi l dca r d com.examp l e.*.data // Gene r ic pa r amete r inc lu sion com.examp l e.Containe r<*> // Gene r ic pa r amete r exc lu sion com.examp l e.W r appe r<* ,_> // Mixed gene r ic pa r amete r s com.examp l e.Comp l ex <* ,_, *> Is known stable type? Is external stable type? ✅Yes (maybe)Stable … ❌No https: // gith u b.com/s ky doves/compose-stabi l it y -in f e r ence? tab= r eadme-ov- f i l e#62-con f ig ur ation- f i l es stabi l it y _con f ig.con f
e r ence b y s ky doves͞Μ • https: // gith u b.com/s ky doves/compose-stabi l it y -in f e r ence?tab= r eadme- ov- f i l e#27-stabi l it y -decision-t r ee • ίϯύΠϥϓϥάΠϯͷ࣮ʹج͍ͮͯΘ͔Γ͘͢ཧͨ͠ ϑϩʔνϟʔτ͕࡞ΒΕ͍ͯ·͢ 69
r ans f o r mation • $compose r , $changed, $de f a ul t • $changed, $de f a ul t, $compose r .changed o r changedInstance → $di r t y → $compose r .sho ul dExec u te • Resta r t/Rep l ace/Movaba l e G r o u ps f o r node management • IR di ff e r ences when pa r amete r s a r e stab l e o r u nstab l e • Stabi l it y In f e r ence a l go r ithm 70