001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.resolve.calls;
018
019 import com.google.common.collect.Lists;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023 import org.jetbrains.kotlin.builtins.ReflectionTypes;
024 import org.jetbrains.kotlin.descriptors.CallableDescriptor;
025 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
026 import org.jetbrains.kotlin.diagnostics.Errors;
027 import org.jetbrains.kotlin.psi.*;
028 import org.jetbrains.kotlin.resolve.BindingTrace;
029 import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
030 import org.jetbrains.kotlin.resolve.TypeResolver;
031 import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesResolutionUtilsKt;
032 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
033 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
034 import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
035 import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
036 import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
037 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImplKt;
038 import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
039 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
040 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
041 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
042 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
043 import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
044 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
045 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
046 import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver;
047 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
048 import org.jetbrains.kotlin.types.FunctionPlaceholders;
049 import org.jetbrains.kotlin.types.FunctionPlaceholdersKt;
050 import org.jetbrains.kotlin.types.KotlinType;
051 import org.jetbrains.kotlin.types.TypeUtils;
052 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
053 import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
054 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
055 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
056
057 import java.util.Collections;
058 import java.util.List;
059
060 import static org.jetbrains.kotlin.psi.KtPsiUtil.getLastElementDeparenthesized;
061 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getRecordedTypeInfo;
062 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
063 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
064 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
065 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
066 import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
067 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
068
069 public class ArgumentTypeResolver {
070 @NotNull private final TypeResolver typeResolver;
071 @NotNull private final CallResolver callResolver;
072 @NotNull private final ExpressionTypingServices expressionTypingServices;
073 @NotNull private final KotlinBuiltIns builtIns;
074 @NotNull private final ReflectionTypes reflectionTypes;
075 @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
076 @NotNull private final FunctionPlaceholders functionPlaceholders;
077
078 public ArgumentTypeResolver(
079 @NotNull TypeResolver typeResolver,
080 @NotNull CallResolver callResolver,
081 @NotNull ExpressionTypingServices expressionTypingServices,
082 @NotNull KotlinBuiltIns builtIns,
083 @NotNull ReflectionTypes reflectionTypes,
084 @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
085 @NotNull FunctionPlaceholders functionPlaceholders
086 ) {
087 this.typeResolver = typeResolver;
088 this.callResolver = callResolver;
089 this.expressionTypingServices = expressionTypingServices;
090 this.builtIns = builtIns;
091 this.reflectionTypes = reflectionTypes;
092 this.constantExpressionEvaluator = constantExpressionEvaluator;
093 this.functionPlaceholders = functionPlaceholders;
094 }
095
096 public static boolean isSubtypeOfForArgumentType(
097 @NotNull KotlinType actualType,
098 @NotNull KotlinType expectedType
099 ) {
100 if (FunctionPlaceholdersKt.isFunctionPlaceholder(actualType)) {
101 KotlinType functionType = ConstraintSystemImplKt.createTypeForFunctionPlaceholder(actualType, expectedType);
102 return KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, expectedType);
103 }
104 return KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
105 }
106
107 public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) {
108 checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
109 }
110
111 public void checkTypesWithNoCallee(
112 @NotNull CallResolutionContext<?> context,
113 @NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
114 ) {
115 if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
116
117 for (ValueArgument valueArgument : context.call.getValueArguments()) {
118 KtExpression argumentExpression = valueArgument.getArgumentExpression();
119 if (argumentExpression != null && !(argumentExpression instanceof KtFunctionLiteralExpression)) {
120 checkArgumentTypeWithNoCallee(context, argumentExpression);
121 }
122 }
123
124 if (resolveFunctionArgumentBodies == RESOLVE_FUNCTION_ARGUMENTS) {
125 checkTypesForFunctionArgumentsWithNoCallee(context);
126 }
127
128 for (KtTypeProjection typeProjection : context.call.getTypeArguments()) {
129 KtTypeReference typeReference = typeProjection.getTypeReference();
130 if (typeReference == null) {
131 context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
132 }
133 else {
134 typeResolver.resolveType(context.scope, typeReference, context.trace, true);
135 }
136 }
137 }
138
139 public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) {
140 if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
141
142 for (ValueArgument valueArgument : context.call.getValueArguments()) {
143 KtExpression argumentExpression = valueArgument.getArgumentExpression();
144 if (argumentExpression != null && isFunctionLiteralArgument(argumentExpression, context)) {
145 checkArgumentTypeWithNoCallee(context, argumentExpression);
146 }
147 }
148 }
149
150 private void checkArgumentTypeWithNoCallee(CallResolutionContext<?> context, KtExpression argumentExpression) {
151 expressionTypingServices.getTypeInfo(argumentExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
152 updateResultArgumentTypeIfNotDenotable(context, argumentExpression);
153 }
154
155 public static boolean isFunctionLiteralArgument(
156 @NotNull KtExpression expression, @NotNull ResolutionContext context
157 ) {
158 return getFunctionLiteralArgumentIfAny(expression, context) != null;
159 }
160
161 @NotNull
162 public static KtFunction getFunctionLiteralArgument(
163 @NotNull KtExpression expression, @NotNull ResolutionContext context
164 ) {
165 assert isFunctionLiteralArgument(expression, context);
166 //noinspection ConstantConditions
167 return getFunctionLiteralArgumentIfAny(expression, context);
168 }
169
170 @Nullable
171 public static KtFunction getFunctionLiteralArgumentIfAny(
172 @NotNull KtExpression expression, @NotNull ResolutionContext context
173 ) {
174 KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
175 if (deparenthesizedExpression instanceof KtFunctionLiteralExpression) {
176 return ((KtFunctionLiteralExpression) deparenthesizedExpression).getFunctionLiteral();
177 }
178 if (deparenthesizedExpression instanceof KtFunction) {
179 return (KtFunction) deparenthesizedExpression;
180 }
181 return null;
182 }
183
184 @Nullable
185 public static KtCallableReferenceExpression getCallableReferenceExpressionIfAny(
186 @NotNull KtExpression expression,
187 @NotNull CallResolutionContext<?> context
188 ) {
189 KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
190 if (deparenthesizedExpression instanceof KtCallableReferenceExpression) {
191 return (KtCallableReferenceExpression) deparenthesizedExpression;
192 }
193 return null;
194 }
195
196 @NotNull
197 public KotlinTypeInfo getArgumentTypeInfo(
198 @Nullable KtExpression expression,
199 @NotNull CallResolutionContext<?> context,
200 @NotNull ResolveArgumentsMode resolveArgumentsMode
201 ) {
202 if (expression == null) {
203 return TypeInfoFactoryKt.noTypeInfo(context);
204 }
205
206 KtFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
207 if (functionLiteralArgument != null) {
208 return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
209 }
210
211 KtCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
212 if (callableReferenceExpression != null) {
213 return getCallableReferenceTypeInfo(expression, callableReferenceExpression, context, resolveArgumentsMode);
214 }
215
216 KotlinTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
217 if (recordedTypeInfo != null) {
218 return recordedTypeInfo;
219 }
220
221 ResolutionContext newContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(DEPENDENT);
222
223 return expressionTypingServices.getTypeInfo(expression, newContext);
224 }
225
226 @NotNull
227 public KotlinTypeInfo getCallableReferenceTypeInfo(
228 @NotNull KtExpression expression,
229 @NotNull KtCallableReferenceExpression callableReferenceExpression,
230 @NotNull CallResolutionContext<?> context,
231 @NotNull ResolveArgumentsMode resolveArgumentsMode
232 ) {
233 if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
234 KotlinType type = getShapeTypeOfCallableReference(callableReferenceExpression, context, true);
235 return TypeInfoFactoryKt.createTypeInfo(type);
236 }
237 return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
238 }
239
240 @Nullable
241 public KotlinType getShapeTypeOfCallableReference(
242 @NotNull KtCallableReferenceExpression callableReferenceExpression,
243 @NotNull CallResolutionContext<?> context,
244 boolean expectedTypeIsUnknown
245 ) {
246 KotlinType receiverType =
247 CallableReferencesResolutionUtilsKt.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver);
248 OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
249 CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference(
250 callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
251 callResolver);
252 return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType(
253 callableReferenceExpression, receiverType, overloadResolutionResults, context, expectedTypeIsUnknown,
254 reflectionTypes, builtIns, functionPlaceholders);
255 }
256
257 @NotNull
258 public KotlinTypeInfo getFunctionLiteralTypeInfo(
259 @NotNull KtExpression expression,
260 @NotNull KtFunction functionLiteral,
261 @NotNull CallResolutionContext<?> context,
262 @NotNull ResolveArgumentsMode resolveArgumentsMode
263 ) {
264 if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
265 KotlinType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true);
266 return TypeInfoFactoryKt.createTypeInfo(type, context);
267 }
268 return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
269 }
270
271 @Nullable
272 public KotlinType getShapeTypeOfFunctionLiteral(
273 @NotNull KtFunction function,
274 @NotNull LexicalScope scope,
275 @NotNull BindingTrace trace,
276 boolean expectedTypeIsUnknown
277 ) {
278 boolean isFunctionLiteral = function instanceof KtFunctionLiteral;
279 if (function.getValueParameterList() == null && isFunctionLiteral) {
280 return expectedTypeIsUnknown
281 ? functionPlaceholders
282 .createFunctionPlaceholderType(Collections.<KotlinType>emptyList(), /* hasDeclaredArguments = */ false)
283 : builtIns.getFunctionType(Annotations.Companion.getEMPTY(), null, Collections.<KotlinType>emptyList(), DONT_CARE);
284 }
285 List<KtParameter> valueParameters = function.getValueParameters();
286 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
287 trace, "trace to resolve function literal parameter types");
288 List<KotlinType> parameterTypes = Lists.newArrayList();
289 for (KtParameter parameter : valueParameters) {
290 parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
291 }
292 KotlinType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE);
293 assert returnType != null;
294 KotlinType receiverType = resolveTypeRefWithDefault(function.getReceiverTypeReference(), scope, temporaryTrace, null);
295
296 return expectedTypeIsUnknown && isFunctionLiteral
297 ? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true)
298 : builtIns.getFunctionType(Annotations.Companion.getEMPTY(), receiverType, parameterTypes, returnType);
299 }
300
301 @Nullable
302 public KotlinType resolveTypeRefWithDefault(
303 @Nullable KtTypeReference returnTypeRef,
304 @NotNull LexicalScope scope,
305 @NotNull BindingTrace trace,
306 @Nullable KotlinType defaultValue
307 ) {
308 if (returnTypeRef != null) {
309 return typeResolver.resolveType(scope, returnTypeRef, trace, true);
310 }
311 return defaultValue;
312 }
313
314 /**
315 * Visits function call arguments and determines data flow information changes
316 */
317 public void analyzeArgumentsAndRecordTypes(
318 @NotNull CallResolutionContext<?> context
319 ) {
320 MutableDataFlowInfoForArguments infoForArguments = context.dataFlowInfoForArguments;
321 Call call = context.call;
322 ReceiverValue receiver = call.getExplicitReceiver();
323 DataFlowInfo initialDataFlowInfo = context.dataFlowInfo;
324 // QualifierReceiver is a thing like Collections. which has no type or value
325 if (receiver.exists() && !(receiver instanceof QualifierReceiver)) {
326 DataFlowValue receiverDataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, context);
327 // Additional "receiver != null" information for KT-5840
328 // Should be applied if we consider a safe call
329 // For an unsafe call, we should not do it,
330 // otherwise not-null will propagate to successive statements
331 // Sample: x?.foo(x.bar()) // Inside foo call, x is not-nullable
332 if (CallUtilKt.isSafeCall(call)) {
333 initialDataFlowInfo = initialDataFlowInfo.disequate(receiverDataFlowValue, DataFlowValue.nullValue(builtIns));
334 }
335 }
336 infoForArguments.setInitialDataFlowInfo(initialDataFlowInfo);
337
338 for (ValueArgument argument : call.getValueArguments()) {
339 KtExpression expression = argument.getArgumentExpression();
340 if (expression == null) continue;
341
342 CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument));
343 // Here we go inside arguments and determine additional data flow information for them
344 KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, SHAPE_FUNCTION_ARGUMENTS);
345 infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
346 }
347 }
348
349 @Nullable
350 public KotlinType updateResultArgumentTypeIfNotDenotable(
351 @NotNull ResolutionContext context,
352 @NotNull KtExpression expression
353 ) {
354 KotlinType type = context.trace.getType(expression);
355 if (type != null && !type.getConstructor().isDenotable()) {
356 if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
357 IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor();
358 KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
359 constantExpressionEvaluator.updateNumberType(primitiveType, expression, context.statementFilter, context.trace);
360 return primitiveType;
361 }
362 }
363 return null;
364 }
365 }