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 PMlistOf
Vampire
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 Comparable
bod
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 {}
๐