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:
@@ -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) {
|
||||
|
||||
Vendored
+8
-6
@@ -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
|
||||
|
||||
+8
-3
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user