Mark
06/10/2022, 5:10 AMSpannableStringBuilder.inSpans()
fun <A : Appendable> A.inSpans(vararg spans: Any, builderAction: A.() -> Unit): A =
if (this is SpannableStringBuilder) {
// PROBLEM: doesn't call SpannableStringBuilder.inSpans()
inSpans(spans = spans, builderAction = builderAction)
} else {
builderAction()
this
}Mark
06/10/2022, 5:14 AMfun <A : Appendable> A.inSpans(vararg spans: Any, builderAction: A.() -> Unit): A {
if (this is SpannableStringBuilder) {
inSpans(spans) {
builderAction()
}
} else {
builderAction()
}
return this
}
It seems the key part is to specify the lambda explicitly rather than passing the builderAction referenceephemient
06/10/2022, 5:17 AMbuilderAction: A.() -> Unit so overload resolution can only choose your local function. when wrapped in the lambda, the receiver it's being called on is the outer A, not the inner SpannableStringBuilderephemient
06/10/2022, 5:19 AMspans = spans or *spans, you're invoking the span = overloadMark
06/10/2022, 5:30 AMspans = spans issue is a nasty one (IMO an API design flaw). I actually had it like that originally, but mistakenly forgot about the easy-to-make mistake.Mark
06/10/2022, 5:34 AM(this as A).builderAction()?ephemient
06/10/2022, 5:41 AM{ builderAction() } it actually means { this@inSpans.builderAction() }, not { this.builderAction() } - that's what makes it different than passing it directlyMark
06/10/2022, 5:48 AM{ this.builderAction() } ?ephemient
06/10/2022, 5:49 AMthis: SpannableStringBuilder does not match builderAction: A.() -> Unitephemient
06/10/2022, 5:50 AMephemient
06/10/2022, 5:51 AMbuilderAction: Appendable.() -> Unit it would be applicableMark
06/10/2022, 5:55 AM(this as A). would also work right?ephemient
06/10/2022, 5:56 AMA could be a subtype of SpannableStringBuilderephemient
06/10/2022, 5:57 AMephemient
06/10/2022, 6:01 AMthis is SpannableStringBuilder does not imply <SpannableStringBuilder : A>