KT-13426: store map from ImplicitReceiver into KotlinType for implicit receiver smart casts

This commit is contained in:
Mikhail Glukhikh
2016-08-15 17:17:18 +03:00
parent 33e96fcb9a
commit cbcef67d82
15 changed files with 265 additions and 8 deletions
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.calls.smartcasts.ImplicitSmartCasts;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
@@ -144,7 +145,7 @@ public interface BindingContext {
WritableSlice<KtExpression, KotlinType> SMARTCAST = Slices.createSimpleSlice();
WritableSlice<KtExpression, Boolean> SMARTCAST_NULL = Slices.createSimpleSlice();
WritableSlice<KtExpression, KotlinType> IMPLICIT_RECEIVER_SMARTCAST = Slices.createSimpleSlice();
WritableSlice<KtExpression, ImplicitSmartCasts> IMPLICIT_RECEIVER_SMARTCAST = new BasicWritableSlice<KtExpression, ImplicitSmartCasts>(DO_NOTHING);
WritableSlice<KtWhenExpression, Boolean> EXHAUSTIVE_WHEN = Slices.createSimpleSlice();
WritableSlice<KtWhenExpression, Boolean> IMPLICIT_EXHAUSTIVE_WHEN = Slices.createSimpleSlice();
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.smartcasts
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.types.KotlinType
data class ImplicitSmartCasts private constructor(val receiverTypes: Map<ImplicitReceiver, KotlinType>) {
operator fun plus(other: ImplicitSmartCasts) = ImplicitSmartCasts(receiverTypes + other.receiverTypes)
constructor(receiver: ImplicitReceiver, type: KotlinType): this(mapOf(receiver to type))
}
@@ -20,12 +20,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors.SMARTCAST_IMPOSSIBLE
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.IMPLICIT_RECEIVER_SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeIntersector
@@ -155,7 +156,14 @@ class SmartCastManager {
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, recordExpressionType)
}
else if (calleeExpression != null && dataFlowValue.isStable) {
c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression, possibleType)
val receiver = (dataFlowValue.identifierInfo as? IdentifierInfo.Receiver)?.value
if (receiver is ImplicitReceiver) {
val oldSmartCasts = c.trace[IMPLICIT_RECEIVER_SMARTCAST, calleeExpression]
val newSmartCasts = ImplicitSmartCasts(receiver, possibleType)
c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression,
oldSmartCasts?.let { it + newSmartCasts } ?: newSmartCasts)
}
}
return SmartCastResult(possibleType, dataFlowValue.isStable)
}