bod
01/22/2021, 3:01 PMfun <T> foo(a: T, block: () -> T) {}
foo("Hello") { 1 }
How come this compiles? T is String for a but Int for the block lambda. Bonus question: what's a way to make this not compile and enforce the same type? ๐ Thanks ๐diesieben07
01/22/2021, 3:03 PMT is inferred to be Any, which is the common supertype of String and Int, foo then returns Any.diesieben07
01/22/2021, 3:03 PMbod
01/22/2021, 3:06 PMNir
01/22/2021, 3:10 PMNir
01/22/2021, 3:11 PMlistOfVampire
01/22/2021, 3:14 PMNir
01/22/2021, 3:14 PMVampire
01/22/2021, 3:16 PMAny there. :-)Nir
01/22/2021, 3:18 PMflosch
01/22/2021, 3:19 PMfun <T> foo(a: T, block: () -> T) where T : String {}
will constrain itMarc Knaup
01/22/2021, 3:19 PMimport kotlin.internal.*
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(a: @Exact T, block: () -> T) {}
fun main() {
foo("Hello") { 2 }
}
(evil hackโข)
Alternative with warning, but no less evil:
import kotlin.internal.*
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@OnlyInputTypes T> foo(a: T, block: () -> T) {}
fun main() {
foo("Hello") { 2 }
}bsimmons
01/22/2021, 3:20 PMT you're explicitly saying you don't care about the type. So it's kinda contradictory to then turn around and be surprised that any type will work.Vampire
01/22/2021, 3:21 PMfoo(1) { 2 } and as String is final it would be pointless to use generics at allflosch
01/22/2021, 3:23 PMBonus question: whatโs a way to make this not compile and enforce the same type?and this is how you do that
Vampire
01/22/2021, 3:27 PMString is not final in Kotlin, missed that.
Assumed it is final like in Java.
But you still miss the meaning of the bonus question.
The question is how to enforce both `T`s are of the same non-Any type,
but without restraining to just String subtypes.
As I said, the goal is that foo("Hello") { "World" } works as well as foo(1) { 2 } or any other type, while foo("Hello") { 1 } does not and there seems to be no way without using internals to reach that.diesieben07
01/22/2021, 3:27 PMString is final in kotlin, because it is not open ๐Marc Knaup
01/22/2021, 3:27 PMString is definitely final ๐
Vampire
01/22/2021, 3:28 PMVampire
01/22/2021, 3:28 PMfun foo(a: String, block: () -> String) {}flosch
01/22/2021, 3:35 PMbod
01/22/2021, 4:02 PMfun <T> bar(a: T, b: T) {}
bar("Hello", 1)Vampire
01/22/2021, 4:03 PMAny still.
As you don't do anything with a or b where Any cannot be used, this is just fine.bod
01/22/2021, 4:05 PMbod
01/22/2021, 4:06 PMkotlin.internal ways ๐)Nir
01/22/2021, 4:12 PMNir
01/22/2021, 4:12 PMNir
01/22/2021, 4:12 PMNir
01/22/2021, 4:13 PMbar(listOf(1,2,3), mutableListOf(4,5,6))Nir
01/22/2021, 4:13 PMAny is usefulbod
01/22/2021, 4:15 PMNir
01/22/2021, 4:17 PMNir
01/22/2021, 4:17 PMNir
01/22/2021, 4:17 PMVampire
01/22/2021, 4:18 PMNir
01/22/2021, 4:20 PMNir
01/22/2021, 4:20 PMNir
01/22/2021, 4:20 PMNir
01/22/2021, 4:20 PMVampire
01/22/2021, 4:20 PMNir
01/22/2021, 4:21 PMVampire
01/22/2021, 4:21 PMNir
01/22/2021, 4:22 PMNir
01/22/2021, 4:22 PMVampire
01/22/2021, 4:22 PMbsimmons
01/22/2021, 5:00 PMfun <T: Comparable<T>> foo(a: T, block: () -> T) {}
At least it will cause a compiler error.bod
01/22/2021, 5:04 PMVampire
01/22/2021, 5:04 PMVampire
01/22/2021, 5:05 PMAny wouldn't be inferred, as it is not Comparablebod
01/22/2021, 5:07 PMbod
01/22/2021, 5:07 PMVampire
01/22/2021, 5:09 PMfun <T> foo(t: T) where T : !Any {}
๐