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