raulraja
06/19/2019, 9:27 AM.class
.
Idea is able to parse that presumably through the metadata annotations or parsing the class structure somehow.
Why doesn’t this work for synthetically generated code which also ends up in a class file? What is different from that bytecode and the one a user types in by hand and is properly recognised by the IDE.
Now for the human side…
For what is worth I’m grateful for everything JB does but the state of meta programming and compiler plugins in Kotlin which has been frequently brought up at conferences and many times publicly does not seem to have a Roadmap or goals for that matter that are publicly known to the community. Instead companies like Google are forking the Kotlin compiler because that is easier since they have control of Android Studio and they have announced a Jetpack Compose, a framework as the future of Android Development which is based on a compiler fork.
At this moment Jetpack Compose relies on a bunch of compiler extensions that are not public or have been modified to fit their needs, (many) I have read the sources and checked with their devs.
Does that mean that all extensions they rely upon will be accepted upstream in the Kotlin compiler?. I’m not sure forking the compiler is good for anyone but the current state of meta in Kotlin is forcing companies to do just this.
It’s not good for everyone when there are multiple versions of the compiler unless they are for KEEPs or enhancing the upstream compiler we all should rely upon.dsavvinov
06/19/2019, 9:28 AMIt’s not good for everyone when there are multiple versions of the compiler unless they are for KEEPs or enhancing the upstream compiler we all should rely uponYes, for sure. I’m not directly related to work around Compose, but, as far as I know, there’s some work on upstreaming those extension points, and it also includes discussions about how to make those EPs universally useful, not just something only JetPack can use. But it’s a long road, yes.
dsavvinov
06/19/2019, 9:37 AMWhy doesn’t this work for synthetically generated code which also ends up in a class file? What is different from that bytecode and the one a user types in by hand and is properly recognised by the IDE.First of all, a little disclaimer I should’ve written earlier. We’re treading a really deep waters of the compiler here, or even, pretty much unknown, because as I said above, API hasn’t been designed properly yet. So, we’re almost pioneers here, and take all my answers with a grain of salt — it’s my understanding how the things work, not the ground truth, as I may easily miss somthing 🙂 If you’re depending on such jar, then, I think, it should work, and synthetically generated code shouldn’t be different from anything. In the worst case, you may miss
@Metadata
for synthetically generated declarations, and they will be seen as Java API.
However, if that’s the sources you’re working with, then it’s completely another story. What is your case?raulraja
06/19/2019, 9:42 AMOption<A>
there should be a marker class generated called ForOption
.
The issue I have is that in the same file I declare Option<A>
I can reference compile and run just fine with references to ForOption
but IDEA shows them in red. If I go to a new module that depends on Option and ForOption the compiler frontend bails saying ForOption
is not a valid reference.
In general we have to expand with these compiler plugins some marker types but also DSLs like the Optics DSL where we enhance companions with new members.raulraja
06/19/2019, 9:42 AMpackage arrow.sample
import arrow.sample.ForOption
interface Kind<out F, out A>
sealed class Option<out A>
object None : Option<Nothing>()
data class Some<out A>(val a: A) : Option<A>()
raulraja
06/19/2019, 9:43 AMraulraja
06/19/2019, 9:45 AMraulraja
06/19/2019, 9:45 AMimport arrow.sample.ForOption
dsavvinov
06/19/2019, 9:45 AMForOption
, right?raulraja
06/19/2019, 9:47 AMraulraja
06/19/2019, 9:47 AMraulraja
06/19/2019, 9:48 AMraulraja
06/19/2019, 9:49 AMraulraja
06/19/2019, 9:50 AMraulraja
06/19/2019, 9:51 AMdsavvinov
06/19/2019, 9:52 AMdsavvinov
06/19/2019, 10:01 AMkotlin
repo, it is intentionally moved in a separate Gradle subproject, so it relatively easy to detach it from kotlin
repo. Also, it is known to work 🙂 So, I propose you to start playing with it, gradually changing its sources to what you want to do, probably without whole Arrow-specific logic, just integration with Kotlin. Then, it should be easy a) for you to track where you made a change which broke everything b) for everyone else to see your code, because it will be in a public fork and won’t contain any business logic you don’t want to share.raulraja
06/19/2019, 10:08 AMraulraja
06/19/2019, 10:08 AMdsavvinov
06/19/2019, 10:09 AMraulraja
06/19/2019, 11:29 AMdmitriy.novozhilov
06/19/2019, 11:38 AMdmitriy.novozhilov
06/19/2019, 11:43 AMComponentRegistrar
in your plugin (see lines 37 and 38)
https://github.com/JetBrains/kotlin/blob/8af1f156b29b91509bd26423ff68c18225642ef5/plugins/contracts/contracts-plugin/src/org/jetbrains/kotlin/contracts/contextual/ContractsComponentRegistrar.kt#L37dmitriy.novozhilov
06/19/2019, 11:44 AMraulraja
06/19/2019, 12:46 PMraulraja
06/19/2019, 8:05 PMAny? -> Any hierarchy
.
In our use case we generate this boilerplate for the higher kind emulation in Arrow for example for the Id
type:
class ForId private constructor() { companion object }
typealias IdOf<A> = arrow.Kind<ForId, A>
inline fun <A> IdOf<A>.fix(): Id<A> =
this as Id<A>
We would like to annotate with a contract the fix
function to state whenever there is a value of IdOf<A>
that is also a smart cast to Id<A>
. This is correct because Id<A> : IdOf<A>
and nobody else extends that.
Is this something we could accomplish with the Contract extension?
Essentially if this was done with the contracts API we would do something like:
inline fun <A> IdOf<A>.fix(): Id<A> {
contract { returns() implies this@fix is Id<A> }
return this as Id<A>
}
but his@fix is Id<A>
is not current available as valid syntax in contracts.dmitriy.novozhilov
06/19/2019, 10:20 PMcontracts-plugin-serialization
is a branch with prototype of new kind of contracts that can provide some CFA diagnostics. It was an experiment and there is no plans to add that code to master in 1.4 or earlier. If you interested in, you can take a look at demo repository with those contracts: https://github.com/demiurg906/kotlin-contracts-samplesdmitriy.novozhilov
06/19/2019, 10:21 PMinterface A<T>
interface B<T> : A<T> {
fun foo()
}
fun <T> A<T>.requireIsB(): B<T> {
contract {
returns() implies (this@requireIsB is B<T>)
}
return this as B<T>
}
fun <T> test(a: A<T>) {
a.requireIsB()
a.foo() // smartcast
}
raulraja
06/20/2019, 8:15 AMimplies
is infix and I thought it was an actual syntax keyword, my bad thanks !