Hi, I’m trying to find the service or code in the ...
# compiler
r
Hi, I’m trying to find the service or code in the compiler sources responsible to check a given
FunctionDescriptor
that points to something like:
Copy code
fun <A> A.show(): String = toString()
is a valid candidate to be applied in the expression
Copy code
val s: String = 1.show()
When I have
A
and
Int
as `KotlinType`s and I ask if
Int
is a subtype of
A
it always says no despite being a generic type. This makes sense since it could refer to any other type. What service does the Kotlin compiler use to see if a generic function is in bounds or applicable to a type? Any help is appreciated, thanks.
d
Hello. It's part of resolution and infrenence You can take a look to file
ResolutionParts.kt
where defined all checks that resolve applies to some candidate when it resolves some call
r
Thank you so much @dmitriy.novozhilov!
I looked into the whole call resolution stack but in all places I'm required to have a Psi Call. What I have now it's just a list of FunctionDescriptor and 2 KotlinTypes, a receiver and a return type. All functions have the same shape: A -> B But I have no psi call. What I'm trying to determine if the any of those functions are valid candidates for that conversion. Should I create a fake Psi Call somehow or is there a way to do this on resolution without PSI? Thanks!
d
You can not run resolution without psi call, because of resolution resolves some call, and all calls are based o psi But in your example you have psi call (
1.show()
), or I misunderstand your problem?
r
I have the
FunctionDescriptor
for:
Copy code
fun <A, B> <http://A.to|A.to>(): B = TODO()
And I want to know if two `KotlinType`s are applicable to that FunctionDescriptor. I could get the PSI out of the
FunctionDescriptor
but that is not the Psi for the Call unless I could construct a fake call for it.
So for example in this case:
Int
and
String
are fine because the function is fully polymorphic but if I ask with the
KotlinTypeChecker
if
Int : A
it yields false because it’s a type argument. Given it’s not one function but a List of functions I need to run over to find a candidate I thought I could do this with resolution but at this point I have no PSI call because what I’m trying to proof is to check if the function descriptor is applicable to those two types one being the receiver and the other the return type. In this case it should have been applicable since this is a universal polymorphic function for all A and B but using the type checker to check for a match isn’t enough. I also tried this:
Copy code
val appliedConversion = conversion.substituteAndApproximateCapturedTypes(
            NewTypeSubstitutorByConstructorMap(listOfNotNull(fromSub, toSub).toMap()),
            TypeApproximator(conversion.module.builtIns)
          )
to get an approximate version of the function I could use to apply but then it complains that the descriptor is not referenced because all its internal point to a descriptor that is not in the binding trace. And at this point I figured there is an easier way and I’m trying to come up with something which currently is garbage but goes in this direction… Does not compile:
Copy code
fun FunctionDescriptor.applyProof2(
        session: ResolveSession,
        subType: KotlinType,
        superType: KotlinType
      ): OverloadResolutionResults<FunctionDescriptor> {
        val call: Call = TODO() //how to get this
        val extensionReceiver = ExtensionReceiver(this, subType, null)
        val newCall = ResolvedCallImpl(
          call,
          this,
          null, extensionReceiver, ExplicitReceiverKind.EXTENSION_RECEIVER,
          null, DelegatingBindingTrace(BindingTraceContext().bindingContext, "Temporary trace for unwrapped suspension function"),
          TracingStrategy.EMPTY, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
        )
        val functionScope = session.declarationScopeProvider.getResolutionScopeForDeclaration(call) // TODO get the PSI
        val innerScope = FunctionDescriptorUtil.getFunctionInnerScope(functionScope, this, session.trace, OverloadChecker(TypeSpecificityComparator.NONE))
        return componentProvider.get<PSICallResolver>().runResolutionAndInferenceForGivenCandidates(
          context = BasicCallResolutionContext.create(
            ... ///TODO not sure how to bring these instances to life here
        )
        resolutionCandidates = proofs.values.map { ResolutionCandidate.create(call, it) },
        tracingStrategy = TracingStrategy.EMPTY
        )
      }
d
I understand There is no such API, but at a first glance it's a very simple problem You need just check that all your types are subtypes of receiver/argument/return type If some of them are type parameters, you should check for all its upper bounds (see
TypeParameterDescriptor.getUpperBounds()
)
r
Oh, thanks that makes perfect sense. I will try that. Thanks for your help @dmitriy.novozhilov
👍 1
i
There are also a few helpers I added for
KotlinType
regarding Descriptors. Maybe they are somehow helpful for you @raulraja https://github.com/arrow-kt/arrow-meta/blob/46db55089d1713d8be88d3beb7888d2c85f929f5/idea-plugin/src/main/kotlin/arrow/meta/ide/dsl/editor/inspection/InspectionUtilitySyntax.kt#L52 I wish I could be of more help 🙂
👍 1