001    /*
002     * Copyright 2010-2013 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.jet.lang.resolve.calls;
018    
019    import com.intellij.lang.ASTNode;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.util.PsiTreeUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.*;
025    import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
026    import org.jetbrains.jet.lang.psi.*;
027    import org.jetbrains.jet.lang.resolve.BindingContext;
028    import org.jetbrains.jet.lang.resolve.BindingTrace;
029    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
030    import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
031    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
032    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
033    import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
034    import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
035    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
036    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
037    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
038    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
039    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
040    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
041    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
042    import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
043    import org.jetbrains.jet.lang.resolve.name.Name;
044    import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
045    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
046    import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
047    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
048    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
049    import org.jetbrains.jet.lang.types.*;
050    import org.jetbrains.jet.lang.types.expressions.BasicExpressionTypingVisitor;
051    import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
052    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
053    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
054    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
055    import org.jetbrains.jet.lexer.JetTokens;
056    import org.jetbrains.jet.utils.Printer;
057    
058    import javax.inject.Inject;
059    import java.util.ArrayList;
060    import java.util.Collections;
061    import java.util.List;
062    
063    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
064    import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
065    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
066    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
067    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
068    import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
069    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
070    
071    public class CallExpressionResolver {
072        @NotNull
073        private ExpressionTypingServices expressionTypingServices;
074    
075        @Inject
076        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
077            this.expressionTypingServices = expressionTypingServices;
078        }
079    
080        @Nullable
081        private JetType lookupPackageOrClassObject(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) {
082            Name referencedName = expression.getReferencedNameAsName();
083            final ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
084            if (classifier != null) {
085                JetType classObjectType = classifier.getClassObjectType();
086                if (classObjectType != null) {
087                    context.trace.record(REFERENCE_TARGET, expression, classifier);
088                    JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context);
089                    checkClassObjectVisibility(classifier, expression, context);
090                    return DataFlowUtils.checkType(result, expression, context);
091                }
092            }
093            JetType[] result = new JetType[1];
094            TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
095                    context.trace, "trace for package/class object lookup of name", referencedName);
096            if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
097                temporaryTrace.commit();
098                return DataFlowUtils.checkType(result[0], expression, context);
099            }
100            // To report NO_CLASS_OBJECT when no package found
101            if (classifier != null) {
102                if (classifier instanceof TypeParameterDescriptor) {
103                    if (isLHSOfDot(expression)) {
104                        context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, (TypeParameterDescriptor) classifier));
105                    }
106                    else {
107                        context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, (TypeParameterDescriptor) classifier));
108                    }
109                }
110                else if (!isLHSOfDot(expression)) {
111                    context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
112                }
113                context.trace.record(REFERENCE_TARGET, expression, classifier);
114                JetScope scopeForStaticMembersResolution =
115                        classifier instanceof ClassDescriptor
116                        ? getStaticNestedClassesScope((ClassDescriptor) classifier)
117                        : new JetScopeImpl() {
118                                @NotNull
119                                @Override
120                                public DeclarationDescriptor getContainingDeclaration() {
121                                    return classifier;
122                                }
123    
124                                @Override
125                                public String toString() {
126                                    return "Scope for the type parameter on the left hand side of dot";
127                                }
128    
129                                @Override
130                                public void printScopeStructure(@NotNull Printer p) {
131                                    p.println(toString(), " for ", classifier);
132                                }
133                        };
134                return new PackageType(referencedName, scopeForStaticMembersResolution, NO_RECEIVER);
135            }
136            temporaryTrace.commit();
137            return result[0];
138        }
139    
140        private static void checkClassObjectVisibility(
141                @NotNull ClassifierDescriptor classifier,
142                @NotNull JetSimpleNameExpression expression,
143                @NotNull ExpressionTypingContext context
144        ) {
145            if (!(classifier instanceof ClassDescriptor)) return;
146            ClassDescriptor classObject = ((ClassDescriptor) classifier).getClassObjectDescriptor();
147            assert classObject != null : "This check should be done only for classes with class objects: " + classifier;
148            DeclarationDescriptor from = context.containingDeclaration;
149            if (!Visibilities.isVisible(classObject, from)) {
150                context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), from));
151            }
152        }
153    
154        @NotNull
155        private static JetType getExtendedClassObjectType(
156                @NotNull JetSimpleNameExpression expression,
157                @NotNull JetType classObjectType,
158                @NotNull ClassifierDescriptor classifier,
159                @NotNull ResolutionContext context
160        ) {
161            if (!isLHSOfDot(expression) || !(classifier instanceof ClassDescriptor)) {
162                return classObjectType;
163            }
164            ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
165    
166            if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
167                return classObjectType;
168            }
169    
170            List<JetScope> scopes = new ArrayList<JetScope>(3);
171    
172            scopes.add(classObjectType.getMemberScope());
173            scopes.add(getStaticNestedClassesScope(classDescriptor));
174    
175            Name referencedName = expression.getReferencedNameAsName();
176            PackageViewDescriptor packageView = context.scope.getPackage(referencedName);
177            if (packageView != null) {
178                //for enums loaded from java binaries
179                scopes.add(packageView.getMemberScope());
180            }
181    
182            JetScope scope = new ChainedScope(
183                    classifier, "Member scope for extended class object type " + classifier, scopes.toArray(new JetScope[scopes.size()])
184            );
185            return new PackageType(referencedName, scope, new ExpressionReceiver(expression, classObjectType));
186        }
187    
188        private boolean furtherNameLookup(
189                @NotNull JetSimpleNameExpression expression,
190                @NotNull JetType[] result,
191                @NotNull ResolutionContext context
192        ) {
193            PackageType packageType = lookupPackageType(expression, context);
194            if (packageType == null) {
195                return false;
196            }
197            if (isLHSOfDot(expression)) {
198                result[0] = packageType;
199                return true;
200            }
201            context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(expression));
202            result[0] = ErrorUtils.createErrorType("Type for " + expression.getReferencedNameAsName());
203            return false;
204        }
205    
206        @Nullable
207        private PackageType lookupPackageType(@NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
208            Name name = expression.getReferencedNameAsName();
209            PackageViewDescriptor packageView = context.scope.getPackage(name);
210            if (packageView == null) {
211                return null;
212            }
213            context.trace.record(REFERENCE_TARGET, expression, packageView);
214    
215            // Construct a PackageType with everything from the package and with nested classes of the corresponding class (if any)
216            JetScope scope;
217            ClassifierDescriptor classifier = context.scope.getClassifier(name);
218            if (classifier instanceof ClassDescriptor) {
219                scope = new ChainedScope(
220                        packageView, "Package type member scope for " + expression.getText(), packageView.getMemberScope(), getStaticNestedClassesScope((ClassDescriptor) classifier)
221                );
222            }
223            else {
224                scope = packageView.getMemberScope();
225            }
226            return new PackageType(name, scope, NO_RECEIVER);
227        }
228    
229        @Nullable
230        public ResolvedCallWithTrace<FunctionDescriptor> getResolvedCallForFunction(
231                @NotNull Call call, @NotNull JetExpression callExpression,
232                @NotNull ResolutionContext context, @NotNull CheckValueArgumentsMode checkArguments,
233                @NotNull boolean[] result
234        ) {
235            CallResolver callResolver = expressionTypingServices.getCallResolver();
236            OverloadResolutionResultsImpl<FunctionDescriptor> results = callResolver.resolveFunctionCall(
237                    BasicCallResolutionContext.create(context, call, checkArguments));
238            if (!results.isNothing()) {
239                checkSuper(call.getExplicitReceiver(), results, context.trace, callExpression);
240                result[0] = true;
241                return OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency);
242            }
243            result[0] = false;
244            return null;
245        }
246    
247        @Nullable
248        private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
249                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context, @NotNull boolean[] result
250        ) {
251            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
252                    context, "trace to resolve as local variable or property", nameExpression);
253            CallResolver callResolver = expressionTypingServices.getCallResolver();
254            Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
255            BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
256                    context.replaceTraceAndCache(temporaryForVariable),
257                    call, CheckValueArgumentsMode.ENABLED);
258            OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
259            if (resolutionResult.isSuccess()) {
260                temporaryForVariable.commit();
261                checkSuper(receiver, resolutionResult, context.trace, nameExpression);
262                result[0] = true;
263                return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
264            }
265    
266            ExpressionTypingContext newContext = receiver.exists()
267                                                 ? context.replaceScope(receiver.getType().getMemberScope())
268                                                 : context;
269            TemporaryTraceAndCache temporaryForPackageOrClassObject = TemporaryTraceAndCache.create(
270                    context, "trace to resolve as package or class object", nameExpression);
271            JetType jetType = lookupPackageOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForPackageOrClassObject));
272            if (jetType != null) {
273                temporaryForPackageOrClassObject.commit();
274    
275                // Uncommitted changes in temp context
276                context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
277                if (context.dataFlowInfo.hasTypeInfoConstraints()) {
278                    context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, nameExpression, context.dataFlowInfo);
279                }
280                result[0] = true;
281                return jetType;
282            }
283            temporaryForVariable.commit();
284            result[0] = !resolutionResult.isNothing();
285            return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
286        }
287    
288        @NotNull
289        public JetTypeInfo getSimpleNameExpressionTypeInfo(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
290                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
291        ) {
292            boolean[] result = new boolean[1];
293    
294            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
295                    context, "trace to resolve as variable", nameExpression);
296            JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
297            if (result[0]) {
298                temporaryForVariable.commit();
299                if (type instanceof PackageType && !isLHSOfDot(nameExpression)) {
300                    type = null;
301                }
302                return JetTypeInfo.create(type, context.dataFlowInfo);
303            }
304    
305            Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList());
306            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
307                    context, "trace to resolve as function", nameExpression);
308            ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
309            ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
310                    call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
311            if (result[0]) {
312                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
313                temporaryForFunction.commit();
314                boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
315                context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
316                type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
317                return JetTypeInfo.create(type, context.dataFlowInfo);
318            }
319    
320            temporaryForVariable.commit();
321            return JetTypeInfo.create(null, context.dataFlowInfo);
322        }
323    
324        @NotNull
325        public JetTypeInfo getCallExpressionTypeInfo(
326                @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
327                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
328        ) {
329            JetTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
330            if (context.contextDependency == INDEPENDENT) {
331                DataFlowUtils.checkType(typeInfo, callExpression, context);
332            }
333            return typeInfo;
334        }
335    
336        @NotNull
337        public JetTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(
338                @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
339                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
340        ) {
341            boolean[] result = new boolean[1];
342            Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
343    
344            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
345                    context, "trace to resolve as function call", callExpression);
346            ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
347                    call, callExpression, context.replaceTraceAndCache(temporaryForFunction),
348                    CheckValueArgumentsMode.ENABLED, result);
349            if (result[0]) {
350                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
351                temporaryForFunction.commit();
352                if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) {
353                    // there are only type arguments
354                    boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
355                    context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
356                }
357                if (functionDescriptor == null) {
358                    return JetTypeInfo.create(null, context.dataFlowInfo);
359                }
360                if (functionDescriptor instanceof ConstructorDescriptor && DescriptorUtils.isAnnotationClass(functionDescriptor.getContainingDeclaration())) {
361                    if (!canInstantiateAnnotationClass(callExpression)) {
362                        context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression));
363                    }
364                }
365    
366                JetType type = functionDescriptor.getReturnType();
367    
368                return JetTypeInfo.create(type, resolvedCall.getDataFlowInfoForArguments().getResultInfo());
369            }
370    
371            JetExpression calleeExpression = callExpression.getCalleeExpression();
372            if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
373                TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
374                        context, "trace to resolve as variable with 'invoke' call", callExpression);
375                JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode,
376                                               context.replaceTraceAndCache(temporaryForVariable), result);
377                if (result[0]) {
378                    temporaryForVariable.commit();
379                    context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
380                                                              type != null ? type : ErrorUtils.createErrorType("")));
381                    return JetTypeInfo.create(null, context.dataFlowInfo);
382                }
383            }
384            temporaryForFunction.commit();
385            return JetTypeInfo.create(null, context.dataFlowInfo);
386        }
387    
388        private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression) {
389            PsiElement parent = expression.getParent();
390            if (parent instanceof JetValueArgument) {
391                return PsiTreeUtil.getParentOfType(parent, JetAnnotationEntry.class) != null;
392            }
393            else if (parent instanceof JetParameter) {
394                JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
395                if (jetClass != null) {
396                    return jetClass.hasModifier(JetTokens.ANNOTATION_KEYWORD);
397                }
398            }
399            return false;
400        }
401    
402        private static void checkSuper(
403                @NotNull ReceiverValue receiverValue,
404                @NotNull OverloadResolutionResults<?> results,
405                @NotNull BindingTrace trace,
406                @NotNull JetExpression expression
407        ) {
408            if (!results.isSingleResult()) return;
409            if (!(receiverValue instanceof ExpressionReceiver)) return;
410            JetExpression receiver = ((ExpressionReceiver) receiverValue).getExpression();
411            CallableDescriptor descriptor = results.getResultingDescriptor();
412            if (receiver instanceof JetSuperExpression && descriptor instanceof MemberDescriptor) {
413                if (((MemberDescriptor) descriptor).getModality() == Modality.ABSTRACT) {
414                    trace.report(ABSTRACT_SUPER_CALL.on(expression));
415                }
416            }
417        }
418    
419        @NotNull
420        private JetTypeInfo getSelectorReturnTypeInfo(
421                @NotNull ReceiverValue receiver,
422                @Nullable ASTNode callOperationNode,
423                @NotNull JetExpression selectorExpression,
424                @NotNull ExpressionTypingContext context
425        ) {
426            if (selectorExpression instanceof JetCallExpression) {
427                return getCallExpressionTypeInfoWithoutFinalTypeCheck((JetCallExpression) selectorExpression, receiver,
428                                                                      callOperationNode, context);
429            }
430            else if (selectorExpression instanceof JetSimpleNameExpression) {
431                return getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
432            }
433            else {
434                context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
435            }
436            return JetTypeInfo.create(null, context.dataFlowInfo);
437        }
438    
439        @NotNull
440        public JetTypeInfo getQualifiedExpressionTypeInfo(
441                @NotNull JetQualifiedExpression expression, @NotNull ExpressionTypingContext context
442        ) {
443            // TODO : functions as values
444            JetExpression selectorExpression = expression.getSelectorExpression();
445            JetExpression receiverExpression = expression.getReceiverExpression();
446            ResolutionContext contextForReceiver = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
447            JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(receiverExpression, contextForReceiver);
448            JetType receiverType = receiverTypeInfo.getType();
449            if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
450            if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
451    
452            context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
453    
454            JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(
455                    new ExpressionReceiver(receiverExpression, receiverType),
456                    expression.getOperationTokenNode(), selectorExpression, context);
457            JetType selectorReturnType = selectorReturnTypeInfo.getType();
458    
459            //TODO move further
460            if (!(receiverType instanceof PackageType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
461                if (selectorReturnType != null && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) {
462                    if (receiverType.isNullable()) {
463                        selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
464                    }
465                }
466            }
467    
468            // TODO : this is suspicious: remove this code?
469            if (selectorReturnType != null) {
470                context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
471            }
472    
473            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType);
474            if (value instanceof IntegerValueConstant && ((IntegerValueConstant) value).isPure()) {
475                return BasicExpressionTypingVisitor.createCompileTimeConstantTypeInfo(value, expression, context);
476            }
477    
478            JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo());
479            if (context.contextDependency == INDEPENDENT) {
480                DataFlowUtils.checkType(typeInfo, expression, context);
481            }
482            return typeInfo;
483        }
484    }