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