Humanize type mismatch diagnostic caused by type projections
#KT-10581 Fixed
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker.VarianceConflictDiagnosticData;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -714,6 +715,8 @@ public interface Errors {
|
||||
// Type mismatch
|
||||
|
||||
DiagnosticFactory2<KtExpression, KotlinType, KotlinType> TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtElement, TypeMismatchDueToTypeProjectionsData> TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, CallableDescriptor, KotlinType> MEMBER_PROJECTED_OUT = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, KotlinType> RETURN_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, KotlinType> EXPECTED_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtBinaryExpression, KotlinType> ASSIGNMENT_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||
@@ -785,6 +788,9 @@ public interface Errors {
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> MUST_BE_INITIALIZED_DIAGNOSTICS = ImmutableSet.of(
|
||||
MUST_BE_INITIALIZED, MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
);
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> TYPE_MISMATCH_ERRORS = ImmutableSet.of(
|
||||
TYPE_MISMATCH, CONSTANT_EXPECTED_TYPE_MISMATCH, NULL_FOR_NONNULL_TYPE, TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS,
|
||||
MEMBER_PROJECTED_OUT);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableNothing
|
||||
|
||||
fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
|
||||
expression: KtElement,
|
||||
expectedType: KotlinType,
|
||||
expressionType: KotlinType?
|
||||
): Boolean {
|
||||
if (!TypeUtils.containsSpecialType(expectedType) { it.isAnyOrNullableAny() || it.isNothing() || it.isNullableNothing() }) return false
|
||||
|
||||
val callPosition = this.callPosition
|
||||
val (resolvedCall, correspondingNotApproximatedTypeByDescriptor: (CallableDescriptor) -> KotlinType?) = when (callPosition) {
|
||||
is CallPosition.ValueArgumentPosition -> Pair(
|
||||
callPosition.resolvedCall, {
|
||||
f: CallableDescriptor ->
|
||||
getEffectiveExpectedType(f.valueParameters[callPosition.valueParameter.index], callPosition.valueArgument)
|
||||
})
|
||||
is CallPosition.ExtensionReceiverPosition -> Pair(
|
||||
callPosition.resolvedCall, {
|
||||
f: CallableDescriptor ->
|
||||
f.extensionReceiverParameter?.type
|
||||
})
|
||||
is CallPosition.PropertyAssignment -> Pair(
|
||||
callPosition.leftPart.getResolvedCall(trace.bindingContext) ?: return false, {
|
||||
f: CallableDescriptor ->
|
||||
(f as? PropertyDescriptor)?.setter?.valueParameters?.get(0)?.type
|
||||
})
|
||||
is CallPosition.Unknown -> return false
|
||||
}
|
||||
|
||||
val receiverType = resolvedCall.dispatchReceiver?.type ?: return false
|
||||
val callableDescriptor = resolvedCall.resultingDescriptor.original
|
||||
|
||||
val substitutedDescriptor =
|
||||
TypeConstructorSubstitution
|
||||
.create(receiverType)
|
||||
.wrapWithCapturingSubstitution(needApproximation = false)
|
||||
.buildSubstitutor().let { callableDescriptor.substitute(it) } ?: return false
|
||||
|
||||
val nonApproximatedExpectedType = correspondingNotApproximatedTypeByDescriptor(substitutedDescriptor) ?: return false
|
||||
if (!TypeUtils.containsSpecialType(nonApproximatedExpectedType) { it.isCaptured() }) return false
|
||||
|
||||
if (expectedType.isNothing()) {
|
||||
if (callPosition is CallPosition.PropertyAssignment) {
|
||||
trace.report(Errors.SETTER_PROJECTED_OUT.on(callPosition.leftPart ?: return false, resolvedCall.resultingDescriptor))
|
||||
}
|
||||
else {
|
||||
val call = resolvedCall.call
|
||||
val reportOn =
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall)
|
||||
resolvedCall.variableCall.call.calleeExpression
|
||||
else
|
||||
call.calleeExpression
|
||||
|
||||
trace.reportDiagnosticOnce(Errors.MEMBER_PROJECTED_OUT.on(reportOn ?: call.callElement, callableDescriptor, receiverType))
|
||||
}
|
||||
}
|
||||
else {
|
||||
// expressionType can be null when reporting CONSTANT_EXPECTED_TYPE_MISMATCH (see addAll.kt test)
|
||||
expressionType ?: return false
|
||||
trace.report(
|
||||
Errors.TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS.on(
|
||||
expression, TypeMismatchDueToTypeProjectionsData(
|
||||
expectedType, expressionType, receiverType, callableDescriptor)))
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun BindingTrace.reportDiagnosticOnce(diagnostic: Diagnostic) {
|
||||
if (bindingContext.diagnostics.forElement(diagnostic.psiElement).any { it.factory == diagnostic.factory }) return
|
||||
|
||||
report(diagnostic)
|
||||
}
|
||||
|
||||
class TypeMismatchDueToTypeProjectionsData(
|
||||
val expectedType: KotlinType,
|
||||
val expressionType: KotlinType,
|
||||
val receiverType: KotlinType,
|
||||
val callableDescriptor: CallableDescriptor
|
||||
)
|
||||
+17
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.diagnostics.TypeMismatchDueToTypeProjectionsData;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
||||
import org.jetbrains.kotlin.psi.KtTypeConstraint;
|
||||
@@ -126,6 +127,22 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ACCESSOR_PARAMETER_NAME_SHADOWING, "Accessor parameter name 'field' is shadowed by backing field variable");
|
||||
|
||||
MAP.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE);
|
||||
MAP.put(TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS,
|
||||
"Type mismatch: inferred type is {1} but {0} was expected. Projected type {2} restricts use of {3}",
|
||||
new MultiRenderer<TypeMismatchDueToTypeProjectionsData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String[] render(@NotNull TypeMismatchDueToTypeProjectionsData object) {
|
||||
return new String[] {
|
||||
RENDER_TYPE.render(object.getExpectedType()),
|
||||
RENDER_TYPE.render(object.getExpressionType()),
|
||||
RENDER_TYPE.render(object.getReceiverType()),
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.render(object.getCallableDescriptor())
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
MAP.put(MEMBER_PROJECTED_OUT, "Out-projected type ''{1}'' prohibits the use of ''{0}''", DescriptorRenderer.FQ_NAMES_IN_TYPES, RENDER_TYPE);
|
||||
MAP.put(INCOMPATIBLE_MODIFIERS, "Modifier ''{0}'' is incompatible with ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING);
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariabl
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||
@@ -68,7 +69,6 @@ class CallCompleter(
|
||||
// for the case 'foo(a)' where 'foo' is a variable, the call 'foo.invoke(a)' shouldn't be completed separately,
|
||||
// it's completed when the outer (variable as function call) is completed
|
||||
if (!isInvokeCallOnVariable(context.call)) {
|
||||
|
||||
val temporaryTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a resulting call")
|
||||
|
||||
completeResolvedCallAndArguments(resolvedCall, results, context.replaceBindingTrace(temporaryTrace), tracing)
|
||||
@@ -222,7 +222,7 @@ class CallCompleter(
|
||||
candidateDescriptor, constraintSystem!!, valueArgumentsCheckingResult.argumentTypes,
|
||||
receiverType, context.expectedType, context.call
|
||||
)
|
||||
tracing.typeInferenceFailed(context.trace, errorData)
|
||||
tracing.typeInferenceFailed(context, errorData)
|
||||
|
||||
addStatus(ResolutionStatus.OTHER_ERROR)
|
||||
}
|
||||
@@ -247,11 +247,16 @@ class CallCompleter(
|
||||
|
||||
for (valueArgument in context.call.valueArguments) {
|
||||
val argumentMapping = getArgumentMapping(valueArgument!!)
|
||||
val expectedType = when (argumentMapping) {
|
||||
is ArgumentMatch -> getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument)
|
||||
else -> TypeUtils.NO_EXPECTED_TYPE
|
||||
val (expectedType, callPosition) = when (argumentMapping) {
|
||||
is ArgumentMatch -> Pair(
|
||||
getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument),
|
||||
CallPosition.ValueArgumentPosition(results.resultingCall, argumentMapping.valueParameter, valueArgument))
|
||||
else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown)
|
||||
}
|
||||
val newContext = context.replaceDataFlowInfo(getDataFlowInfoForArgument(valueArgument)).replaceExpectedType(expectedType)
|
||||
val newContext =
|
||||
context.replaceDataFlowInfo(getDataFlowInfoForArgument(valueArgument))
|
||||
.replaceExpectedType(expectedType)
|
||||
.replaceCallPosition(callPosition)
|
||||
completeOneArgument(valueArgument, newContext)
|
||||
}
|
||||
}
|
||||
@@ -306,7 +311,7 @@ class CallCompleter(
|
||||
val (cachedResolutionResults, cachedContext, tracing) = cachedData
|
||||
|
||||
val contextForArgument = cachedContext.replaceBindingTrace(context.trace)
|
||||
.replaceExpectedType(context.expectedType).replaceCollectAllCandidates(false)
|
||||
.replaceExpectedType(context.expectedType).replaceCollectAllCandidates(false).replaceCallPosition(context.callPosition)
|
||||
|
||||
return completeCall(contextForArgument, cachedResolutionResults, tracing)
|
||||
}
|
||||
|
||||
@@ -449,7 +449,9 @@ class CandidateResolver(
|
||||
receiverArgument, receiverParameter.type, this)
|
||||
|
||||
if (!isSubtypeBySmartCastIgnoringNullability) {
|
||||
tracing.wrongReceiverType(trace, receiverParameter, receiverArgument)
|
||||
tracing.wrongReceiverType(
|
||||
trace, receiverParameter, receiverArgument,
|
||||
this.replaceCallPosition(CallPosition.ExtensionReceiverPosition(candidateCall)))
|
||||
return OTHER_ERROR
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -42,10 +42,11 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -62,7 +63,8 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
) {
|
||||
return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
new ResolutionResultsCacheImpl(), null,
|
||||
callChecker, StatementFilter.NONE, isAnnotationContext, false);
|
||||
callChecker, StatementFilter.NONE, isAnnotationContext, false,
|
||||
CallPosition.Unknown.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -74,7 +76,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, context.contextDependency, checkArguments,
|
||||
context.resolutionResultsCache, dataFlowInfoForArguments,
|
||||
context.callChecker,
|
||||
context.statementFilter, context.isAnnotationContext, context.collectAllCandidates);
|
||||
context.statementFilter, context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -93,18 +95,19 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BasicCallResolutionContext replaceCall(@NotNull Call newCall) {
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
public void performContextDependentCallChecks(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
|
||||
+9
-6
@@ -58,11 +58,12 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
@Nullable Receiver explicitExtensionReceiverForInvoke,
|
||||
@NotNull CandidateResolveMode candidateResolveMode,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
this.candidateCall = candidateCall;
|
||||
this.tracing = tracing;
|
||||
this.explicitExtensionReceiverForInvoke = explicitExtensionReceiverForInvoke;
|
||||
@@ -79,7 +80,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
context.dataFlowInfo, context.contextDependency, context.checkArguments,
|
||||
context.resolutionResultsCache, context.dataFlowInfoForArguments,
|
||||
context.callChecker, context.statementFilter, explicitExtensionReceiverForInvoke,
|
||||
candidateResolveMode, context.isAnnotationContext, context.collectAllCandidates);
|
||||
candidateResolveMode, context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -90,7 +91,8 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
candidateCall, tracing, context.trace, context.scope, context.call, context.expectedType,
|
||||
context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache,
|
||||
context.dataFlowInfoForArguments, context.callChecker, context.statementFilter,
|
||||
null, CandidateResolveMode.FULLY, context.isAnnotationContext, context.collectAllCandidates);
|
||||
null, CandidateResolveMode.FULLY, context.isAnnotationContext, context.collectAllCandidates,
|
||||
context.callPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,11 +104,12 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
return new CallCandidateResolutionContext<D>(
|
||||
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
resolutionResultsCache, dataFlowInfoForArguments, callChecker, statementFilter,
|
||||
explicitExtensionReceiverForInvoke, candidateResolveMode, isAnnotationContext, collectAllCandidates);
|
||||
explicitExtensionReceiverForInvoke, candidateResolveMode, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.context
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
|
||||
sealed class CallPosition {
|
||||
object Unknown : CallPosition()
|
||||
|
||||
class ExtensionReceiverPosition(val resolvedCall: ResolvedCall<*>) : CallPosition()
|
||||
|
||||
class ValueArgumentPosition(
|
||||
val resolvedCall: ResolvedCall<*>,
|
||||
val valueParameter: ValueParameterDescriptor,
|
||||
val valueArgument: ValueArgument
|
||||
) : CallPosition()
|
||||
|
||||
class PropertyAssignment(val leftPart: KtExpression?) : CallPosition()
|
||||
}
|
||||
+3
-2
@@ -50,10 +50,11 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache, callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
this.call = call;
|
||||
this.checkArguments = checkArguments;
|
||||
if (dataFlowInfoForArguments != null) {
|
||||
|
||||
+22
-10
@@ -54,6 +54,9 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
|
||||
public final boolean collectAllCandidates;
|
||||
|
||||
@NotNull
|
||||
public final CallPosition callPosition;
|
||||
|
||||
protected ResolutionContext(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull LexicalScope scope,
|
||||
@@ -64,7 +67,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
this.trace = trace;
|
||||
this.scope = scope;
|
||||
@@ -76,6 +80,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
this.statementFilter = statementFilter;
|
||||
this.isAnnotationContext = isAnnotationContext;
|
||||
this.collectAllCandidates = collectAllCandidates;
|
||||
this.callPosition = callPosition;
|
||||
}
|
||||
|
||||
protected abstract Context create(
|
||||
@@ -86,7 +91,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
);
|
||||
|
||||
@NotNull
|
||||
@@ -99,14 +105,14 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
public Context replaceBindingTrace(@NotNull BindingTrace trace) {
|
||||
if (this.trace == trace) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
|
||||
if (newDataFlowInfo == dataFlowInfo) return self();
|
||||
return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -114,28 +120,28 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
if (expectedType == newExpectedType) return self();
|
||||
return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceScope(@NotNull LexicalScope newScope) {
|
||||
if (newScope == scope) return self();
|
||||
return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
|
||||
if (newContextDependency == contextDependency) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
|
||||
if (newResolutionResultsCache == resolutionResultsCache) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -146,12 +152,18 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull
|
||||
public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
newCollectAllCandidates);
|
||||
newCollectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates);
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceCallPosition(@NotNull CallPosition callPosition) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-10
@@ -21,6 +21,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -29,13 +30,13 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.Variance;
|
||||
@@ -80,13 +81,19 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument) {
|
||||
if (receiverArgument instanceof ExpressionReceiver) {
|
||||
ExpressionReceiver expressionReceiver = (ExpressionReceiver)receiverArgument;
|
||||
trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
|
||||
}
|
||||
else {
|
||||
trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
|
||||
public void wrongReceiverType(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ReceiverParameterDescriptor receiverParameter,
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull ResolutionContext<?> c
|
||||
) {
|
||||
KtExpression reportOn = receiverArgument instanceof ExpressionReceiver
|
||||
? ((ExpressionReceiver) receiverArgument).getExpression()
|
||||
: reference;
|
||||
|
||||
if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(
|
||||
c, reportOn, receiverParameter.getType(), receiverArgument.getType())) {
|
||||
trace.report(TYPE_MISMATCH.on(reportOn, receiverParameter.getType(), receiverArgument.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +202,7 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData data) {
|
||||
public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data) {
|
||||
ConstraintSystem constraintSystem = data.constraintSystem;
|
||||
ConstraintSystemStatus status = constraintSystem.getStatus();
|
||||
assert !status.isSuccessful() : "Report error only for not successful constraint system";
|
||||
@@ -205,6 +212,7 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
||||
// (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
|
||||
return;
|
||||
}
|
||||
BindingTrace trace = context.trace;
|
||||
if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
|
||||
KotlinType declaredReturnType = data.descriptor.getReturnType();
|
||||
if (declaredReturnType == null) return;
|
||||
@@ -215,7 +223,10 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
||||
assert substitutedReturnType != null; //todo
|
||||
|
||||
assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
|
||||
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(call.getCallElement(), data.expectedType, substitutedReturnType));
|
||||
if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(
|
||||
context, call.getCallElement(), data.expectedType, substitutedReturnType)) {
|
||||
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(call.getCallElement(), data.expectedType, substitutedReturnType));
|
||||
}
|
||||
}
|
||||
else if (status.hasCannotCaptureTypesError()) {
|
||||
trace.report(TYPE_INFERENCE_CANNOT_CAPTURE_TYPES.on(reference, data));
|
||||
|
||||
@@ -58,10 +58,11 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
@NotNull StatementFilter statementFilter,
|
||||
@NotNull Collection<MutableResolvedCall<F>> resolvedCalls,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
this.lazyCandidates = lazyCandidates;
|
||||
this.resolvedCalls = resolvedCalls;
|
||||
this.tracing = tracing;
|
||||
@@ -78,7 +79,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
context.resolutionResultsCache, context.dataFlowInfoForArguments,
|
||||
context.callChecker,
|
||||
context.statementFilter, new SmartList<MutableResolvedCall<F>>(),
|
||||
context.isAnnotationContext, context.collectAllCandidates);
|
||||
context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -104,14 +105,15 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
return new ResolutionTask<D, F>(
|
||||
lazyCandidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
resolutionResultsCache, dataFlowInfoForArguments,
|
||||
callChecker,
|
||||
statementFilter, resolvedCalls,
|
||||
isAnnotationContext, collectAllCandidates);
|
||||
isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-4
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.Call;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
@@ -52,7 +53,12 @@ public interface TracingStrategy {
|
||||
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver) {}
|
||||
|
||||
@Override
|
||||
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument) {}
|
||||
public void wrongReceiverType(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ReceiverParameterDescriptor receiverParameter,
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull ResolutionContext<?> c
|
||||
) {}
|
||||
|
||||
@Override
|
||||
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
|
||||
@@ -95,7 +101,7 @@ public interface TracingStrategy {
|
||||
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {}
|
||||
|
||||
@Override
|
||||
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {}
|
||||
public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData inferenceErrorData) {}
|
||||
|
||||
@Override
|
||||
public void nonExtensionFunctionCalledAsExtension(@NotNull BindingTrace trace) { }
|
||||
@@ -115,7 +121,12 @@ public interface TracingStrategy {
|
||||
|
||||
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver);
|
||||
|
||||
void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument);
|
||||
void wrongReceiverType(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ReceiverParameterDescriptor receiverParameter,
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull ResolutionContext<?> c
|
||||
);
|
||||
|
||||
void noReceiverAllowed(@NotNull BindingTrace trace);
|
||||
|
||||
@@ -146,7 +157,7 @@ public interface TracingStrategy {
|
||||
|
||||
void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor);
|
||||
|
||||
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData);
|
||||
void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData inferenceErrorData);
|
||||
|
||||
void nonExtensionFunctionCalledAsExtension(@NotNull BindingTrace trace);
|
||||
}
|
||||
|
||||
+3
-2
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.CALL
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.RESOLVED_CALL
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -117,7 +118,7 @@ class TracingStrategyForImplicitConstructorDelegationCall(
|
||||
unexpectedError("missingReceiver")
|
||||
}
|
||||
|
||||
override fun wrongReceiverType(trace: BindingTrace, receiverParameter: ReceiverParameterDescriptor, receiverArgument: ReceiverValue) {
|
||||
override fun wrongReceiverType(trace: BindingTrace, receiverParameter: ReceiverParameterDescriptor, receiverArgument: ReceiverValue, c: ResolutionContext<*>) {
|
||||
unexpectedError("wrongReceiverType")
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ class TracingStrategyForImplicitConstructorDelegationCall(
|
||||
unexpectedError("wrongNumberOfTypeArguments")
|
||||
}
|
||||
|
||||
override fun typeInferenceFailed(trace: BindingTrace, data: InferenceErrorData) {
|
||||
override fun typeInferenceFailed(context: ResolutionContext<*>, data: InferenceErrorData) {
|
||||
unexpectedError("typeInferenceFailed")
|
||||
}
|
||||
|
||||
|
||||
+27
-7
@@ -24,12 +24,15 @@ import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||
import org.jetbrains.kotlin.psi.KtConstantExpression;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -42,15 +45,17 @@ public class CompileTimeConstantChecker {
|
||||
private final KotlinBuiltIns builtIns;
|
||||
private final BindingTrace trace;
|
||||
private final boolean checkOnlyErrorsThatDependOnExpectedType;
|
||||
private final ResolutionContext<?> context;
|
||||
|
||||
public CompileTimeConstantChecker(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ResolutionContext<?> context,
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
boolean checkOnlyErrorsThatDependOnExpectedType
|
||||
) {
|
||||
this.checkOnlyErrorsThatDependOnExpectedType = checkOnlyErrorsThatDependOnExpectedType;
|
||||
this.builtIns = builtIns;
|
||||
this.trace = trace;
|
||||
this.trace = context.trace;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// return true if there is an error
|
||||
@@ -95,7 +100,7 @@ public class CompileTimeConstantChecker {
|
||||
if (!noExpectedTypeOrError(expectedType)) {
|
||||
KotlinType valueType = value.getType();
|
||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType));
|
||||
return reportConstantExpectedTypeMismatch(expression, "integer", expectedType, null);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -112,7 +117,7 @@ public class CompileTimeConstantChecker {
|
||||
if (!noExpectedTypeOrError(expectedType)) {
|
||||
KotlinType valueType = value.getType();
|
||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "floating-point", expectedType));
|
||||
return reportConstantExpectedTypeMismatch(expression, "floating-point", expectedType, null);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -124,7 +129,7 @@ public class CompileTimeConstantChecker {
|
||||
) {
|
||||
if (!noExpectedTypeOrError(expectedType)
|
||||
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(builtIns.getBooleanType(), expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "boolean", expectedType));
|
||||
return reportConstantExpectedTypeMismatch(expression, "boolean", expectedType, builtIns.getBooleanType());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -132,7 +137,7 @@ public class CompileTimeConstantChecker {
|
||||
private boolean checkCharValue(ConstantValue<?> constant, KotlinType expectedType, KtConstantExpression expression) {
|
||||
if (!noExpectedTypeOrError(expectedType)
|
||||
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(builtIns.getCharType(), expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType));
|
||||
return reportConstantExpectedTypeMismatch(expression, "character", expectedType, builtIns.getCharType());
|
||||
}
|
||||
|
||||
if (constant != null) {
|
||||
@@ -148,6 +153,9 @@ public class CompileTimeConstantChecker {
|
||||
|
||||
private boolean checkNullValue(@NotNull KotlinType expectedType, @NotNull KtConstantExpression expression) {
|
||||
if (!noExpectedTypeOrError(expectedType) && !TypeUtils.acceptsNullable(expectedType)) {
|
||||
if (DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(context, expression, expectedType, builtIns.getNullableNothingType())) {
|
||||
return true;
|
||||
}
|
||||
return reportError(NULL_FOR_NONNULL_TYPE.on(expression, expectedType));
|
||||
}
|
||||
return false;
|
||||
@@ -269,10 +277,22 @@ public class CompileTimeConstantChecker {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean noExpectedTypeOrError(KotlinType expectedType) {
|
||||
private static boolean noExpectedTypeOrError(KotlinType expectedType) {
|
||||
return TypeUtils.noExpectedType(expectedType) || expectedType.isError();
|
||||
}
|
||||
|
||||
private boolean reportConstantExpectedTypeMismatch(
|
||||
@NotNull KtConstantExpression expression,
|
||||
@NotNull String typeName,
|
||||
@NotNull KotlinType expectedType,
|
||||
@Nullable KotlinType expressionType
|
||||
) {
|
||||
if (DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(context, expression, expectedType, expressionType)) return true;
|
||||
|
||||
trace.report(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, typeName, expectedType));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean reportError(@NotNull Diagnostic diagnostic) {
|
||||
if (!checkOnlyErrorsThatDependOnExpectedType || errorsThatDependOnExpectedType.contains(diagnostic.getFactory())) {
|
||||
trace.report(diagnostic);
|
||||
|
||||
+3
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
@@ -196,7 +198,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
);
|
||||
|
||||
if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
|
||||
CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context.trace, components.builtIns, false);
|
||||
CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context, components.builtIns, false);
|
||||
ConstantValue constantValue =
|
||||
compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
|
||||
boolean hasError = constantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
|
||||
|
||||
+8
-4
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintsUtil;
|
||||
@@ -386,7 +387,7 @@ public class ControlStructureTypingUtils {
|
||||
|
||||
@Override
|
||||
public void typeInferenceFailed(
|
||||
@NotNull BindingTrace trace, @NotNull InferenceErrorData data
|
||||
@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data
|
||||
) {
|
||||
ConstraintSystem constraintSystem = data.constraintSystem;
|
||||
ConstraintSystemStatus status = constraintSystem.getStatus();
|
||||
@@ -398,7 +399,7 @@ public class ControlStructureTypingUtils {
|
||||
KtExpression expression = (KtExpression) call.getCallElement();
|
||||
if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints()
|
||||
|| status.hasTypeInferenceIncorporationError()) { // todo after KT-... remove this line
|
||||
expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType));
|
||||
expression.accept(checkTypeVisitor, new CheckTypeContext(context.trace, data.expectedType));
|
||||
return;
|
||||
}
|
||||
KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtNamedDeclaration.class);
|
||||
@@ -455,7 +456,10 @@ public class ControlStructureTypingUtils {
|
||||
|
||||
@Override
|
||||
public void wrongReceiverType(
|
||||
@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull ReceiverParameterDescriptor receiverParameter,
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull ResolutionContext<?> c
|
||||
) {
|
||||
logError();
|
||||
}
|
||||
@@ -532,7 +536,7 @@ public class ControlStructureTypingUtils {
|
||||
|
||||
@Override
|
||||
public void typeInferenceFailed(
|
||||
@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData
|
||||
@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData inferenceErrorData
|
||||
) {
|
||||
logError();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -196,7 +197,7 @@ public class DataFlowAnalyzer {
|
||||
|
||||
if (expression instanceof KtConstantExpression) {
|
||||
ConstantValue<?> constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, c.trace, c.expectedType);
|
||||
boolean error = new CompileTimeConstantChecker(c.trace, builtIns, true)
|
||||
boolean error = new CompileTimeConstantChecker(c, builtIns, true)
|
||||
.checkConstantExpressionType(constantValue, (KtConstantExpression) expression, c.expectedType);
|
||||
hasError.set(error);
|
||||
return expressionType;
|
||||
@@ -210,7 +211,9 @@ public class DataFlowAnalyzer {
|
||||
SmartCastResult castResult = checkPossibleCast(expressionType, expression, c);
|
||||
if (castResult != null) return castResult.getResultType();
|
||||
|
||||
c.trace.report(TYPE_MISMATCH.on(expression, c.expectedType, expressionType));
|
||||
if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(c, expression, c.expectedType, expressionType)) {
|
||||
c.trace.report(TYPE_MISMATCH.on(expression, c.expectedType, expressionType));
|
||||
}
|
||||
hasError.set(true);
|
||||
return expressionType;
|
||||
}
|
||||
|
||||
+10
-11
@@ -20,10 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionResultsCache;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionResultsCacheImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -61,8 +58,8 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
context.contextDependency, context.resolutionResultsCache,
|
||||
context.callChecker,
|
||||
context.statementFilter,
|
||||
context.isAnnotationContext, context.collectAllCandidates
|
||||
);
|
||||
context.isAnnotationContext, context.collectAllCandidates,
|
||||
context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -79,7 +76,7 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
) {
|
||||
return new ExpressionTypingContext(
|
||||
trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, callChecker,
|
||||
statementFilter, isAnnotationContext, false);
|
||||
statementFilter, isAnnotationContext, false, CallPosition.Unknown.INSTANCE);
|
||||
}
|
||||
|
||||
private ExpressionTypingContext(
|
||||
@@ -92,11 +89,12 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
|
||||
callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,11 +106,12 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean collectAllCandidates
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
return new ExpressionTypingContext(trace, scope, dataFlowInfo,
|
||||
expectedType, contextDependency, resolutionResultsCache,
|
||||
callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates);
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -124,8 +124,7 @@ public class ExpressionTypingUtils {
|
||||
@Override
|
||||
public void report(@NotNull Diagnostic diagnostic) {
|
||||
DiagnosticFactory<?> factory = diagnostic.getFactory();
|
||||
if ((factory == TYPE_MISMATCH || factory == CONSTANT_EXPECTED_TYPE_MISMATCH || factory == NULL_FOR_NONNULL_TYPE)
|
||||
&& diagnostic.getPsiElement() == expressionToWatch) {
|
||||
if (Errors.TYPE_MISMATCH_ERRORS.contains(factory) && diagnostic.getPsiElement() == expressionToWatch) {
|
||||
mismatchFound[0] = true;
|
||||
}
|
||||
if (TYPE_INFERENCE_ERRORS.contains(factory) &&
|
||||
|
||||
+3
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
|
||||
import org.jetbrains.kotlin.types.DeferredType;
|
||||
@@ -230,7 +231,8 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitLambdaExpression(@NotNull KtLambdaExpression expression, ExpressionTypingContext data) {
|
||||
return functions.visitLambdaExpression(expression, data);
|
||||
// Erasing call position to unknown is necessary to prevent wrong call positions when type checking lambda's body
|
||||
return functions.visitLambdaExpression(expression, data.replaceCallPosition(CallPosition.Unknown.INSTANCE));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-2
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
@@ -269,7 +270,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
KotlinType expectedType = refineTypeFromPropertySetterIfPossible(context.trace.getBindingContext(), leftOperand, leftType);
|
||||
|
||||
components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(expectedType)
|
||||
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()));
|
||||
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()).replaceCallPosition(new CallPosition.PropertyAssignment(left)));
|
||||
basic.checkLValue(context.trace, context, leftOperand, right);
|
||||
}
|
||||
temporary.commit();
|
||||
@@ -317,7 +318,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
||||
KotlinTypeInfo resultInfo;
|
||||
if (right != null) {
|
||||
resultInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(expectedType));
|
||||
resultInfo = facade.getTypeInfo(
|
||||
right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(expectedType).replaceCallPosition(
|
||||
new CallPosition.PropertyAssignment(leftOperand)));
|
||||
|
||||
dataFlowInfo = resultInfo.getDataFlowInfo();
|
||||
KotlinType rightType = resultInfo.getType();
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
|
||||
fun foo() {
|
||||
val f : Function1<*, *> = { x -> x.toString() }
|
||||
f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
<!MEMBER_PROJECTED_OUT!>f<!>(1)
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ fun testInOut() {
|
||||
|
||||
Inv<Int>().f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!MEMBER_PROJECTED_OUT!>f<!>(1) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!MEMBER_PROJECTED_OUT!>f<!>(1) // !!
|
||||
|
||||
Inv<Int>().inf(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).inf(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).inf(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).inf(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!MEMBER_PROJECTED_OUT!>inf<!>(1) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!MEMBER_PROJECTED_OUT!>inf<!>(1) // !!
|
||||
|
||||
Inv<Int>().outf()
|
||||
checkSubtype<Int>(<!TYPE_MISMATCH!>(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).outf()<!>) // Type mismatch
|
||||
|
||||
+3
-3
@@ -28,9 +28,9 @@ fun main() {
|
||||
checkSubtype<Outer<out CharSequence>.Inner>(outer.bar())
|
||||
checkSubtype<Outer<out CharSequence>.Inner>(outer.Inner())
|
||||
|
||||
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<out kotlin.String>.Inner)!>outer.bar()<!>)
|
||||
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<out kotlin.String>.Inner)!>outer.Inner()<!>)
|
||||
outer.<!MEMBER_PROJECTED_OUT!>set<!>(outer.bar())
|
||||
outer.<!MEMBER_PROJECTED_OUT!>set<!>(outer.Inner())
|
||||
|
||||
val x: Outer<String>.Inner = factoryString()
|
||||
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<kotlin.String>.Inner)!>x<!>)
|
||||
outer.<!MEMBER_PROJECTED_OUT!>set<!>(x)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ interface C<out T>
|
||||
interface MC<T> : C<T> {
|
||||
fun addAll(x: C<T>): Boolean
|
||||
fun addAllMC(x: MC<out T>): Boolean
|
||||
fun addAllInv(x: MC<T>): Boolean
|
||||
}
|
||||
|
||||
interface Open
|
||||
@@ -13,15 +14,18 @@ fun <T> mc(): MC<T> = null!!
|
||||
fun <T> c(): C<T> = null!!
|
||||
|
||||
fun foo(x: MC<out Open>) {
|
||||
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<out Open>)!>x<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<out Open>)!>x<!>)
|
||||
x.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<out Open>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>x<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<out Open>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>x<!>)
|
||||
|
||||
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<Open>)!>mc<Open>()<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<Open>)!>mc<Open>()<!>)
|
||||
x.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<Open>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>mc<Open>()<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<Open>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>mc<Open>()<!>)
|
||||
|
||||
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<Derived>)!>mc<Derived>()<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<Derived>)!>mc<Derived>()<!>)
|
||||
x.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<Derived>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>mc<Derived>()<!>)
|
||||
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<Derived>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>mc<Derived>()<!>)
|
||||
|
||||
x.addAll(c())
|
||||
x.addAll(c<Nothing>())
|
||||
|
||||
x.<!MEMBER_PROJECTED_OUT!>addAllInv<!>(mc<Open>())
|
||||
x.addAll(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public final class Derived : Open {
|
||||
|
||||
public interface MC</*0*/ T> : C<T> {
|
||||
public abstract fun addAll(/*0*/ x: C<T>): kotlin.Boolean
|
||||
public abstract fun addAllInv(/*0*/ x: MC<T>): kotlin.Boolean
|
||||
public abstract fun addAllMC(/*0*/ x: MC<out T>): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
class A<T> {
|
||||
fun T.foo() {}
|
||||
fun Out<T>.bar() {}
|
||||
}
|
||||
class Out<out E>
|
||||
|
||||
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test(x: A<out CharSequence>, y: Out<CharSequence>) {
|
||||
with(x) {
|
||||
// TODO: this diagnostic could be replaced with TYPE_MISMATCH_DUE_TO_TYPE_PROJECTION
|
||||
"".<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>foo<!>()
|
||||
<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>.bar()
|
||||
|
||||
with(y) {
|
||||
<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>bar<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ x: A<out kotlin.CharSequence>, /*1*/ y: Out<kotlin.CharSequence>): kotlin.Unit
|
||||
public inline fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ f: T.() -> R): R
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final fun Out<T>.bar(): kotlin.Unit
|
||||
public final fun T.foo(): kotlin.Unit
|
||||
}
|
||||
|
||||
public final class Out</*0*/ out E> {
|
||||
public constructor Out</*0*/ out E>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface A<T>
|
||||
interface B<E> {
|
||||
fun foo(x: A<in E>)
|
||||
}
|
||||
|
||||
fun foo(x: B<in CharSequence>, y: A<CharSequence>) {
|
||||
x.foo(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>)
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: B<in kotlin.CharSequence>, /*1*/ y: A<kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ x: A<in E>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class Out<out T>
|
||||
class In<in T> {
|
||||
fun invoke1(x: T) {}
|
||||
fun invoke2(x: Out<T>) {}
|
||||
}
|
||||
|
||||
interface A<E> {
|
||||
fun foo(): In<E>
|
||||
}
|
||||
|
||||
fun test(a: A<out CharSequence>, y: Out<CharSequence>) {
|
||||
val i = a.foo()
|
||||
// TODO: These diagnostic are wrong, type of 'i' --- 'In<Nothing>' is not projected itself,
|
||||
// but it's approximation result caused by 'a' projection
|
||||
i.invoke1(<!TYPE_MISMATCH!>""<!>)
|
||||
i.invoke2(<!TYPE_MISMATCH!>y<!>)
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: Out<kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): In<E>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class In</*0*/ in T> {
|
||||
public constructor In</*0*/ in T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun invoke1(/*0*/ x: T): kotlin.Unit
|
||||
public final fun invoke2(/*0*/ x: Out<T>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Out</*0*/ out T> {
|
||||
public constructor Out</*0*/ out T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A<T> {
|
||||
fun foo(x: T, y: T) {}
|
||||
}
|
||||
|
||||
fun test(a: A<out CharSequence>) {
|
||||
a.<!MEMBER_PROJECTED_OUT!>foo<!>("", "")
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ x: T, /*1*/ y: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A<T> {
|
||||
operator fun plus(x: T): A<T> = this
|
||||
operator fun set(x: Int, y: T) {}
|
||||
operator fun get(x: T) = 1
|
||||
}
|
||||
|
||||
fun test(a: A<out CharSequence>) {
|
||||
a <!MEMBER_PROJECTED_OUT(public final operator fun plus\(x: T\): A<T> defined in A; A<out kotlin.CharSequence>)!>+<!> ""
|
||||
<!MEMBER_PROJECTED_OUT(public final operator fun set\(x: kotlin.Int, y: T\): kotlin.Unit defined in A; A<out kotlin.CharSequence>)!>a[1]<!> = ""
|
||||
<!MEMBER_PROJECTED_OUT(public final operator fun get\(x: T\): kotlin.Int defined in A; A<out kotlin.CharSequence>)!>a[""]<!>
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final operator fun get(/*0*/ x: T): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final operator fun plus(/*0*/ x: T): A<T>
|
||||
public final operator fun set(/*0*/ x: kotlin.Int, /*1*/ y: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A<T> {
|
||||
operator fun plus(x: Out<T>): A<T> = this
|
||||
operator fun set(x: Int, y: Out<T>) {}
|
||||
operator fun get(x: Out<T>) = 1
|
||||
}
|
||||
|
||||
class Out<out F>
|
||||
|
||||
fun test(a: A<out CharSequence>, y: Out<CharSequence>) {
|
||||
a + <!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>
|
||||
a[1] = <!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>
|
||||
a[<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>]
|
||||
|
||||
a + Out<Nothing>()
|
||||
a[1] = Out<Nothing>()
|
||||
a[Out<Nothing>()]
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: Out<kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final operator fun get(/*0*/ x: Out<T>): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final operator fun plus(/*0*/ x: Out<T>): A<T>
|
||||
public final operator fun set(/*0*/ x: kotlin.Int, /*1*/ y: Out<T>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Out</*0*/ out F> {
|
||||
public constructor Out</*0*/ out F>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
class Out<out T> {
|
||||
fun id() = this
|
||||
fun foobar(x: Any) {}
|
||||
}
|
||||
|
||||
class A<E> {
|
||||
inline fun foo(block: () -> E) {}
|
||||
inline fun bar(block: () -> Out<E>) {}
|
||||
}
|
||||
|
||||
fun test(a: A<out CharSequence>, z: Out<CharSequence>) {
|
||||
a.foo {
|
||||
val x: String = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> // Should be no TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
|
||||
<!TYPE_MISMATCH!>""<!>
|
||||
}
|
||||
a.bar { <!TYPE_MISMATCH!>Out<CharSequence>()<!> }
|
||||
a.bar { Out() }
|
||||
a.bar { <!TYPE_MISMATCH!>z.id()<!> }
|
||||
|
||||
a.foo {
|
||||
z.foobar(if (1 > 2) return@foo <!TYPE_MISMATCH!>""<!> else "")
|
||||
<!TYPE_MISMATCH!>""<!>
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ z: Out<kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ E> {
|
||||
public constructor A</*0*/ E>()
|
||||
public final inline fun bar(/*0*/ block: () -> Out<E>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final inline fun foo(/*0*/ block: () -> E): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Out</*0*/ out T> {
|
||||
public constructor Out</*0*/ out T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foobar(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun id(): Out<T>
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A<T> {
|
||||
fun foo(vararg x: T) {}
|
||||
}
|
||||
|
||||
fun test(a: A<out CharSequence>, y: Array<out CharSequence>) {
|
||||
a.<!MEMBER_PROJECTED_OUT!>foo<!>("", "", "")
|
||||
a.foo(*<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>)
|
||||
// TODO: TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS probably redundant
|
||||
a.<!MEMBER_PROJECTED_OUT!>foo<!>(*<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>, "")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: kotlin.Array<out kotlin.CharSequence>): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ vararg x: T /*kotlin.Array<out T>*/): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+1
-1
@@ -4,6 +4,6 @@ interface Tr<T> {
|
||||
}
|
||||
|
||||
fun test(t: Tr<*>) {
|
||||
t.v = <!TYPE_MISMATCH!>t<!>
|
||||
<!SETTER_PROJECTED_OUT!>t.v<!> = t
|
||||
t.v checkType { _<Tr<*>>() }
|
||||
}
|
||||
+2
-2
@@ -7,7 +7,7 @@ interface Tr<T> {
|
||||
|
||||
fun test(t: Tr<*>) {
|
||||
t.v = null!!
|
||||
t.v = <!TYPE_MISMATCH!>""<!>
|
||||
t.v = <!NULL_FOR_NONNULL_TYPE!>null<!>
|
||||
<!SETTER_PROJECTED_OUT!>t.v<!> = ""
|
||||
<!SETTER_PROJECTED_OUT!>t.v<!> = null
|
||||
t.v checkType { _<Any?>() }
|
||||
}
|
||||
Vendored
+1
-1
@@ -6,5 +6,5 @@ interface Tr<T> {
|
||||
fun test(t: Tr<out String>) {
|
||||
// resolved as t.v = t.v + null!!, where type of right operand is String,
|
||||
// so TYPE_MISMATCH: String is not <: of Captured(out String)
|
||||
<!TYPE_MISMATCH!>t.v += null!!<!>
|
||||
<!SETTER_PROJECTED_OUT!>t.v<!> += null!!
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
fun test(mc: MutableCollection<out CharSequence>) {
|
||||
mc.addAll(<!TYPE_MISMATCH!>mc<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>mc<!>)
|
||||
|
||||
mc.addAll(<!TYPE_MISMATCH!>arrayListOf<CharSequence>()<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>arrayListOf<CharSequence>()<!>)
|
||||
mc.addAll(arrayListOf())
|
||||
|
||||
mc.addAll(<!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>listOf("")<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH!>listOf<String>("")<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH!>listOf<CharSequence>("")<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf("")<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<String>("")<!>)
|
||||
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<CharSequence>("")<!>)
|
||||
|
||||
mc.addAll(emptyList())
|
||||
mc.addAll(emptyList<Nothing>())
|
||||
|
||||
@@ -7190,6 +7190,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionReceiverTypeMismatch.kt")
|
||||
public void testExtensionReceiverTypeMismatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/extensionReceiverTypeMismatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionResultSubstitution.kt")
|
||||
public void testExtensionResultSubstitution() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.kt");
|
||||
@@ -7202,6 +7208,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inValueParameter.kt")
|
||||
public void testInValueParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/inValueParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt7296.kt")
|
||||
public void testKt7296() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.kt");
|
||||
@@ -7220,18 +7232,36 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("leakedApproximatedType.kt")
|
||||
public void testLeakedApproximatedType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/leakedApproximatedType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MLOut.kt")
|
||||
public void testMLOut() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleArgumentProjectedOut.kt")
|
||||
public void testMultipleArgumentProjectedOut() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/multipleArgumentProjectedOut.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("platformSuperClass.kt")
|
||||
public void testPlatformSuperClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/platformSuperClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("projectedOutConventions.kt")
|
||||
public void testProjectedOutConventions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutConventions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveUpperBoundStar.kt")
|
||||
public void testRecursiveUpperBoundStar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt");
|
||||
@@ -7262,6 +7292,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchConventions.kt")
|
||||
public void testTypeMismatchConventions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchConventions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchInLambda.kt")
|
||||
public void testTypeMismatchInLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchInLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterBounds.kt")
|
||||
public void testTypeParameterBounds() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
||||
@@ -7273,6 +7315,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("varargs.kt")
|
||||
public void testVarargs() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/starProjections")
|
||||
|
||||
+3
-3
@@ -98,17 +98,17 @@ fun createCapturedType(typeProjection: TypeProjection): KotlinType
|
||||
|
||||
fun KotlinType.isCaptured(): Boolean = constructor is CapturedTypeConstructor
|
||||
|
||||
fun TypeSubstitution.wrapWithCapturingSubstitution(): TypeSubstitution =
|
||||
fun TypeSubstitution.wrapWithCapturingSubstitution(needApproximation: Boolean = true): TypeSubstitution =
|
||||
if (this is IndexedParametersSubstitution)
|
||||
IndexedParametersSubstitution(
|
||||
this.parameters,
|
||||
this.arguments.zip(this.parameters).map {
|
||||
it.first.createCapturedIfNeeded(it.second)
|
||||
}.toTypedArray(),
|
||||
approximateCapturedTypes = true)
|
||||
approximateCapturedTypes = needApproximation)
|
||||
else
|
||||
object : DelegatedTypeSubstitution(this@wrapWithCapturingSubstitution) {
|
||||
override fun approximateContravariantCapturedTypes() = true
|
||||
override fun approximateContravariantCapturedTypes() = needApproximation
|
||||
override fun get(key: KotlinType) = super.get(key)?.createCapturedIfNeeded(key.constructor.declarationDescriptor as? TypeParameterDescriptor)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
data class ApproximationBounds<T>(
|
||||
|
||||
@@ -20,12 +20,14 @@ import com.intellij.icons.AllIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.TypeMismatchDueToTypeProjectionsData;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallDataHtmlRenderer;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.renderer.MultiRenderer;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@@ -66,6 +68,22 @@ public class IdeErrorMessages {
|
||||
MAP.put(TYPE_MISMATCH, "<html>Type mismatch.<table><tr><td>Required:</td><td>{0}</td></tr><tr><td>Found:</td><td>{1}</td></tr></table></html>",
|
||||
HTML_RENDER_TYPE, HTML_RENDER_TYPE);
|
||||
|
||||
MAP.put(TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS,
|
||||
"<html>Type mismatch.<table><tr><td>Required:</td><td>{0}</td></tr><tr><td>Found:</td><td>{1}</td></tr></table><br />\n" +
|
||||
"Projected type {2} restricts use of <br />\n{3}\n</html>",
|
||||
new MultiRenderer<TypeMismatchDueToTypeProjectionsData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String[] render(@NotNull TypeMismatchDueToTypeProjectionsData object) {
|
||||
return new String[] {
|
||||
HTML_RENDER_TYPE.render(object.getExpectedType()),
|
||||
HTML_RENDER_TYPE.render(object.getExpressionType()),
|
||||
HTML_RENDER_TYPE.render(object.getReceiverType()),
|
||||
DescriptorRenderer.HTML.render(object.getCallableDescriptor())
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
MAP.put(ASSIGN_OPERATOR_AMBIGUITY, "<html>Assignment operators ambiguity. All these functions match.<ul>{0}</ul></table></html>",
|
||||
HTML_AMBIGUOUS_CALLS);
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// !DIAGNOSTICS_NUMBER: 1
|
||||
// !DIAGNOSTICS: MEMBER_PROJECTED_OUT
|
||||
|
||||
fun foo(x: MutableCollection<out CharSequence>) {
|
||||
x.add("")
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<!-- expectedNothingDueToProjections1 -->
|
||||
Out-projected type 'kotlin.MutableCollection<out kotlin.CharSequence>' prohibits the use of 'public abstract fun add(element: E): kotlin.Boolean defined in kotlin.MutableCollection'
|
||||
@@ -0,0 +1,6 @@
|
||||
// !DIAGNOSTICS_NUMBER: 1
|
||||
// !DIAGNOSTICS: TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
|
||||
|
||||
fun foo(x: MutableCollection<out CharSequence>, y: MutableCollection<CharSequence>) {
|
||||
x.addAll(y)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<!-- typeMismatchDueToProjections1 -->
|
||||
<html>
|
||||
Type mismatch.
|
||||
<table>
|
||||
<tr>
|
||||
<td>Required:</td>
|
||||
<td>kotlin.Collection<`kotlin.Nothing></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Found:</td>
|
||||
<td>kotlin.MutableCollection<`kotlin.CharSequence></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
Projected type kotlin.MutableCollection<`out kotlin.CharSequence> restricts use of <br />
|
||||
<b>public</b> <b>abstract</b> <b>fun</b> addAll(elements: kotlin.Collection<`E>): kotlin.Boolean <i>defined in</i> kotlin.MutableCollection
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
// !DIAGNOSTICS_NUMBER: 1
|
||||
// !DIAGNOSTICS: TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
|
||||
|
||||
interface A<T>
|
||||
interface B<E> {
|
||||
fun foo(x: A<in E>)
|
||||
}
|
||||
|
||||
fun foo(x: B<in CharSequence>, y: A<CharSequence>) {
|
||||
x.foo(y)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<!-- typeMismatchDueToProjectionsIn1 -->
|
||||
<html>
|
||||
Type mismatch.
|
||||
<table>
|
||||
<tr>
|
||||
<td>Required:</td>
|
||||
<td>A<`kotlin.Any?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Found:</td>
|
||||
<td>A<`kotlin.CharSequence></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
Projected type B<`in kotlin.CharSequence> restricts use of <br />
|
||||
<b>public</b> <b>abstract</b> <b>fun</b> foo(x: A<`in E>): kotlin.Unit <i>defined in</i> B
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
// !DIAGNOSTICS_NUMBER: 1
|
||||
// !DIAGNOSTICS: TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
|
||||
// !MESSAGE_TYPE: TEXT
|
||||
|
||||
fun foo(x: MutableCollection<out CharSequence>, y: MutableCollection<CharSequence>) {
|
||||
x.addAll(y)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<!-- typeMismatchDueToProjectionsTxt1 -->
|
||||
Type mismatch: inferred type is kotlin.MutableCollection<kotlin.CharSequence> but kotlin.Collection<kotlin.Nothing> was expected. Projected type kotlin.MutableCollection<out kotlin.CharSequence> restricts use of public abstract fun addAll(elements: kotlin.Collection<E>): kotlin.Boolean defined in kotlin.MutableCollection
|
||||
@@ -101,6 +101,12 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("expectedNothingDueToProjections.kt")
|
||||
public void testExpectedNothingDueToProjections() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/expectedNothingDueToProjections.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionInClassReference.kt")
|
||||
public void testExtensionInClassReference() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/extensionInClassReference.kt");
|
||||
@@ -179,6 +185,24 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchDueToProjections.kt")
|
||||
public void testTypeMismatchDueToProjections() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/typeMismatchDueToProjections.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchDueToProjectionsIn.kt")
|
||||
public void testTypeMismatchDueToProjectionsIn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/typeMismatchDueToProjectionsIn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchDueToProjectionsTxt.kt")
|
||||
public void testTypeMismatchDueToProjectionsTxt() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/typeMismatchDueToProjectionsTxt.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeMismatchWithNothing.kt")
|
||||
public void testTypeMismatchWithNothing() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/typeMismatchWithNothing.kt");
|
||||
|
||||
Reference in New Issue
Block a user