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    }