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    }