@@ -58,9 +58,11 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
58
58
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
59
59
import org.jetbrains.kotlin.types.typeUtil.makeNullable
60
60
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
61
+ import org.jetbrains.kotlin.utils.yieldIfNotNull
61
62
import java.lang.UnsupportedOperationException
62
63
import java.util.*
63
64
import javax.inject.Inject
65
+ import kotlin.coroutines.experimental.buildSequence
64
66
65
67
sealed class DoubleColonLHS (val type : KotlinType ) {
66
68
/* *
@@ -626,15 +628,18 @@ class DoubleColonExpressionResolver(
626
628
}
627
629
}
628
630
631
+ private class ResolutionResultsAndTraceCommitCallback (
632
+ val results : OverloadResolutionResults <CallableDescriptor >,
633
+ val commitTrace : () -> Unit
634
+ )
635
+
629
636
private fun tryResolveRHSWithReceiver (
630
637
traceTitle : String ,
631
638
receiver : Receiver ? ,
632
639
reference : KtSimpleNameExpression ,
633
640
outerContext : ResolutionContext <* >,
634
641
resolutionMode : ResolveArgumentsMode
635
- ): OverloadResolutionResults <CallableDescriptor >? {
636
- checkReservedYield(reference, outerContext.trace)
637
-
642
+ ): ResolutionResultsAndTraceCommitCallback ? {
638
643
// we should preserve information about `call` because callable references are analyzed two times,
639
644
// otherwise there will be not completed calls in trace
640
645
val call = outerContext.trace[BindingContext .CALL , reference] ? : CallMaker .makeCall(reference, receiver, null , reference, emptyList())
@@ -652,12 +657,15 @@ class DoubleColonExpressionResolver(
652
657
reference, BasicCallResolutionContext .create(newContext, call, CheckArgumentTypesMode .CHECK_CALLABLE_TYPE )
653
658
)
654
659
655
- val shouldCommitTrace =
656
- if (resolutionMode == ResolveArgumentsMode .SHAPE_FUNCTION_ARGUMENTS ) resolutionResults.isSingleResult
657
- else ! resolutionResults.isNothing
658
- if (shouldCommitTrace) temporaryTrace.commit()
659
-
660
- return if (resolutionResults.isNothing) null else resolutionResults
660
+ return when {
661
+ resolutionResults.isNothing -> null
662
+ else -> ResolutionResultsAndTraceCommitCallback (resolutionResults) {
663
+ checkReservedYield(reference, outerContext.trace)
664
+ if (resolutionMode != ResolveArgumentsMode .SHAPE_FUNCTION_ARGUMENTS || resolutionResults.isSingleResult) {
665
+ temporaryTrace.commit()
666
+ }
667
+ }
668
+ }
661
669
}
662
670
663
671
private fun resolveCallableReferenceRHS (
@@ -668,52 +676,71 @@ class DoubleColonExpressionResolver(
668
676
): OverloadResolutionResults <CallableDescriptor >? {
669
677
val reference = expression.callableReference
670
678
671
- val lhsType = lhs?.type ? :
672
- return tryResolveRHSWithReceiver(" resolve callable reference with empty LHS" , null , reference, c, mode)
679
+ val lhsType =
680
+ lhs?.type ? :
681
+ return tryResolveRHSWithReceiver(" resolve callable reference with empty LHS" , null , reference, c, mode)
682
+ ?.apply { commitTrace() }?.results
673
683
674
- when (lhs) {
675
- is DoubleColonLHS .Type -> {
676
- val classifier = lhsType.constructor .declarationDescriptor
677
- if (classifier !is ClassDescriptor ) {
678
- c.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS .on(expression))
679
- return null
680
- }
684
+ val resultSequence = buildSequence {
685
+ when (lhs) {
686
+ is DoubleColonLHS .Type -> {
687
+ val classifier = lhsType.constructor .declarationDescriptor
688
+ if (classifier !is ClassDescriptor ) {
689
+ c.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS .on(expression))
690
+ return @buildSequence
691
+ }
681
692
682
- val qualifier = c.trace.get(BindingContext .QUALIFIER , expression.receiverExpression!! )
683
- if (qualifier is ClassQualifier ) {
684
- val possibleStatic = tryResolveRHSWithReceiver(
685
- " resolve unbound callable reference in static scope" , qualifier, reference, c, mode
693
+ val qualifier = c.trace.get(BindingContext .QUALIFIER , expression.receiverExpression!! )
694
+ if (qualifier is ClassQualifier ) {
695
+ yieldIfNotNull(
696
+ tryResolveRHSWithReceiver(
697
+ " resolve unbound callable reference in static scope" , qualifier, reference, c, mode
698
+ )
699
+ )
700
+ }
701
+
702
+ yieldIfNotNull(
703
+ tryResolveRHSWithReceiver(
704
+ " resolve unbound callable reference with receiver" , TransientReceiver (lhsType), reference, c, mode
705
+ )
686
706
)
687
- if (possibleStatic != null ) return possibleStatic
688
707
}
708
+ is DoubleColonLHS .Expression -> {
709
+ val expressionReceiver = ExpressionReceiver .create(expression.receiverExpression!! , lhsType, c.trace.bindingContext)
710
+ yieldIfNotNull(
711
+ tryResolveRHSWithReceiver(
712
+ " resolve bound callable reference" , expressionReceiver, reference, c, mode
713
+ )
714
+ )
689
715
690
- val possibleWithReceiver = tryResolveRHSWithReceiver(
691
- " resolve unbound callable reference with receiver" , TransientReceiver (lhsType), reference, c, mode
692
- )
693
- if (possibleWithReceiver != null ) return possibleWithReceiver
694
- }
695
- is DoubleColonLHS .Expression -> {
696
- val expressionReceiver = ExpressionReceiver .create(expression.receiverExpression!! , lhsType, c.trace.bindingContext)
697
- val result = tryResolveRHSWithReceiver(
698
- " resolve bound callable reference" , expressionReceiver, reference, c, mode
699
- )
700
- if (result != null ) return result
701
-
702
- if (lhs.isObjectQualifier) {
703
- val classifier = lhsType.constructor .declarationDescriptor
704
- val calleeExpression = expression.receiverExpression?.getCalleeExpressionIfAny()
705
- if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor ) {
706
- val qualifier = ClassQualifier (calleeExpression, classifier)
707
- val possibleStatic = tryResolveRHSWithReceiver(
708
- " resolve object callable reference in static scope" , qualifier, reference, c, mode
709
- )
710
- if (possibleStatic != null ) return possibleStatic
716
+ if (lhs.isObjectQualifier) {
717
+ val classifier = lhsType.constructor .declarationDescriptor
718
+ val calleeExpression = expression.receiverExpression?.getCalleeExpressionIfAny()
719
+ if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor ) {
720
+ val qualifier = ClassQualifier (calleeExpression, classifier)
721
+ yieldIfNotNull(
722
+ tryResolveRHSWithReceiver(
723
+ " resolve object callable reference in static scope" , qualifier, reference, c, mode
724
+ )
725
+ )
726
+ }
711
727
}
712
728
}
713
729
}
714
730
}
715
731
716
- return null
732
+ // TODO: Maybe it makes sense to report all results when all of them are unsuccessful (NONE_APPLICABLE or something like this)
733
+ var resultToCommit: ResolutionResultsAndTraceCommitCallback ? = null
734
+ for (result in resultSequence) {
735
+ resultToCommit = result
736
+ if (result.results.isSuccess) {
737
+ break
738
+ }
739
+ }
740
+ return resultToCommit?.let {
741
+ it.commitTrace()
742
+ it.results
743
+ }
717
744
}
718
745
719
746
companion object {
0 commit comments