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.types.expressions;
018    
019    import com.google.common.collect.Lists;
020    import com.google.common.collect.Maps;
021    import com.intellij.openapi.project.Project;
022    import com.intellij.openapi.util.Pair;
023    import com.intellij.psi.PsiElement;
024    import com.intellij.psi.tree.IElementType;
025    import com.intellij.psi.util.PsiTreeUtil;
026    import org.jetbrains.annotations.NotNull;
027    import org.jetbrains.annotations.Nullable;
028    import org.jetbrains.jet.JetNodeTypes;
029    import org.jetbrains.jet.lang.descriptors.*;
030    import org.jetbrains.jet.lang.diagnostics.Diagnostic;
031    import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
032    import org.jetbrains.jet.lang.diagnostics.Errors;
033    import org.jetbrains.jet.lang.psi.*;
034    import org.jetbrains.jet.lang.resolve.*;
035    import org.jetbrains.jet.lang.resolve.calls.CallResolver;
036    import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
037    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
038    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
039    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
040    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
041    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
042    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
043    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
044    import org.jetbrains.jet.lang.resolve.name.FqName;
045    import org.jetbrains.jet.lang.resolve.name.Name;
046    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
047    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
048    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
049    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
050    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
051    import org.jetbrains.jet.lang.types.*;
052    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
053    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
054    import org.jetbrains.jet.lexer.JetTokens;
055    import org.jetbrains.jet.util.slicedmap.WritableSlice;
056    
057    import java.util.*;
058    
059    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
060    import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory;
061    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
062    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
063    
064    public class ExpressionTypingUtils {
065    
066        private final ExpressionTypingServices expressionTypingServices;
067        private final CallResolver callResolver;
068    
069        public ExpressionTypingUtils(@NotNull ExpressionTypingServices expressionTypingServices, @NotNull CallResolver resolver) {
070            this.expressionTypingServices = expressionTypingServices;
071            callResolver = resolver;
072        }
073    
074        @Nullable
075        protected static ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, @Nullable JetType type) {
076            if (type == null) return null;
077            return new ExpressionReceiver(expression, type);
078        }
079    
080        @Nullable
081        protected static ExpressionReceiver getExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) {
082            return getExpressionReceiver(expression, facade.getTypeInfo(expression, context).getType());
083        }
084    
085        @NotNull
086        protected static ExpressionReceiver safeGetExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) {
087            JetType type = safeGetType(facade.safeGetTypeInfo(expression, context));
088            return new ExpressionReceiver(expression, type);
089        }
090    
091        @NotNull
092        public static JetType safeGetType(@NotNull JetTypeInfo typeInfo) {
093            JetType type = typeInfo.getType();
094            assert type != null : "safeGetType should be invoked on safe JetTypeInfo; safeGetTypeInfo should return @NotNull type";
095            return type;
096        }
097    
098        @NotNull
099        public static WritableScopeImpl newWritableScopeImpl(ExpressionTypingContext context, @NotNull String scopeDebugName) {
100            WritableScopeImpl scope = new WritableScopeImpl(
101                    context.scope, context.scope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.trace), scopeDebugName);
102            scope.changeLockLevel(WritableScope.LockLevel.BOTH);
103            return scope;
104        }
105    
106        public static boolean isBoolean(@NotNull JetType type) {
107            return JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
108        }
109    
110        public static boolean ensureBooleanResult(JetExpression operationSign, Name name, JetType resultType, ExpressionTypingContext context) {
111            return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'", context);
112        }
113    
114        public static boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName, ExpressionTypingContext context) {
115            if (resultType != null) {
116                // TODO : Relax?
117                if (!isBoolean(resultType)) {
118                    context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, subjectName, KotlinBuiltIns.getInstance().getBooleanType(), resultType));
119                    return false;
120                }
121            }
122            return true;
123        }
124    
125        @NotNull
126        public static JetType getDefaultType(IElementType constantType) {
127            if (constantType == JetNodeTypes.INTEGER_CONSTANT) {
128                return KotlinBuiltIns.getInstance().getIntType();
129            }
130            else if (constantType == JetNodeTypes.FLOAT_CONSTANT) {
131                return KotlinBuiltIns.getInstance().getDoubleType();
132            }
133            else if (constantType == JetNodeTypes.BOOLEAN_CONSTANT) {
134                return KotlinBuiltIns.getInstance().getBooleanType();
135            }
136            else if (constantType == JetNodeTypes.CHARACTER_CONSTANT) {
137                return KotlinBuiltIns.getInstance().getCharType();
138            }
139            else if (constantType == JetNodeTypes.NULL) {
140                return KotlinBuiltIns.getInstance().getNullableNothingType();
141            }
142            else {
143                throw new IllegalArgumentException("Unsupported constant type: " + constantType);
144            }
145        }
146    
147        private static boolean isCapturedInInline(
148                @NotNull BindingContext context,
149                @NotNull DeclarationDescriptor scopeContainer,
150                @NotNull DeclarationDescriptor variableParent
151        ) {
152            PsiElement scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer);
153            if (!(scopeDeclaration instanceof JetFunctionLiteral)) {
154                return false;
155            }
156    
157            PsiElement parent = scopeDeclaration.getParent();
158            assert parent instanceof JetFunctionLiteralExpression : "parent of JetFunctionLiteral is " + parent;
159            ResolvedCall<?> resolvedCall = CallUtilPackage.getParentResolvedCall((JetFunctionLiteralExpression) parent, context, true);
160            if (resolvedCall == null) {
161                return false;
162            }
163    
164            CallableDescriptor callable = resolvedCall.getResultingDescriptor();
165            if (callable instanceof SimpleFunctionDescriptor && ((SimpleFunctionDescriptor) callable).getInlineStrategy().isInline()) {
166                DeclarationDescriptor scopeContainerParent = scopeContainer.getContainingDeclaration();
167                assert scopeContainerParent != null : "parent is null for " + scopeContainer;
168                return scopeContainerParent == variableParent || isCapturedInInline(context, scopeContainerParent, variableParent);
169            }
170            else {
171                return false;
172            }
173        }
174    
175        public static void checkCapturingInClosure(JetSimpleNameExpression expression, BindingTrace trace, JetScope scope) {
176            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
177            if (variable != null) {
178                DeclarationDescriptor variableParent = variable.getContainingDeclaration();
179                DeclarationDescriptor scopeContainer = scope.getContainingDeclaration();
180                if (scopeContainer != variableParent && variableParent instanceof CallableDescriptor) {
181                    if (trace.get(CAPTURED_IN_CLOSURE, variable) != CaptureKind.NOT_INLINE) {
182                        boolean inline = isCapturedInInline(trace.getBindingContext(), scopeContainer, variableParent);
183                        trace.record(CAPTURED_IN_CLOSURE, variable, inline ? CaptureKind.INLINE_ONLY : CaptureKind.NOT_INLINE);
184                    }
185                }
186            }
187        }
188    
189        /**
190         * Check that function or property with the given qualified name can be resolved in given scope and called on given receiver
191         *
192         * @param callableFQN
193         * @param scope
194         * @return
195         */
196        public static List<CallableDescriptor> canFindSuitableCall(
197                @NotNull FqName callableFQN,
198                @NotNull JetExpression receiverExpression,
199                @NotNull JetType receiverType,
200                @NotNull JetScope scope,
201                @NotNull ModuleDescriptor module
202        ) {
203            JetImportDirective importDirective = JetPsiFactory(receiverExpression).createImportDirective(callableFQN.asString());
204    
205            Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver()
206                    .analyseImportReference(importDirective, scope, new BindingTraceContext(), module);
207    
208            List<CallableDescriptor> callableExtensionDescriptors = new ArrayList<CallableDescriptor>();
209            ReceiverValue receiverValue = new ExpressionReceiver(receiverExpression, receiverType);
210    
211            for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
212                if (declarationDescriptor instanceof CallableDescriptor) {
213                    CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor;
214    
215                    if (checkIsExtensionCallable(receiverValue, callableDescriptor)) {
216                        callableExtensionDescriptors.add(callableDescriptor);
217                    }
218                }
219            }
220    
221            return callableExtensionDescriptors;
222        }
223    
224        /*
225        * Checks if receiver declaration could be resolved to call expected receiver.
226        */
227        public static boolean checkIsExtensionCallable (
228                @NotNull ReceiverValue receiverArgument,
229                @NotNull CallableDescriptor callableDescriptor
230        ) {
231            JetType type = receiverArgument.getType();
232    
233            if (type instanceof PackageType) {
234                // This fake class ruins standard algorithms
235                return false;
236            }
237    
238            if (checkReceiverResolution(receiverArgument, type, callableDescriptor)) return true;
239            if (type.isNullable()) {
240                JetType notNullableType = TypeUtils.makeNotNullable(type);
241                if (checkReceiverResolution(receiverArgument, notNullableType, callableDescriptor)) return true;
242            }
243            return false;
244        }
245    
246        private static boolean checkReceiverResolution (
247                @NotNull ReceiverValue receiverArgument,
248                @NotNull JetType receiverType,
249                @NotNull CallableDescriptor callableDescriptor
250        ) {
251            ReceiverParameterDescriptor receiverParameter = callableDescriptor.getReceiverParameter();
252    
253            if (!receiverArgument.exists() && receiverParameter == null) {
254                // Both receivers do not exist
255                return true;
256            }
257    
258            if (!(receiverArgument.exists() && receiverParameter != null)) {
259                return false;
260            }
261    
262            Set<Name> typeNamesInReceiver = collectUsedTypeNames(receiverParameter.getType());
263    
264            ConstraintSystem constraintSystem = new ConstraintSystemImpl();
265            Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
266            for (TypeParameterDescriptor typeParameterDescriptor : callableDescriptor.getTypeParameters()) {
267                if (typeNamesInReceiver.contains(typeParameterDescriptor.getName())) {
268                    typeVariables.put(typeParameterDescriptor, Variance.INVARIANT);
269                }
270            }
271            constraintSystem.registerTypeVariables(typeVariables);
272    
273            constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
274            return constraintSystem.getStatus().isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, true);
275        }
276    
277        private static Set<Name> collectUsedTypeNames(@NotNull JetType jetType) {
278            Set<Name> typeNames = new HashSet<Name>();
279    
280            ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
281            if (descriptor != null) {
282                typeNames.add(descriptor.getName());
283            }
284    
285            for (TypeProjection argument : jetType.getArguments()) {
286                typeNames.addAll(collectUsedTypeNames(argument.getType()));
287            }
288    
289            return typeNames;
290        }
291    
292        @NotNull
293        public OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(
294                @NotNull ExpressionTypingContext context,
295                @NotNull ReceiverValue receiver,
296                @NotNull Name name,
297                @NotNull JetType... argumentTypes
298        ) {
299            TemporaryBindingTrace traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for",
300                                                                                           name);
301            List<JetExpression> fakeArguments = Lists.newArrayList();
302            for (JetType type : argumentTypes) {
303                fakeArguments.add(createFakeExpressionOfType(expressionTypingServices.getProject(), traceWithFakeArgumentInfo,
304                                                             "fakeArgument" + fakeArguments.size(), type));
305            }
306            return makeAndResolveFakeCall(receiver, context.replaceBindingTrace(traceWithFakeArgumentInfo), fakeArguments, name).getSecond();
307        }
308    
309        public static JetExpression createFakeExpressionOfType(
310                @NotNull Project project,
311                @NotNull BindingTrace trace,
312                @NotNull String argumentName,
313                @NotNull JetType argumentType
314        ) {
315            JetExpression fakeExpression = JetPsiFactory(project).createExpression(argumentName);
316            trace.record(EXPRESSION_TYPE, fakeExpression, argumentType);
317            trace.record(PROCESSED, fakeExpression);
318            return fakeExpression;
319        }
320    
321        @NotNull
322        public OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(
323                @NotNull ExpressionTypingContext context,
324                @NotNull ReceiverValue receiver,
325                @NotNull Name name
326        ) {
327            return resolveFakeCall(receiver, context, Collections.<JetExpression>emptyList(), name);
328        }
329    
330        @NotNull
331        public OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(
332                @NotNull ReceiverValue receiver,
333                @NotNull ExpressionTypingContext context,
334                @NotNull List<JetExpression> valueArguments,
335                @NotNull Name name
336        ) {
337            return makeAndResolveFakeCall(receiver, context, valueArguments, name).getSecond();
338        }
339    
340        @NotNull
341        public Pair<Call, OverloadResolutionResults<FunctionDescriptor>> makeAndResolveFakeCall(
342                @NotNull ReceiverValue receiver,
343                @NotNull ExpressionTypingContext context,
344                @NotNull List<JetExpression> valueArguments,
345                @NotNull Name name
346        ) {
347            final JetReferenceExpression fake = JetPsiFactory(expressionTypingServices.getProject()).createSimpleName("fake");
348            TemporaryBindingTrace fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name);
349            Call call = CallMaker.makeCallWithExpressions(fake, receiver, null, fake, valueArguments);
350            OverloadResolutionResults<FunctionDescriptor> results =
351                    callResolver.resolveCallWithGivenName(context.replaceBindingTrace(fakeTrace), call, fake, name);
352            if (results.isSuccess()) {
353                fakeTrace.commit(new TraceEntryFilter() {
354                    @Override
355                    public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
356                        // excluding all entries related to fake expression
357                        return key != fake;
358                    }
359                }, true);
360            }
361            return Pair.create(call, results);
362        }
363    
364        public void defineLocalVariablesFromMultiDeclaration(
365                @NotNull WritableScope writableScope,
366                @NotNull JetMultiDeclaration multiDeclaration,
367                @NotNull ReceiverValue receiver,
368                @NotNull JetExpression reportErrorsOn,
369                @NotNull ExpressionTypingContext context
370        ) {
371            int componentIndex = 1;
372            for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
373                Name componentName = Name.identifier(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX + componentIndex);
374                componentIndex++;
375    
376                JetType expectedType = getExpectedTypeForComponent(context, entry);
377                OverloadResolutionResults<FunctionDescriptor> results =
378                        resolveFakeCall(context.replaceExpectedType(expectedType), receiver, componentName);
379    
380                JetType componentType = null;
381                if (results.isSuccess()) {
382                    context.trace.record(COMPONENT_RESOLVED_CALL, entry, results.getResultingCall());
383                    componentType = results.getResultingDescriptor().getReturnType();
384                    if (componentType != null && !noExpectedType(expectedType)
385                           && !JetTypeChecker.DEFAULT.isSubtypeOf(componentType, expectedType)) {
386    
387                        context.trace.report(
388                                COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(reportErrorsOn, componentName, componentType, expectedType));
389                    }
390                }
391                else if (results.isAmbiguity()) {
392                    context.trace.report(COMPONENT_FUNCTION_AMBIGUITY.on(reportErrorsOn, componentName, results.getResultingCalls()));
393                }
394                else {
395                    context.trace.report(COMPONENT_FUNCTION_MISSING.on(reportErrorsOn, componentName, receiver.getType()));
396                }
397                if (componentType == null) {
398                    componentType = ErrorUtils.createErrorType(componentName + "() return type");
399                }
400                VariableDescriptor variableDescriptor = expressionTypingServices.getDescriptorResolver().
401                    resolveLocalVariableDescriptorWithType(writableScope, entry, componentType, context.trace);
402    
403                VariableDescriptor olderVariable = writableScope.getLocalVariable(variableDescriptor.getName());
404                checkVariableShadowing(context, variableDescriptor, olderVariable);
405    
406                writableScope.addVariableDescriptor(variableDescriptor);
407            }
408        }
409    
410        public static void checkVariableShadowing(@NotNull ExpressionTypingContext context, @NotNull VariableDescriptor variableDescriptor, VariableDescriptor oldDescriptor) {
411            if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) {
412                PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
413                if (declaration != null) {
414                    context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
415                }
416            }
417        }
418    
419        @NotNull
420        private JetType getExpectedTypeForComponent(ExpressionTypingContext context, JetMultiDeclarationEntry entry) {
421            JetTypeReference entryTypeRef = entry.getTypeRef();
422            if (entryTypeRef != null) {
423                return expressionTypingServices.getTypeResolver().resolveType(context.scope, entryTypeRef, context.trace, true);
424            }
425            else {
426                return TypeUtils.NO_EXPECTED_TYPE;
427            }
428        }
429    
430        public static ObservableBindingTrace makeTraceInterceptingTypeMismatch(@NotNull BindingTrace trace, @NotNull final JetElement expressionToWatch, @NotNull final boolean[] mismatchFound) {
431            return new ObservableBindingTrace(trace) {
432    
433                @Override
434                public void report(@NotNull Diagnostic diagnostic) {
435                    DiagnosticFactory<?> factory = diagnostic.getFactory();
436                    if ((factory == TYPE_MISMATCH || factory == CONSTANT_EXPECTED_TYPE_MISMATCH || factory == NULL_FOR_NONNULL_TYPE)
437                            && diagnostic.getPsiElement() == expressionToWatch) {
438                        mismatchFound[0] = true;
439                    }
440                    if (TYPE_INFERENCE_ERRORS.contains(factory) &&
441                        PsiTreeUtil.isAncestor(expressionToWatch, diagnostic.getPsiElement(), false)) {
442                        mismatchFound[0] = true;
443                    }
444                    super.report(diagnostic);
445                }
446            };
447        }
448    
449        @NotNull
450        public static JetTypeInfo getTypeInfoOrNullType(
451                @Nullable JetExpression expression,
452                @NotNull ExpressionTypingContext context,
453                @NotNull ExpressionTypingInternals facade
454        ) {
455            return expression != null
456                   ? facade.getTypeInfo(expression, context)
457                   : JetTypeInfo.create(null, context.dataFlowInfo);
458        }
459    
460        @SuppressWarnings("SuspiciousMethodCalls")
461        public static boolean isBinaryExpressionDependentOnExpectedType(@NotNull JetBinaryExpression expression) {
462            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
463            return (operationType == JetTokens.IDENTIFIER || OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)
464                    || operationType == JetTokens.ELVIS);
465        }
466    
467        public static boolean isUnaryExpressionDependentOnExpectedType(@NotNull JetUnaryExpression expression) {
468            return expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL;
469        }
470    
471        @NotNull
472        public static List<JetType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
473            List<JetType> parameterTypes = new ArrayList<JetType>(valueParameters.size());
474            for (ValueParameterDescriptor parameter : valueParameters) {
475                parameterTypes.add(parameter.getType());
476            }
477            return parameterTypes;
478        }
479    
480        /**
481         * The primary case for local extensions is the following:
482         *
483         * I had a locally declared extension function or a local variable of function type called foo
484         * And I called it on my x
485         * Now, someone added function foo() to the class of x
486         * My code should not change
487         *
488         * thus
489         *
490         * local extension prevail over members (and members prevail over all non-local extensions)
491         */
492        public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
493            if (candidate instanceof ValueParameterDescriptor) {
494                return true;
495            }
496            DeclarationDescriptor parent = candidate.getContainingDeclaration();
497            if (!(parent instanceof FunctionDescriptor)) {
498                return false;
499            }
500            FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
501            DeclarationDescriptor current = containerOfTheCurrentLocality;
502            while (current != null) {
503                if (current == functionDescriptor) {
504                    return true;
505                }
506                current = current.getContainingDeclaration();
507            }
508            return false;
509        }
510    
511        public static boolean dependsOnExpectedType(@Nullable JetExpression expression) {
512            JetExpression expr = JetPsiUtil.deparenthesize(expression, false);
513            if (expr == null) return false;
514    
515            if (expr instanceof JetBinaryExpressionWithTypeRHS) {
516                return false;
517            }
518            if (expr instanceof JetBinaryExpression) {
519                return isBinaryExpressionDependentOnExpectedType((JetBinaryExpression) expr);
520            }
521            if (expr instanceof JetUnaryExpression) {
522                return isUnaryExpressionDependentOnExpectedType((JetUnaryExpression) expr);
523            }
524            return true;
525        }
526    }