Change resolution scope for componentX in lambda parameters

Component-functions are resolved in the same scope as the first statement of the lambda, but lambda receiver was not available

 #KT-14692 Fixed
This commit is contained in:
Denis Zharkov
2016-11-09 18:10:17 +03:00
parent 6656bf835f
commit 24819a079b
5 changed files with 53 additions and 20 deletions
@@ -263,9 +263,9 @@ public class DescriptorResolver {
@NotNull
public ValueParameterDescriptorImpl resolveValueParameterDescriptor(
@NotNull LexicalScope scope, @NotNull FunctionDescriptor owner,
@NotNull final LexicalScope scope, @NotNull final FunctionDescriptor owner,
@NotNull KtParameter valueParameter, int index,
@NotNull KotlinType type, @NotNull BindingTrace trace
@NotNull final KotlinType type, @NotNull final BindingTrace trace
) {
KotlinType varargElementType = null;
KotlinType variableType = type;
@@ -291,20 +291,35 @@ public class DescriptorResolver {
}
}
KtDestructuringDeclaration destructuringDeclaration = valueParameter.getDestructuringDeclaration();
final KtDestructuringDeclaration destructuringDeclaration = valueParameter.getDestructuringDeclaration();
List<VariableDescriptor> destructuringVariables;
Function0<List<VariableDescriptor>> destructuringVariables;
if (destructuringDeclaration != null) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.DestructuringLambdaParameters)) {
trace.report(Errors.UNSUPPORTED_FEATURE.on(valueParameter, LanguageFeature.DestructuringLambdaParameters));
}
destructuringVariables = destructuringDeclarationResolver.resolveLocalVariablesFromDestructuringDeclaration(
scope, destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
ExpressionTypingContext.newContext(trace, scope, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE)
);
destructuringVariables = new Function0<List<VariableDescriptor>>() {
@Override
public List<VariableDescriptor> invoke() {
assert owner.getDispatchReceiverParameter() == null
: "Destructuring declarations are only be parsed for lambdas, and they must not have a dispatch receiver";
LexicalScope scopeWithReceiver =
ScopeUtilsKt.addImplicitReceiver(scope, owner.getExtensionReceiverParameter());
modifiersChecker.withTrace(trace).checkModifiersForDestructuringDeclaration(destructuringDeclaration);
List<VariableDescriptor> result =
destructuringDeclarationResolver.resolveLocalVariablesFromDestructuringDeclaration(
scope,
destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
ExpressionTypingContext.newContext(
trace, scopeWithReceiver, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE
)
);
modifiersChecker.withTrace(trace).checkModifiersForDestructuringDeclaration(destructuringDeclaration);
return result;
}
};
}
else {
destructuringVariables = null;
@@ -22,10 +22,13 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.serialization.ProtoBuf;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeConstructor;
import org.jetbrains.kotlin.types.TypeProjection;
import java.util.Collection;
@@ -71,6 +74,9 @@ public class ForceResolveUtil {
LazyEntity lazyEntity = (LazyEntity) object;
lazyEntity.forceResolveAllContents();
}
else if (object instanceof ValueParameterDescriptorImpl.WithDestructuringDeclaration) {
((ValueParameterDescriptorImpl.WithDestructuringDeclaration) object).getDestructuringVariables();
}
else if (object instanceof CallableDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) object;
ReceiverParameterDescriptor parameter = callableDescriptor.getExtensionReceiverParameter();
@@ -201,6 +201,11 @@ fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): L
return LexicalScopeWrapper(this, newImportingScopeChain)
}
fun LexicalScope.addImplicitReceiver(newReceiver: ReceiverParameterDescriptor?): LexicalScope {
if (newReceiver == null) return this
return LexicalScopeImpl(parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, newReceiver, kind)
}
private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingScopeChain: ImportingScope): LexicalScope by delegate {
init {
assert(delegate !is LexicalScopeWrapper) {
@@ -30,15 +30,17 @@ fun bar() {
b checkType { _<String>() }
}
// From KEEP: Component-functions are resolved in the scope that contains the lambda
foobaz { (<!COMPONENT_FUNCTION_MISSING, UNUSED_DESTRUCTURED_PARAMETER_ENTRY!>a<!>, <!COMPONENT_FUNCTION_MISSING, UNUSED_DESTRUCTURED_PARAMETER_ENTRY!>b<!>) ->
// From KEEP: Component-functions are resolved in the same scope as the first statement of the lambda
foobaz { (a, b) ->
a checkType { _<Double>() }
b checkType { _<Char>() }
}
// From KEEP: Component-functions are resolved in the scope that contains the lambda
// So `component1`/`component2` for lambda parameters were resolved to the top-level extensions
// From KEEP: Component-functions are resolved in the same scope as the first statement of the lambda
// So `component1`/`component2` for lambda parameters were resolved to member extensions
foobar { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
a checkType { _<Double>() }
b checkType { _<Char>() }
}
// the following code fails with exception, see KT-13873
@@ -53,7 +53,7 @@ open class ValueParameterDescriptorImpl(
isCrossinline: Boolean,
isNoinline: Boolean, isCoroutine: Boolean, varargElementType: KotlinType?,
source: SourceElement,
destructuringVariables: List<VariableDescriptor>?
destructuringVariables: (() -> List<VariableDescriptor>)?
): ValueParameterDescriptorImpl =
if (destructuringVariables == null)
ValueParameterDescriptorImpl(containingDeclaration, original, index, annotations, name, outType,
@@ -74,11 +74,16 @@ open class ValueParameterDescriptorImpl(
isCrossinline: Boolean,
isNoinline: Boolean, isCoroutine: Boolean, varargElementType: KotlinType?,
source: SourceElement,
val destructuringVariables: List<VariableDescriptor>
destructuringVariables: () -> List<VariableDescriptor>
) : ValueParameterDescriptorImpl(
containingDeclaration, original, index, annotations, name, outType, declaresDefaultValue,
isCrossinline, isNoinline, isCoroutine,
varargElementType, source)
varargElementType, source) {
// It's forced to be lazy because its resolution depends on receiver of relevant lambda, that is being created at the same moment
// as value parameters.
// Must be forced via ForceResolveUtil.forceResolveAllContents()
val destructuringVariables by lazy(destructuringVariables)
}
private val original: ValueParameterDescriptor = original ?: this