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