In a compiler plugin in the `SyntheticResolverExte...
# compiler
r
In a compiler plugin in the
SyntheticResolverExtension
I’m overriding
generateSyntheticClasses(PackageFragmentDescriptor, ...)
and
addSyntheticSupertypes
. I’m attempting to add a super type to a class that I generate myself in that pass. For example:
Copy code
package x
interface Foo<A>
class Bar
I want to expand to:
Copy code
package x
interface Foo<A>
class GeneratedClass
class Bar : Foo<GeneratedClass>
The issue I’m having is that
addSyntheticSupertypes
happens before
GeneratedClass
has a valid
ClasDescriptor
so when I add the supertype I get:
Copy code
Bar : Foo<[ERROR : Unsubstituted type for <ERROR CLASS>]>

e: java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Cause: Error type encountered: [ERROR : Unsubstituted type for <ERROR CLASS>] (ErrorType).
How can I generate a valid descriptor in that phase for
GeneratedClass
or how can I add a supertype to a class given the class the type refers to may not have been generated yet? Is this the wrong phase to do this kind of work?
d
How do you generate
GeneratedClass
?
r
In the
generateSyntheticClasses
overload that takes first the
PackageFragmentDescriptor
with something like:
Copy code
fun PackageFragmentDescriptor.kindMarker(ctx: LazyClassContext, target: ClassDescriptor): ClassDescriptor =
  ClassDescriptorImpl(
    containingDeclaration,
    target.markerName.shortName(),
    Modality.FINAL,
    ClassKind.CLASS,
    emptyList<KotlinType>(),
    SourceElement.NO_SOURCE,
    false,
    ctx.storageManager
  )
Not sure if there is anything extra I have to do, I add that descriptor to the
result: MutableSet<ClassDescriptor>
which is passed to me in
generateSyntheticClasses
d
Hm, that’s seems reasonable for me. And how do you find the generated descriptor in the
addSyntheticSupertypes
? Is it possible to see the actual code?
r
I’m using :
Copy code
someOtherClassDescriptor.module.resolveClassByFqName(GeneratedClassName, NoLookupLocation.FROM_BACKEND)
@dsavvinov if that doesn’t look suspicious I can setup a small plugin on a public repo that better illustrates the issue. Also thanks for you help 🙂
d
Yeah, I don’t know that the exactly correct way to do it, but it doesn’t look overly suspicious for me, and I’d probably do the same at first. The only thing I’d re-check is that, quite obviously, you should add synthetic descriptor to the
packageFragmentDescriptor
of the module which you later query in
addSyntheticSupertypes
(but most probably you’ve checked that already)
r
That does not seem to be possible based on what I’m seeing because
addSynthetiClasses
which is where one can access the
packageFragmentDescriptor
is invoked after
addSyntheticSupertypes
. I could create a valid
ClassDescriptor
inside
addSyntheticSupertypes
if I get access to a
StorageManager
. For what I can see the storage manager which is a requirement in
ClassDescriptorImpl
is not available because is private in the KotlinBuiltIns and other objects that reference it. Can I access the StorageManager as global service and request it wherever needed?
I was able to create a descriptor with:
Copy code
ClassDescriptorImpl(
  descriptor.parents.first(),
  Name("GeneratedClass"),
  Modality.FINAL,
  ClassKind.CLASS,
  emptyList<KotlinType>(),
  SourceElement.NO_SOURCE,
  false,
  LockBasedStorageManager.NO_LOCKS
) {
  override fun getUnsubstitutedMemberScope(): MemberScope = MemberScope.Empty
  override fun getConstructors(): Collection<ClassConstructorDescriptor> = emptyList()
}
I had to override those two methods so it would not blow up. The issue I see now is that
GeneratedClass
is in the metadata properly in the bytecode but no actual class is generated since
Class.forName("sample.GeneratedClass")
blows up. I suppose I’m missing the IR generation step. Is there an example somewhere that shows how to generate a marker simple class with no methods in the IR backend?
Any ideas as to what I’m missing? I’m currently overriding
generateSyntheticClasses(PackageFramentProvider, ....)
,
addSyntheticSupertypes
and doing all the IR generation for the class with transformDeclarationsFlat. Do I also need to add the class to the package declaration somehow?
k
Do you specify the descriptor of the
GeneratedClass
in the
PackageFragmentProvider
of the sample package via the
PackageFragmentProviderExtension
? Thats what I am doing and it worked out quite well for me. Though I'm not sure whether it's available in IR.
r
@kralli yes and just changed from a ClassDescriptorImpl to SyntheticClassOrObjectDescriptor just in case but its constructor requieres a KtPureClassorObject which I'm not sure how to get in that phase
Actually I take it back it's in the synthetic resolver extension I was doing that but will try that extension thanks !