001 /*
002 * Copyright 2010-2016 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.FunctionTypeResolveUtilsKt;
030 import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
031 import org.jetbrains.kotlin.resolve.TypeResolver;
032 import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesResolutionUtilsKt;
033 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
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.ConstraintSystemBuilderImplKt;
038 import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
039 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
040 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
041 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
042 import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
043 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
044 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
045 import org.jetbrains.kotlin.types.FunctionPlaceholders;
046 import org.jetbrains.kotlin.types.FunctionPlaceholdersKt;
047 import org.jetbrains.kotlin.types.KotlinType;
048 import org.jetbrains.kotlin.types.TypeUtils;
049 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
050 import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
051 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
052 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
053
054 import java.util.Collections;
055 import java.util.List;
056
057 import static org.jetbrains.kotlin.psi.KtPsiUtil.getLastElementDeparenthesized;
058 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getRecordedTypeInfo;
059 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
060 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
061 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
062 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
063 import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
064 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
065
066 public class ArgumentTypeResolver {
067 @NotNull private final TypeResolver typeResolver;
068 @NotNull private final CallResolver callResolver;
069 @NotNull private final ExpressionTypingServices expressionTypingServices;
070 @NotNull private final KotlinBuiltIns builtIns;
071 @NotNull private final ReflectionTypes reflectionTypes;
072 @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
073 @NotNull private final FunctionPlaceholders functionPlaceholders;
074
075 public ArgumentTypeResolver(
076 @NotNull TypeResolver typeResolver,
077 @NotNull CallResolver callResolver,
078 @NotNull ExpressionTypingServices expressionTypingServices,
079 @NotNull KotlinBuiltIns builtIns,
080 @NotNull ReflectionTypes reflectionTypes,
081 @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
082 @NotNull FunctionPlaceholders functionPlaceholders
083 ) {
084 this.typeResolver = typeResolver;
085 this.callResolver = callResolver;
086 this.expressionTypingServices = expressionTypingServices;
087 this.builtIns = builtIns;
088 this.reflectionTypes = reflectionTypes;
089 this.constantExpressionEvaluator = constantExpressionEvaluator;
090 this.functionPlaceholders = functionPlaceholders;
091 }
092
093 public static boolean isSubtypeOfForArgumentType(
094 @NotNull KotlinType actualType,
095 @NotNull KotlinType expectedType
096 ) {
097 if (FunctionPlaceholdersKt.isFunctionPlaceholder(actualType)) {
098 KotlinType functionType = ConstraintSystemBuilderImplKt.createTypeForFunctionPlaceholder(actualType, expectedType);
099 return KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, expectedType);
100 }
101 return KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
102 }
103
104 public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) {
105 checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
106 }
107
108 public void checkTypesWithNoCallee(
109 @NotNull CallResolutionContext<?> context,
110 @NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
111 ) {
112 if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
113
114 for (ValueArgument valueArgument : context.call.getValueArguments()) {
115 KtExpression argumentExpression = valueArgument.getArgumentExpression();
116 if (argumentExpression != null && !(argumentExpression instanceof KtLambdaExpression)) {
117 checkArgumentTypeWithNoCallee(context, argumentExpression);
118 }
119 }
120
121 if (resolveFunctionArgumentBodies == RESOLVE_FUNCTION_ARGUMENTS) {
122 checkTypesForFunctionArgumentsWithNoCallee(context);
123 }
124
125 for (KtTypeProjection typeProjection : context.call.getTypeArguments()) {
126 KtTypeReference typeReference = typeProjection.getTypeReference();
127 if (typeReference == null) {
128 context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
129 }
130 else {
131 typeResolver.resolveType(context.scope, typeReference, context.trace, true);
132 }
133 }
134 }
135
136 public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) {
137 if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
138
139 for (ValueArgument valueArgument : context.call.getValueArguments()) {
140 KtExpression argumentExpression = valueArgument.getArgumentExpression();
141 if (argumentExpression != null && isFunctionLiteralArgument(argumentExpression, context)) {
142 checkArgumentTypeWithNoCallee(context, argumentExpression);
143 }
144 }
145 }
146
147 private void checkArgumentTypeWithNoCallee(CallResolutionContext<?> context, KtExpression argumentExpression) {
148 expressionTypingServices.getTypeInfo(argumentExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
149 updateResultArgumentTypeIfNotDenotable(context, argumentExpression);
150 }
151
152 public static boolean isFunctionLiteralArgument(
153 @NotNull KtExpression expression, @NotNull ResolutionContext context
154 ) {
155 return getFunctionLiteralArgumentIfAny(expression, context) != null;
156 }
157
158 @NotNull
159 public static KtFunction getFunctionLiteralArgument(
160 @NotNull KtExpression expression, @NotNull ResolutionContext context
161 ) {
162 assert isFunctionLiteralArgument(expression, context);
163 //noinspection ConstantConditions
164 return getFunctionLiteralArgumentIfAny(expression, context);
165 }
166
167 @Nullable
168 public static KtFunction getFunctionLiteralArgumentIfAny(
169 @NotNull KtExpression expression, @NotNull ResolutionContext context
170 ) {
171 KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
172 if (deparenthesizedExpression instanceof KtLambdaExpression) {
173 return ((KtLambdaExpression) deparenthesizedExpression).getFunctionLiteral();
174 }
175 if (deparenthesizedExpression instanceof KtFunction) {
176 return (KtFunction) deparenthesizedExpression;
177 }
178 return null;
179 }
180
181 @Nullable
182 public static KtCallableReferenceExpression getCallableReferenceExpressionIfAny(
183 @NotNull KtExpression expression,
184 @NotNull CallResolutionContext<?> context
185 ) {
186 KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
187 if (deparenthesizedExpression instanceof KtCallableReferenceExpression) {
188 return (KtCallableReferenceExpression) deparenthesizedExpression;
189 }
190 return null;
191 }
192
193 @NotNull
194 public KotlinTypeInfo getArgumentTypeInfo(
195 @Nullable KtExpression expression,
196 @NotNull CallResolutionContext<?> context,
197 @NotNull ResolveArgumentsMode resolveArgumentsMode
198 ) {
199 if (expression == null) {
200 return TypeInfoFactoryKt.noTypeInfo(context);
201 }
202
203 KtFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
204 if (functionLiteralArgument != null) {
205 return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
206 }
207
208 KtCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
209 if (callableReferenceExpression != null) {
210 return getCallableReferenceTypeInfo(expression, callableReferenceExpression, context, resolveArgumentsMode);
211 }
212
213 KotlinTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
214 if (recordedTypeInfo != null) {
215 return recordedTypeInfo;
216 }
217
218 ResolutionContext newContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(DEPENDENT);
219
220 return expressionTypingServices.getTypeInfo(expression, newContext);
221 }
222
223 @NotNull
224 public KotlinTypeInfo getCallableReferenceTypeInfo(
225 @NotNull KtExpression expression,
226 @NotNull KtCallableReferenceExpression callableReferenceExpression,
227 @NotNull CallResolutionContext<?> context,
228 @NotNull ResolveArgumentsMode resolveArgumentsMode
229 ) {
230 if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
231 KotlinType type = getShapeTypeOfCallableReference(callableReferenceExpression, context, true);
232 return TypeInfoFactoryKt.createTypeInfo(type);
233 }
234 return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
235 }
236
237 @Nullable
238 public KotlinType getShapeTypeOfCallableReference(
239 @NotNull KtCallableReferenceExpression callableReferenceExpression,
240 @NotNull CallResolutionContext<?> context,
241 boolean expectedTypeIsUnknown
242 ) {
243 KtTypeReference typeReference = callableReferenceExpression.getTypeReference();
244 KotlinType receiverType =
245 typeReference == null ? null : typeResolver.resolveType(context.scope, typeReference, context.trace, false);
246 OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
247 CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference(
248 callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
249 callResolver);
250 if (overloadResolutionResults == null) return null;
251
252 if (overloadResolutionResults.isSingleResult()) {
253 ResolvedCall<?> resolvedCall =
254 OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency);
255 if (resolvedCall == null) return null;
256
257 return CallableReferencesResolutionUtilsKt.createReflectionTypeForCallableDescriptor(
258 resolvedCall.getResultingDescriptor(), receiverType, reflectionTypes,
259 callableReferenceExpression.isEmptyLHS(), context.scope.getOwnerDescriptor()
260 );
261 }
262
263 if (expectedTypeIsUnknown) {
264 return functionPlaceholders.createFunctionPlaceholderType(Collections.<KotlinType>emptyList(), false);
265 }
266
267 return FunctionTypeResolveUtilsKt.createFunctionType(
268 builtIns, Annotations.Companion.getEMPTY(), null, Collections.<KotlinType>emptyList(), TypeUtils.DONT_CARE
269 );
270 }
271
272 @NotNull
273 public KotlinTypeInfo getFunctionLiteralTypeInfo(
274 @NotNull KtExpression expression,
275 @NotNull KtFunction functionLiteral,
276 @NotNull CallResolutionContext<?> context,
277 @NotNull ResolveArgumentsMode resolveArgumentsMode
278 ) {
279 if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
280 KotlinType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true);
281 return TypeInfoFactoryKt.createTypeInfo(type, context);
282 }
283 return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
284 }
285
286 @Nullable
287 public KotlinType getShapeTypeOfFunctionLiteral(
288 @NotNull KtFunction function,
289 @NotNull LexicalScope scope,
290 @NotNull BindingTrace trace,
291 boolean expectedTypeIsUnknown
292 ) {
293 boolean isFunctionLiteral = function instanceof KtFunctionLiteral;
294 if (function.getValueParameterList() == null && isFunctionLiteral) {
295 return expectedTypeIsUnknown
296 ? functionPlaceholders
297 .createFunctionPlaceholderType(Collections.<KotlinType>emptyList(), /* hasDeclaredArguments = */ false)
298 : FunctionTypeResolveUtilsKt.createFunctionType(
299 builtIns, Annotations.Companion.getEMPTY(), null, Collections.<KotlinType>emptyList(), DONT_CARE
300 );
301 }
302 List<KtParameter> valueParameters = function.getValueParameters();
303 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
304 trace, "trace to resolve function literal parameter types");
305 List<KotlinType> parameterTypes = Lists.newArrayList();
306 for (KtParameter parameter : valueParameters) {
307 parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
308 }
309 KotlinType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE);
310 assert returnType != null;
311 KotlinType receiverType = resolveTypeRefWithDefault(function.getReceiverTypeReference(), scope, temporaryTrace, null);
312
313 return expectedTypeIsUnknown && isFunctionLiteral
314 ? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true)
315 : FunctionTypeResolveUtilsKt.createFunctionType(
316 builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, returnType
317 );
318 }
319
320 @Nullable
321 public KotlinType resolveTypeRefWithDefault(
322 @Nullable KtTypeReference returnTypeRef,
323 @NotNull LexicalScope scope,
324 @NotNull BindingTrace trace,
325 @Nullable KotlinType defaultValue
326 ) {
327 if (returnTypeRef != null) {
328 return typeResolver.resolveType(scope, returnTypeRef, trace, true);
329 }
330 return defaultValue;
331 }
332
333 /**
334 * Visits function call arguments and determines data flow information changes
335 */
336 public void analyzeArgumentsAndRecordTypes(
337 @NotNull CallResolutionContext<?> context, @NotNull ResolveArgumentsMode resolveArgumentsMode
338 ) {
339 MutableDataFlowInfoForArguments infoForArguments = context.dataFlowInfoForArguments;
340 Call call = context.call;
341
342 for (ValueArgument argument : call.getValueArguments()) {
343 KtExpression expression = argument.getArgumentExpression();
344 if (expression == null) continue;
345
346 CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument));
347 // Here we go inside arguments and determine additional data flow information for them
348 KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, resolveArgumentsMode);
349 infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
350 }
351 }
352
353 @Nullable
354 public KotlinType updateResultArgumentTypeIfNotDenotable(
355 @NotNull ResolutionContext context,
356 @NotNull KtExpression expression
357 ) {
358 KotlinType type = context.trace.getType(expression);
359 if (type != null && !type.getConstructor().isDenotable()) {
360 if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
361 IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor();
362 KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
363 constantExpressionEvaluator.updateNumberType(primitiveType, expression, context.statementFilter, context.trace);
364 return primitiveType;
365 }
366 }
367 return null;
368 }
369 }