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.types.expressions;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.psi.PsiElement;
021 import com.intellij.psi.tree.IElementType;
022 import com.intellij.psi.tree.TokenSet;
023 import com.intellij.psi.util.PsiTreeUtil;
024 import kotlin.KotlinPackage;
025 import kotlin.jvm.functions.Function0;
026 import kotlin.jvm.functions.Function1;
027 import org.jetbrains.annotations.NotNull;
028 import org.jetbrains.annotations.Nullable;
029 import org.jetbrains.kotlin.JetNodeTypes;
030 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
031 import org.jetbrains.kotlin.descriptors.*;
032 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
033 import org.jetbrains.kotlin.diagnostics.Diagnostic;
034 import org.jetbrains.kotlin.lexer.JetTokens;
035 import org.jetbrains.kotlin.name.Name;
036 import org.jetbrains.kotlin.psi.*;
037 import org.jetbrains.kotlin.resolve.*;
038 import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
039 import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
040 import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
041 import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
042 import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
043 import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
044 import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
045 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
046 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl;
047 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
048 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
049 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
050 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
051 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
052 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
053 import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability;
054 import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
055 import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
056 import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
057 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
058 import org.jetbrains.kotlin.resolve.constants.*;
059 import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
060 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
061 import org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage;
062 import org.jetbrains.kotlin.types.*;
063 import org.jetbrains.kotlin.types.checker.JetTypeChecker;
064 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
065 import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperPackage;
066 import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
067
068 import java.util.Collection;
069 import java.util.Collections;
070 import java.util.Iterator;
071 import java.util.List;
072
073 import static org.jetbrains.kotlin.diagnostics.Errors.*;
074 import static org.jetbrains.kotlin.lexer.JetTokens.AS_KEYWORD;
075 import static org.jetbrains.kotlin.lexer.JetTokens.AS_SAFE;
076 import static org.jetbrains.kotlin.resolve.BindingContext.*;
077 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
078 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
079 import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue;
080 import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
081 import static org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage.asJetScope;
082 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
083 import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
084 import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
085 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
086 import static org.jetbrains.kotlin.types.expressions.TypeReconstructionUtil.reconstructBareType;
087
088 @SuppressWarnings("SuspiciousMethodCalls")
089 public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
090
091 private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE);
092
093 protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
094 super(facade);
095 }
096
097 @Override
098 public JetTypeInfo visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, ExpressionTypingContext context) {
099 // TODO : other members
100 // TODO : type substitutions???
101 CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
102 JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
103 return components.dataFlowAnalyzer.checkType(typeInfo, expression, context); // TODO : Extensions to this
104 }
105
106 @Override
107 public JetTypeInfo visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, ExpressionTypingContext context) {
108 JetExpression innerExpression = expression.getExpression();
109 if (innerExpression == null) {
110 return TypeInfoFactoryPackage.noTypeInfo(context);
111 }
112 return facade.getTypeInfo(innerExpression, context.replaceScope(context.scope));
113 }
114
115 @Override
116 public JetTypeInfo visitConstantExpression(@NotNull JetConstantExpression expression, ExpressionTypingContext context) {
117 CompileTimeConstant<?> compileTimeConstant = components.constantExpressionEvaluator.evaluateExpression(
118 expression, context.trace, context.expectedType
119 );
120
121 if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
122 CompileTimeConstantChecker compileTimeConstantChecker = context.getCompileTimeConstantChecker();
123 ConstantValue constantValue = compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
124 boolean hasError = compileTimeConstantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
125 if (hasError) {
126 IElementType elementType = expression.getNode().getElementType();
127 return TypeInfoFactoryPackage.createTypeInfo(getDefaultType(elementType), context);
128 }
129 }
130
131 assert compileTimeConstant != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
132 return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context);
133 }
134
135 @NotNull
136 public JetType getDefaultType(IElementType constantType) {
137 KotlinBuiltIns builtIns = components.builtIns;
138 if (constantType == JetNodeTypes.INTEGER_CONSTANT) {
139 return builtIns.getIntType();
140 }
141 else if (constantType == JetNodeTypes.FLOAT_CONSTANT) {
142 return builtIns.getDoubleType();
143 }
144 else if (constantType == JetNodeTypes.BOOLEAN_CONSTANT) {
145 return builtIns.getBooleanType();
146 }
147 else if (constantType == JetNodeTypes.CHARACTER_CONSTANT) {
148 return builtIns.getCharType();
149 }
150 else if (constantType == JetNodeTypes.NULL) {
151 return builtIns.getNullableNothingType();
152 }
153 else {
154 throw new IllegalArgumentException("Unsupported constant type: " + constantType);
155 }
156 }
157
158 @Override
159 public JetTypeInfo visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
160 ExpressionTypingContext contextWithNoExpectedType =
161 context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
162 JetExpression left = expression.getLeft();
163 JetTypeReference right = expression.getRight();
164 if (right == null) {
165 return facade.getTypeInfo(left, contextWithNoExpectedType).clearType();
166 }
167
168 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
169
170 boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
171 TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
172 PossiblyBareType possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, right);
173
174 if (operationType == JetTokens.COLON) {
175 // We do not allow bare types on static assertions, because static assertions provide an expected type for their argument,
176 // thus causing a circularity in type dependencies
177 assert !possiblyBareTarget.isBare() : "Bare types should not be allowed for static assertions, because argument inference makes no sense there";
178 JetType targetType = possiblyBareTarget.getActualType();
179
180 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
181 checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
182 return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(targetType), expression, context);
183 }
184
185 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
186
187 JetType subjectType = typeInfo.getType();
188 JetType targetType = reconstructBareType(right, possiblyBareTarget, subjectType, context.trace, components.builtIns);
189
190 if (subjectType != null) {
191 checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType);
192 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
193 if (operationType == AS_KEYWORD) {
194 DataFlowValue value = createDataFlowValue(left, subjectType, context);
195 typeInfo = typeInfo.replaceDataFlowInfo(dataFlowInfo.establishSubtyping(value, targetType));
196 }
197 }
198
199 JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
200 return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result), expression, context);
201 }
202
203 private void checkBinaryWithTypeRHS(
204 @NotNull JetBinaryExpressionWithTypeRHS expression,
205 @NotNull ExpressionTypingContext context,
206 @NotNull JetType targetType,
207 @Nullable JetType actualType
208 ) {
209 if (actualType == null) return;
210 JetSimpleNameExpression operationSign = expression.getOperationReference();
211 IElementType operationType = operationSign.getReferencedNameElementType();
212 if (operationType == JetTokens.COLON) {
213 context.trace.report(DEPRECATED_STATIC_ASSERT.on(expression));
214 return;
215 }
216 if (operationType != JetTokens.AS_KEYWORD && operationType != JetTokens.AS_SAFE) {
217 context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
218 return;
219 }
220 checkForCastImpossibilityOrRedundancy(expression, actualType, targetType, context);
221 }
222
223 private void checkForCastImpossibilityOrRedundancy(
224 JetBinaryExpressionWithTypeRHS expression,
225 JetType actualType,
226 JetType targetType,
227 ExpressionTypingContext context
228 ) {
229 if (actualType == null || noExpectedType(targetType) || targetType.isError()) return;
230
231 if (TypesPackage.isDynamic(targetType)) {
232 JetTypeReference right = expression.getRight();
233 assert right != null : "We know target is dynamic, but RHS is missing";
234 context.trace.report(DYNAMIC_NOT_ALLOWED.on(right));
235 return;
236 }
237
238 if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, components.platformToKotlinClassMap)) {
239 context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
240 return;
241 }
242 JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
243 if (actualType.equals(targetType)) {
244 // cast to itself: String as String
245 context.trace.report(USELESS_CAST.on(expression));
246 return;
247 }
248 Collection<JetType> possibleTypes = components.dataFlowAnalyzer.getAllPossibleTypes(
249 expression.getLeft(), context.dataFlowInfo, actualType, context);
250
251 boolean checkExactType = checkExactTypeForUselessCast(expression);
252 for (JetType possibleType : possibleTypes) {
253 boolean castIsUseless = checkExactType
254 ? possibleType.equals(targetType)
255 : typeChecker.isSubtypeOf(possibleType, targetType);
256 if (castIsUseless) {
257 context.trace.report(USELESS_CAST.on(expression));
258 return;
259 }
260 }
261 if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
262 context.trace.report(UNCHECKED_CAST.on(expression, actualType, targetType));
263 }
264 }
265
266 // Casting an argument or a receiver to a supertype may be useful to select an exact overload of a method.
267 // Casting to a supertype in other contexts is unlikely to be useful.
268 private static boolean checkExactTypeForUselessCast(JetBinaryExpressionWithTypeRHS expression) {
269 PsiElement parent = expression.getParent();
270 while (parent instanceof JetParenthesizedExpression ||
271 parent instanceof JetLabeledExpression ||
272 parent instanceof JetAnnotatedExpression) {
273 parent = parent.getParent();
274 }
275 if (parent instanceof JetValueArgument) {
276 return true;
277 }
278 if (parent instanceof JetQualifiedExpression) {
279 JetExpression receiver = ((JetQualifiedExpression) parent).getReceiverExpression();
280 return PsiTreeUtil.isAncestor(receiver, expression, false);
281 }
282 return false;
283 }
284
285 @Override
286 public JetTypeInfo visitThisExpression(@NotNull JetThisExpression expression, ExpressionTypingContext context) {
287 JetType result = null;
288 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false);
289
290 switch (resolutionResult.getCode()) {
291 case LABEL_RESOLUTION_ERROR:
292 // Do nothing, the error is already reported
293 break;
294 case NO_THIS:
295 context.trace.report(NO_THIS.on(expression));
296 break;
297 case SUCCESS:
298 result = resolutionResult.getReceiverParameterDescriptor().getType();
299 context.trace.recordType(expression.getInstanceReference(), result);
300 break;
301 }
302 return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
303 }
304
305 @Override
306 public JetTypeInfo visitSuperExpression(@NotNull JetSuperExpression expression, ExpressionTypingContext context) {
307 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
308
309 if (!JetPsiUtil.isLHSOfDot(expression)) {
310 context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
311 return errorInSuper(expression, context);
312 }
313
314 switch (resolutionResult.getCode()) {
315 case LABEL_RESOLUTION_ERROR:
316 // The error is already reported
317 return errorInSuper(expression, context);
318 case NO_THIS:
319 context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
320 return errorInSuper(expression, context);
321 case SUCCESS:
322 JetType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor());
323 if (result != null) {
324 context.trace.recordType(expression.getInstanceReference(), result);
325 }
326 return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
327 }
328 throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
329 }
330
331 private JetTypeInfo errorInSuper(JetSuperExpression expression, ExpressionTypingContext context) {
332 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
333 if (superTypeQualifier != null) {
334 components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
335 }
336 return TypeInfoFactoryPackage.noTypeInfo(context);
337 }
338
339 private JetType checkPossiblyQualifiedSuper(
340 JetSuperExpression expression,
341 ExpressionTypingContext context,
342 ReceiverParameterDescriptor thisReceiver
343 ) {
344 JetType result = null;
345 JetType thisType = thisReceiver.getType();
346 Collection<JetType> supertypes = thisType.getConstructor().getSupertypes();
347 TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
348
349 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
350 if (superTypeQualifier != null) {
351 JetTypeElement typeElement = superTypeQualifier.getTypeElement();
352
353 DeclarationDescriptor classifierCandidate = null;
354 JetType supertype = null;
355 PsiElement redundantTypeArguments = null;
356 if (typeElement instanceof JetUserType) {
357 JetUserType userType = (JetUserType) typeElement;
358 // This may be just a superclass name even if the superclass is generic
359 if (userType.getTypeArguments().isEmpty()) {
360 classifierCandidate = components.typeResolver.resolveClass(context.scope, userType, context.trace);
361 }
362 else {
363 supertype = components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
364 redundantTypeArguments = userType.getTypeArgumentList();
365 }
366 }
367 else {
368 supertype = components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
369 }
370
371 if (supertype != null) {
372 if (supertypes.contains(supertype)) {
373 result = supertype;
374 }
375 }
376 else if (classifierCandidate instanceof ClassDescriptor) {
377 ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
378
379 for (JetType declaredSupertype : supertypes) {
380 if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
381 result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
382 break;
383 }
384 }
385 }
386
387 boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
388 boolean validType = supertype != null && !supertype.isError();
389 if (result == null && (validClassifier || validType)) {
390 context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
391 }
392 else if (redundantTypeArguments != null) {
393 context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
394 }
395 }
396 else {
397 if (UnqualifiedSuperPackage.isPossiblyAmbiguousUnqualifiedSuper(expression, supertypes)) {
398 Collection<JetType> supertypesResolvedFromContext =
399 UnqualifiedSuperPackage.resolveUnqualifiedSuperFromExpressionContext(
400 expression, supertypes, components.builtIns.getAnyType());
401 if (supertypesResolvedFromContext.size() == 1) {
402 JetType singleResolvedType = supertypesResolvedFromContext.iterator().next();
403 result = substitutor.substitute(singleResolvedType, Variance.INVARIANT);
404 }
405 else if (supertypesResolvedFromContext.isEmpty()) {
406 // No supertype found, either with concrete or abstract members.
407 // Resolve to 'Any' (this will cause diagnostics for unresolved member reference).
408 result = components.builtIns.getAnyType();
409 }
410 else {
411 context.trace.report(AMBIGUOUS_SUPER.on(expression));
412 }
413 }
414 else {
415 // supertypes may be empty when all the supertypes are error types (are not resolved, for example)
416 JetType type = supertypes.isEmpty()
417 ? components.builtIns.getAnyType()
418 : supertypes.iterator().next();
419 result = substitutor.substitute(type, Variance.INVARIANT);
420 }
421 }
422 if (result != null) {
423 if (DescriptorUtils.isTrait(thisType.getConstructor().getDeclarationDescriptor())) {
424 if (DescriptorUtils.isClass(result.getConstructor().getDeclarationDescriptor())) {
425 context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression));
426 }
427 }
428 context.trace.recordType(expression.getInstanceReference(), result);
429 context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
430 }
431 if (superTypeQualifier != null) {
432 context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, asJetScope(context.scope));
433 }
434 return result;
435 }
436
437 @NotNull // No class receivers
438 private LabelResolver.LabeledReceiverResolutionResult resolveToReceiver(
439 JetInstanceExpressionWithLabel expression,
440 ExpressionTypingContext context,
441 boolean onlyClassReceivers
442 ) {
443 Name labelName = expression.getLabelNameAsName();
444 if (labelName != null) {
445 LabelResolver.LabeledReceiverResolutionResult resolutionResult =
446 LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, labelName);
447 if (resolutionResult.success()) {
448 ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
449 recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
450 if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) {
451 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(null);
452 }
453 }
454 return resolutionResult;
455 }
456 else {
457 ReceiverParameterDescriptor result = null;
458 List<ReceiverParameterDescriptor> receivers = UtilsPackage.getImplicitReceiversHierarchy(context.scope);
459 if (onlyClassReceivers) {
460 for (ReceiverParameterDescriptor receiver : receivers) {
461 if (isDeclaredInClass(receiver)) {
462 result = receiver;
463 break;
464 }
465 }
466 }
467 else if (!receivers.isEmpty()) {
468 result = receivers.get(0);
469 }
470 if (result != null) {
471 context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
472 recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
473 }
474 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
475 }
476 }
477
478 private void recordThisOrSuperCallInTraceAndCallExtension(
479 ExpressionTypingContext context,
480 ReceiverParameterDescriptor descriptor,
481 JetExpression expression
482 ) {
483 BindingTrace trace = context.trace;
484 Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
485 ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
486 ResolutionCandidate.create(
487 call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
488
489 ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
490 ResolvedCallImpl.create(resolutionCandidate,
491 TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"),
492 TracingStrategy.EMPTY,
493 new DataFlowInfoForArgumentsImpl(call));
494 resolvedCall.markCallAsCompleted();
495
496 trace.record(RESOLVED_CALL, call, resolvedCall);
497 trace.record(CALL, expression, call);
498
499 BasicCallResolutionContext resolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE);
500 resolutionContext.performContextDependentCallChecks(resolvedCall);
501 for (CallChecker checker : components.callCheckers) {
502 checker.check(resolvedCall, resolutionContext);
503 }
504
505 components.symbolUsageValidator.validateCall(descriptor, trace, expression);
506 }
507
508 private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
509 return receiver.getContainingDeclaration() instanceof ClassDescriptor;
510 }
511
512 @Override
513 public JetTypeInfo visitBlockExpression(@NotNull JetBlockExpression expression, ExpressionTypingContext context) {
514 return components.expressionTypingServices.getBlockReturnedType(expression, context, false);
515 }
516
517 @Override
518 public JetTypeInfo visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, ExpressionTypingContext c) {
519 JetType type = resolveClassLiteral(expression, c);
520 if (type != null && !type.isError()) {
521 return components.dataFlowAnalyzer.createCheckedTypeInfo(
522 components.reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression
523 );
524 }
525
526 return TypeInfoFactoryPackage.createTypeInfo(ErrorUtils.createErrorType("Unresolved class"), c);
527 }
528
529 @Nullable
530 private JetType resolveClassLiteral(@NotNull JetClassLiteralExpression expression, ExpressionTypingContext c) {
531 JetTypeReference typeReference = expression.getTypeReference();
532
533 if (typeReference == null) {
534 // "::class" will mean "this::class", a class of "this" instance
535 c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"));
536 return null;
537 }
538
539 TypeResolutionContext context =
540 new TypeResolutionContext(c.scope, c.trace, /* checkBounds = */ false, /* allowBareTypes = */ true);
541 PossiblyBareType possiblyBareType =
542 components.typeResolver.resolvePossiblyBareType(context, typeReference);
543
544 JetType type = null;
545 if (possiblyBareType.isBare()) {
546 if (!possiblyBareType.isNullable()) {
547 ClassifierDescriptor descriptor = possiblyBareType.getBareTypeConstructor().getDeclarationDescriptor();
548 if (descriptor instanceof ClassDescriptor) {
549 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
550 if (KotlinBuiltIns.isNonPrimitiveArray(classDescriptor)) {
551 context.trace.report(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT.on(expression));
552 return null;
553 }
554 type = substituteWithStarProjections(classDescriptor);
555 }
556 }
557 }
558 else {
559 JetType actualType = possiblyBareType.getActualType();
560 if (actualType.isError()) return null;
561 if (isAllowedInClassLiteral(actualType)) {
562 type = actualType;
563 }
564 }
565
566 if (type != null) {
567 return type;
568 }
569
570 context.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression));
571 return null;
572 }
573
574 @NotNull
575 private static JetType substituteWithStarProjections(@NotNull ClassDescriptor descriptor) {
576 TypeConstructor typeConstructor = descriptor.getTypeConstructor();
577 List<TypeProjection> arguments =
578 KotlinPackage.map(typeConstructor.getParameters(), new Function1<TypeParameterDescriptor, TypeProjection>() {
579 @Override
580 public TypeProjection invoke(TypeParameterDescriptor descriptor) {
581 return TypeUtils.makeStarProjection(descriptor);
582 }
583 });
584
585 return JetTypeImpl.create(Annotations.EMPTY, descriptor, false, arguments);
586 }
587
588 private static boolean isAllowedInClassLiteral(@NotNull JetType type) {
589 return isClassAvailableAtRuntime(type, false);
590 }
591
592 private static boolean isClassAvailableAtRuntime(@NotNull JetType type, boolean canBeNullable) {
593 if (type.isMarkedNullable() && !canBeNullable) return false;
594
595 TypeConstructor typeConstructor = type.getConstructor();
596 ClassifierDescriptor typeDeclarationDescriptor = typeConstructor.getDeclarationDescriptor();
597
598 if (typeDeclarationDescriptor instanceof ClassDescriptor) {
599 List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
600 if (parameters.size() != type.getArguments().size()) return false;
601
602 Iterator<TypeProjection> typeArgumentsIterator = type.getArguments().iterator();
603 for (TypeParameterDescriptor parameter : parameters) {
604 if (!parameter.isReified()) return false;
605 TypeProjection typeArgument = typeArgumentsIterator.next();
606 if (typeArgument == null) return false;
607 if (typeArgument.isStarProjection()) return false;
608 if (!isClassAvailableAtRuntime(typeArgument.getType(), true)) return false;
609 }
610
611 return true;
612 }
613 else if (typeDeclarationDescriptor instanceof TypeParameterDescriptor) {
614 return ((TypeParameterDescriptor) typeDeclarationDescriptor).isReified();
615 }
616
617 return false;
618 }
619
620 @Override
621 public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext c) {
622 JetTypeReference typeReference = expression.getTypeReference();
623
624 JetType receiverType =
625 typeReference == null
626 ? null
627 : components.typeResolver.resolveType(c.scope, typeReference, c.trace, false);
628
629 JetSimpleNameExpression callableReference = expression.getCallableReference();
630 if (callableReference.getReferencedName().isEmpty()) {
631 c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
632 JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
633 return components.dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression);
634 }
635
636 JetType result = getCallableReferenceType(expression, receiverType, c);
637 return components.dataFlowAnalyzer.createCheckedTypeInfo(result, c, expression);
638 }
639
640 @Override
641 public JetTypeInfo visitObjectLiteralExpression(@NotNull final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
642 final JetType[] result = new JetType[1];
643 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace,
644 "trace to resolve object literal expression", expression);
645 ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {
646
647 @Override
648 public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) {
649 if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
650 JetType defaultType = DeferredType.createRecursionIntolerant(components.globalContext.getStorageManager(),
651 context.trace,
652 new Function0<JetType>() {
653 @Override
654 public JetType invoke() {
655 return descriptor.getDefaultType();
656 }
657 });
658 result[0] = defaultType;
659 }
660 }
661 };
662 ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
663 traceAdapter.addHandler(CLASS, handler);
664 components.localClassifierAnalyzer.processClassOrObject(null, // don't need to add classifier of object literal to any scope
665 context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT),
666 context.scope.getOwnerDescriptor(),
667 expression.getObjectDeclaration());
668 temporaryTrace.commit();
669 DataFlowInfo resultFlowInfo = context.dataFlowInfo;
670 for (JetDelegationSpecifier specifier: expression.getObjectDeclaration().getDelegationSpecifiers()) {
671 if (specifier instanceof JetDelegatorToSuperCall) {
672 JetDelegatorToSuperCall delegator = (JetDelegatorToSuperCall)specifier;
673 JetTypeInfo delegatorTypeInfo = context.trace.get(EXPRESSION_TYPE_INFO, delegator.getCalleeExpression());
674 if (delegatorTypeInfo != null) {
675 resultFlowInfo = resultFlowInfo.and(delegatorTypeInfo.getDataFlowInfo());
676 }
677 }
678 }
679 // Breaks are not possible inside constructor arguments, so jumpPossible or jumpFlowInfo are not necessary here
680 JetTypeInfo resultTypeInfo = components.dataFlowAnalyzer.checkType(TypeInfoFactoryPackage.createTypeInfo(result[0], resultFlowInfo),
681 expression,
682 context);
683 // We have to record it here,
684 // otherwise ExpressionTypingVisitorDispatcher records wrong information
685 context.trace.record(EXPRESSION_TYPE_INFO, expression, resultTypeInfo);
686 context.trace.record(PROCESSED, expression);
687 return resultTypeInfo;
688 }
689
690 @Nullable
691 private JetType getCallableReferenceType(
692 @NotNull JetCallableReferenceExpression expression,
693 @Nullable JetType lhsType,
694 @NotNull ExpressionTypingContext context
695 ) {
696 JetSimpleNameExpression reference = expression.getCallableReference();
697
698 boolean[] resolved = new boolean[1];
699 CallableDescriptor descriptor = CallableReferencesPackage.resolveCallableReferenceTarget(
700 expression, lhsType, context, resolved, components.callResolver);
701 if (!resolved[0]) {
702 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
703 }
704 if (descriptor == null) return null;
705
706 return CallableReferencesPackage.createReflectionTypeForResolvedCallableReference(expression, descriptor, context, components.reflectionTypes);
707 }
708
709 @Override
710 public JetTypeInfo visitQualifiedExpression(@NotNull JetQualifiedExpression expression, ExpressionTypingContext context) {
711 CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
712 return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
713 }
714
715 @Override
716 public JetTypeInfo visitCallExpression(@NotNull JetCallExpression expression, ExpressionTypingContext context) {
717 CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
718 return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
719 }
720
721 @Override
722 public JetTypeInfo visitUnaryExpression(@NotNull JetUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
723 ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
724 ? contextWithExpectedType
725 : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
726
727 JetExpression baseExpression = expression.getBaseExpression();
728 if (baseExpression == null) return TypeInfoFactoryPackage.noTypeInfo(context);
729
730 JetSimpleNameExpression operationSign = expression.getOperationReference();
731
732 IElementType operationType = operationSign.getReferencedNameElementType();
733
734 // Special case for expr!!
735 if (operationType == JetTokens.EXCLEXCL) {
736 return visitExclExclExpression(expression, context);
737 }
738
739 // Type check the base expression
740 JetTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
741 JetType type = ExpressionTypingUtils.safeGetType(typeInfo);
742 ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
743
744 Call call = CallMaker.makeCall(receiver, expression);
745
746 // Conventions for unary operations
747 Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
748 if (name == null) {
749 context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
750 return typeInfo.clearType();
751 }
752
753 // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
754 if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
755 JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
756 TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace
757 .create(context.trace, "trace to resolve array access set method for unary expression", expression);
758 ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
759 resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
760 }
761
762 // Resolve the operation reference
763 OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
764 context, call, expression.getOperationReference(), name);
765
766 if (!resolutionResults.isSuccess()) {
767 return typeInfo.clearType();
768 }
769
770 // Computing the return type
771 JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
772 JetType result;
773 if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
774 assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
775 if (KotlinBuiltIns.isUnit(returnType)) {
776 result = ErrorUtils.createErrorType(components.builtIns.getUnit().getName().asString());
777 context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
778 }
779 else {
780 JetType receiverType = receiver.getType();
781 if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
782 context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
783 }
784 else {
785 context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
786 JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
787 checkLValue(context.trace, context, baseExpression, stubExpression);
788 }
789 // x++ type is x type, but ++x type is x.inc() type
790 DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(call.getExplicitReceiver(), contextWithExpectedType);
791 if (expression instanceof JetPrefixExpression) {
792 result = returnType;
793 }
794 else {
795 result = receiverType;
796 // Also record data flow information for x++ value (= x)
797 DataFlowValue returnValue = DataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
798 typeInfo = typeInfo.replaceDataFlowInfo(typeInfo.getDataFlowInfo().assign(returnValue, receiverValue));
799 }
800 }
801 }
802 else {
803 result = returnType;
804 }
805
806 CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
807 expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
808 );
809 if (value != null) {
810 return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
811 }
812
813 return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result),
814 expression,
815 contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
816 }
817
818 private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
819 JetExpression baseExpression = expression.getBaseExpression();
820 assert baseExpression != null;
821 JetSimpleNameExpression operationSign = expression.getOperationReference();
822 assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
823
824 // TODO: something must be done for not to lose safe call chain information here
825 // See also CallExpressionResolver.getSimpleNameExpressionTypeInfo, .getQualifiedExpressionTypeInfo
826 Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Collections.singletonList(baseExpression));
827 components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
828 call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
829 JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
830
831 if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) {
832 context.trace.report(NOT_NULL_ASSERTION_ON_FUNCTION_LITERAL.on(operationSign));
833 return baseTypeInfo;
834 }
835 assert baseTypeInfo != null : "Base expression was not processed: " + expression;
836 JetType baseType = baseTypeInfo.getType();
837 if (baseType == null) {
838 return baseTypeInfo;
839 }
840 DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
841 if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
842 context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
843 }
844 else {
845 DataFlowValue value = createDataFlowValue(baseExpression, baseType, context);
846 baseTypeInfo = baseTypeInfo.replaceDataFlowInfo(dataFlowInfo.disequate(value, DataFlowValue.NULL));
847 }
848 JetType resultingType = TypeUtils.makeNotNullable(baseType);
849 if (context.contextDependency == DEPENDENT) {
850 return baseTypeInfo.replaceType(resultingType);
851 }
852
853 // The call to checkType() is only needed here to execute additionalTypeCheckers, hence the NO_EXPECTED_TYPE
854 return components.dataFlowAnalyzer.checkType(baseTypeInfo.replaceType(resultingType), expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
855 }
856
857 @Override
858 public JetTypeInfo visitLabeledExpression(
859 @NotNull JetLabeledExpression expression, ExpressionTypingContext context
860 ) {
861 return visitLabeledExpression(expression, context, false);
862 }
863
864 @NotNull
865 public JetTypeInfo visitLabeledExpression(
866 @NotNull JetLabeledExpression expression,
867 @NotNull ExpressionTypingContext context,
868 boolean isStatement
869 ) {
870 JetSimpleNameExpression labelExpression = expression.getTargetLabel();
871 if (labelExpression != null) {
872 PsiElement labelIdentifier = labelExpression.getIdentifier();
873 UnderscoreChecker.INSTANCE$.checkIdentifier(labelIdentifier, context.trace);
874 }
875 JetExpression baseExpression = expression.getBaseExpression();
876 if (baseExpression == null) return TypeInfoFactoryPackage.noTypeInfo(context);
877
878 return facade.getTypeInfo(baseExpression, context, isStatement);
879 }
880
881 private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
882 JetType type = context.trace.getType(expression);
883 assert type != null : "This method is only supposed to be called when the type is not null";
884 return isKnownToBeNotNull(expression, type, context);
885 }
886
887 private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
888 DataFlowValue dataFlowValue = createDataFlowValue(expression, jetType, context);
889 return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
890 }
891
892 /**
893 * @return {@code true} iff expression can be assigned to
894 */
895 public boolean checkLValue(
896 @NotNull BindingTrace trace,
897 @NotNull ExpressionTypingContext context,
898 @NotNull JetExpression expression,
899 @Nullable JetExpression rightHandSide
900 ) {
901 return checkLValue(trace, context, expression, rightHandSide, false);
902 }
903
904 private boolean checkLValue(
905 @NotNull BindingTrace trace,
906 @NotNull ExpressionTypingContext context,
907 @NotNull JetExpression expressionWithParenthesis,
908 @Nullable JetExpression rightHandSide,
909 boolean canBeThis
910 ) {
911 JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
912 if (expression instanceof JetArrayAccessExpression) {
913 JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) expression;
914 JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
915 if (arrayExpression == null || rightHandSide == null) return false;
916
917 TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
918 ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
919 JetTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
920 return info.getType() != null;
921 }
922
923 if (canBeThis && expression instanceof JetThisExpression) return true;
924 VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
925
926 boolean result = true;
927 JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
928 if (reportOn instanceof JetQualifiedExpression) {
929 JetExpression selector = ((JetQualifiedExpression) reportOn).getSelectorExpression();
930 if (selector != null)
931 reportOn = selector;
932 }
933
934 if (variable instanceof PropertyDescriptor) {
935 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
936 PropertySetterDescriptor setter = propertyDescriptor.getSetter();
937 if (propertyDescriptor.isSetterProjectedOut()) {
938 trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
939 result = false;
940 } else {
941 if (setter != null) {
942 components.symbolUsageValidator.validateCall(setter, trace, reportOn);
943 }
944 }
945 }
946
947 if (variable == null) {
948 trace.report(VARIABLE_EXPECTED.on(reportOn));
949 result = false;
950 }
951 else if (!variable.isVar()) {
952 result = false;
953 }
954
955 return result;
956 }
957
958 @Override
959 public JetTypeInfo visitBinaryExpression(@NotNull JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
960 ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
961 ? contextWithExpectedType
962 : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
963
964 JetSimpleNameExpression operationSign = expression.getOperationReference();
965 JetExpression left = expression.getLeft();
966 JetExpression right = expression.getRight();
967 IElementType operationType = operationSign.getReferencedNameElementType();
968
969 JetTypeInfo result;
970
971 //Expressions that can depend on expected type
972 if (operationType == JetTokens.IDENTIFIER) {
973 Name referencedName = operationSign.getReferencedNameAsName();
974 result = getTypeInfoForBinaryCall(referencedName, context, expression);
975 }
976 else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
977 Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
978 result = getTypeInfoForBinaryCall(referencedName, context, expression);
979 }
980 else if (operationType == JetTokens.ELVIS) {
981 //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
982 return visitElvisExpression(expression, context);
983 }
984
985 //Expressions that don't depend on expected type
986 else if (operationType == JetTokens.EQ) {
987 result = visitAssignment(expression, context);
988 }
989 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
990 result = visitAssignmentOperation(expression, context);
991 }
992 else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
993 result = visitComparison(expression, context, operationSign);
994 }
995 else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
996 result = visitEquality(expression, context, operationSign, left, right);
997 }
998 else if (OperatorConventions.IDENTITY_EQUALS_OPERATIONS.contains(operationType)) {
999 context.trace.record(REFERENCE_TARGET, operationSign, components.builtIns.getIdentityEquals());
1000 ensureNonemptyIntersectionOfOperandTypes(expression, context);
1001 // TODO : Check comparison pointlessness
1002 result = TypeInfoFactoryPackage.createTypeInfo(components.builtIns.getBooleanType(), context);
1003 }
1004 else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
1005 ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
1006 result = checkInExpression(expression, operationSign, leftArgument, right, context);
1007 }
1008 else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
1009 result = visitBooleanOperationExpression(operationType, left, right, context);
1010 }
1011 else {
1012 context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
1013 result = TypeInfoFactoryPackage.noTypeInfo(context);
1014 }
1015 CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
1016 expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
1017 );
1018 if (value != null) {
1019 return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
1020 }
1021 return components.dataFlowAnalyzer.checkType(result, expression, contextWithExpectedType);
1022 }
1023
1024 private JetTypeInfo visitEquality(
1025 JetBinaryExpression expression,
1026 ExpressionTypingContext context,
1027 JetSimpleNameExpression operationSign,
1028 final JetExpression left,
1029 final JetExpression right
1030 ) {
1031 if (right == null || left == null) {
1032 ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
1033 ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
1034 return TypeInfoFactoryPackage.createTypeInfo(components.builtIns.getBooleanType(), context);
1035 }
1036
1037 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
1038
1039 DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1040 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1041
1042 JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
1043
1044 TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
1045 context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
1046 traceInterpretingRightAsNullableAny.recordType(right, components.builtIns.getNullableAnyType());
1047
1048 // Nothing? has no members, and `equals()` would be unresolved on it
1049 JetType leftType = leftTypeInfo.getType();
1050 if (leftType != null && KotlinBuiltIns.isNothingOrNullableNothing(leftType)) {
1051 traceInterpretingRightAsNullableAny.recordType(left, components.builtIns.getNullableAnyType());
1052 }
1053
1054 ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
1055 ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, newContext);
1056 Call call = CallMaker.makeCallWithExpressions(
1057 expression,
1058 receiver,
1059 // semantically, a call to `==` is a safe call
1060 new JetPsiFactory(expression.getProject()).createSafeCallNode(),
1061 operationSign,
1062 Collections.singletonList(right)
1063 );
1064 OverloadResolutionResults<FunctionDescriptor> resolutionResults =
1065 components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
1066
1067 traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
1068 @Override
1069 public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
1070 // the type of the right (and sometimes left) expression isn't 'Any?' actually
1071 if ((key == right || key == left) && slice == EXPRESSION_TYPE_INFO) return false;
1072
1073 // a hack due to KT-678
1074 // without this line an smartcast is reported on the receiver (if it was previously checked for not-null)
1075 // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
1076 if (key == left && slice == SMARTCAST) return false;
1077
1078 return true;
1079 }
1080 }, true);
1081
1082 if (resolutionResults.isSuccess()) {
1083 FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
1084 if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(),
1085 context)) {
1086 ensureNonemptyIntersectionOfOperandTypes(expression, context);
1087 }
1088 }
1089 else {
1090 if (resolutionResults.isAmbiguity()) {
1091 context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
1092 }
1093 else {
1094 context.trace.report(EQUALS_MISSING.on(operationSign));
1095 }
1096 }
1097 return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
1098 }
1099
1100 @NotNull
1101 private JetTypeInfo visitComparison(
1102 @NotNull JetBinaryExpression expression,
1103 @NotNull ExpressionTypingContext context,
1104 @NotNull JetSimpleNameExpression operationSign
1105 ) {
1106 JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
1107 JetType compareToReturnType = typeInfo.getType();
1108 JetType type = null;
1109 if (compareToReturnType != null && !compareToReturnType.isError()) {
1110 if (JetTypeChecker.DEFAULT.equalTypes(components.builtIns.getIntType(), compareToReturnType)) {
1111 type = components.builtIns.getBooleanType();
1112 }
1113 else {
1114 context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
1115 }
1116 }
1117 return typeInfo.replaceType(type);
1118 }
1119
1120 @NotNull
1121 private JetTypeInfo visitBooleanOperationExpression(
1122 @Nullable IElementType operationType,
1123 @Nullable JetExpression left,
1124 @Nullable JetExpression right,
1125 @NotNull ExpressionTypingContext context
1126 ) {
1127 JetType booleanType = components.builtIns.getBooleanType();
1128 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
1129 DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1130
1131 LexicalWritableScope leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
1132 // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
1133 boolean isAnd = operationType == JetTokens.ANDAND;
1134 DataFlowInfo flowInfoLeft = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
1135 LexicalWritableScope rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
1136
1137 ExpressionTypingContext contextForRightExpr =
1138 context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
1139 if (right != null) {
1140 facade.getTypeInfo(right, contextForRightExpr);
1141 }
1142 return leftTypeInfo.replaceType(booleanType);
1143 }
1144
1145 @NotNull
1146 private JetTypeInfo visitElvisExpression(
1147 @NotNull JetBinaryExpression expression,
1148 @NotNull ExpressionTypingContext contextWithExpectedType
1149 ) {
1150 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
1151 JetExpression left = expression.getLeft();
1152 JetExpression right = expression.getRight();
1153
1154 if (left == null || right == null) {
1155 getTypeInfoOrNullType(left, context, facade);
1156 return TypeInfoFactoryPackage.noTypeInfo(context);
1157 }
1158
1159 Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
1160 ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
1161 call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
1162 JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
1163 if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) {
1164 context.trace.report(USELESS_ELVIS_ON_FUNCTION_LITERAL.on(expression.getOperationReference()));
1165 if (leftTypeInfo == null) return TypeInfoFactoryPackage.noTypeInfo(context);
1166 }
1167 assert leftTypeInfo != null : "Left expression was not processed: " + expression;
1168 JetType leftType = leftTypeInfo.getType();
1169 if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
1170 context.trace.report(USELESS_ELVIS.on(expression, leftType));
1171 }
1172 JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
1173 if (rightTypeInfo == null && ArgumentTypeResolver.isFunctionLiteralArgument(right, context)) {
1174 // the type is computed later in call completer according to the '?:' semantics as a function
1175 return TypeInfoFactoryPackage.noTypeInfo(context);
1176 }
1177 assert rightTypeInfo != null : "Right expression was not processed: " + expression;
1178 boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
1179 JetType rightType = rightTypeInfo.getType();
1180
1181 // Only left argument DFA is taken into account here: we cannot be sure that right argument is executed
1182 DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getInfo(call.getValueArguments().get(1));
1183 if (leftType != null) {
1184 DataFlowValue leftValue = createDataFlowValue(left, leftType, context);
1185 DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
1186 // left argument is considered not-null if it's not-null also in right part or if we have jump in right part
1187 if ((rightType != null && KotlinBuiltIns.isNothingOrNullableNothing(rightType) && !rightType.isMarkedNullable())
1188 || !rightDataFlowInfo.getNullability(leftValue).canBeNull()) {
1189 dataFlowInfo = dataFlowInfo.disequate(leftValue, DataFlowValue.NULL);
1190 }
1191 }
1192 JetType type = resolvedCall.getResultingDescriptor().getReturnType();
1193 if (type == null || rightType == null) return TypeInfoFactoryPackage.noTypeInfo(dataFlowInfo);
1194
1195 // Sometimes return type for special call for elvis operator might be nullable,
1196 // but result is not nullable if the right type is not nullable
1197 if (!TypeUtils.isNullableType(rightType) && TypeUtils.isNullableType(type)) {
1198 type = TypeUtils.makeNotNullable(type);
1199 }
1200 if (context.contextDependency == DEPENDENT) {
1201 return TypeInfoFactoryPackage.createTypeInfo(type, dataFlowInfo);
1202 }
1203
1204 // If break or continue was possible, take condition check info as the jump info
1205 return TypeInfoFactoryPackage.createTypeInfo(components.dataFlowAnalyzer.checkType(type, expression, contextWithExpectedType),
1206 dataFlowInfo,
1207 loopBreakContinuePossible,
1208 context.dataFlowInfo);
1209 }
1210
1211 @NotNull
1212 public JetTypeInfo checkInExpression(
1213 @NotNull JetElement callElement,
1214 @NotNull JetSimpleNameExpression operationSign,
1215 @NotNull ValueArgument leftArgument,
1216 @Nullable JetExpression right,
1217 @NotNull ExpressionTypingContext context
1218 ) {
1219 JetExpression left = leftArgument.getArgumentExpression();
1220 ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1221 if (right == null) {
1222 if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1223 return TypeInfoFactoryPackage.noTypeInfo(context);
1224 }
1225
1226 JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithNoExpectedType);
1227 DataFlowInfo dataFlowInfo = rightTypeInfo.getDataFlowInfo();
1228
1229 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1230 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1231
1232 OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1233 contextWithDataFlow,
1234 CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
1235 operationSign,
1236 OperatorConventions.CONTAINS);
1237 JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1238 ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
1239
1240 if (left != null) {
1241 dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1242 rightTypeInfo = rightTypeInfo.replaceDataFlowInfo(dataFlowInfo);
1243 }
1244
1245 if (resolutionResult.isSuccess()) {
1246 return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
1247 }
1248 else {
1249 return rightTypeInfo.clearType();
1250 }
1251 }
1252
1253
1254 private boolean ensureBooleanResult(JetExpression operationSign, Name name, JetType resultType, ExpressionTypingContext context) {
1255 return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'", context);
1256 }
1257
1258 private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName, ExpressionTypingContext context) {
1259 if (resultType != null) {
1260 // TODO : Relax?
1261 if (!components.builtIns.isBooleanOrSubtype(resultType)) {
1262 context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, subjectName, components.builtIns.getBooleanType(), resultType));
1263 return false;
1264 }
1265 }
1266 return true;
1267 }
1268
1269 private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, final ExpressionTypingContext context) {
1270 JetExpression left = expression.getLeft();
1271 if (left == null) return;
1272
1273 JetExpression right = expression.getRight();
1274
1275 // TODO : duplicated effort for == and !=
1276 JetType leftType = facade.getTypeInfo(left, context).getType();
1277 if (leftType != null && right != null) {
1278 JetType rightType = facade.getTypeInfo(right, context).getType();
1279
1280 if (rightType != null) {
1281 if (components.typeIntersector.isIntersectionEmpty(leftType, rightType)) {
1282 context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1283 }
1284 SenselessComparisonChecker.checkSenselessComparisonWithNull(
1285 expression, left, right, context,
1286 new Function1<JetExpression, JetType>() {
1287 @Override
1288 public JetType invoke(JetExpression expression) {
1289 return facade.getTypeInfo(expression, context).getType();
1290 }
1291 },
1292 new Function1<DataFlowValue, Nullability>() {
1293 @Override
1294 public Nullability invoke(DataFlowValue value) {
1295 return context.dataFlowInfo.getNullability(value);
1296 }
1297 });
1298 }
1299 }
1300 }
1301
1302 @NotNull
1303 private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1304 return assignmentIsNotAnExpressionError(expression, context);
1305 }
1306
1307 @NotNull
1308 private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1309 return assignmentIsNotAnExpressionError(expression, context);
1310 }
1311
1312 @NotNull
1313 private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1314 facade.checkStatementType(expression, context);
1315 context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1316 return TypeInfoFactoryPackage.noTypeInfo(context);
1317 }
1318
1319 @Override
1320 public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
1321 return components.dataFlowAnalyzer.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
1322 }
1323
1324 @NotNull
1325 public JetTypeInfo getTypeInfoForBinaryCall(
1326 @NotNull Name name,
1327 @NotNull ExpressionTypingContext context,
1328 @NotNull JetBinaryExpression binaryExpression
1329 ) {
1330 JetExpression left = binaryExpression.getLeft();
1331 JetTypeInfo typeInfo;
1332 if (left != null) {
1333 //left here is a receiver, so it doesn't depend on expected type
1334 typeInfo = facade.getTypeInfo(left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE));
1335 } else {
1336 typeInfo = TypeInfoFactoryPackage.noTypeInfo(context);
1337 }
1338 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
1339
1340 OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1341 if (left != null) {
1342 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1343 resolutionResults = components.callResolver.resolveBinaryCall(
1344 contextWithDataFlow.replaceScope(context.scope),
1345 receiver, binaryExpression, name
1346 );
1347 }
1348 else {
1349 resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1350 }
1351
1352 if (resolutionResults.isSingleResult()) {
1353 typeInfo = typeInfo.replaceDataFlowInfo(resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo());
1354 }
1355
1356 return typeInfo.replaceType(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency));
1357 }
1358
1359 @Override
1360 public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
1361 context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1362 return TypeInfoFactoryPackage.noTypeInfo(context);
1363 }
1364
1365 @Override
1366 public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
1367 if (!JetPsiUtil.isLHSOfDot(expression)) {
1368 context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1369 }
1370 return TypeInfoFactoryPackage.noTypeInfo(context);
1371 }
1372
1373 @Override
1374 public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1375 final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1376 class StringTemplateVisitor extends JetVisitorVoid {
1377 private JetTypeInfo typeInfo = TypeInfoFactoryPackage.noTypeInfo(context);
1378
1379 @Override
1380 public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
1381 JetExpression entryExpression = entry.getExpression();
1382 if (entryExpression != null) {
1383 typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
1384 }
1385 }
1386
1387 @Override
1388 public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
1389 CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1390 Diagnostic diagnostic = value.getDiagnostic();
1391 if (diagnostic != null) {
1392 context.trace.report(diagnostic);
1393 }
1394 }
1395 }
1396 StringTemplateVisitor visitor = new StringTemplateVisitor();
1397 for (JetStringTemplateEntry entry : expression.getEntries()) {
1398 entry.accept(visitor);
1399 }
1400 components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType);
1401 return components.dataFlowAnalyzer.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
1402 expression,
1403 contextWithExpectedType);
1404 }
1405
1406 @Override
1407 public JetTypeInfo visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, ExpressionTypingContext context) {
1408 return visitAnnotatedExpression(expression, context, false);
1409 }
1410
1411 public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1412 components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
1413
1414 JetExpression baseExpression = expression.getBaseExpression();
1415 if (baseExpression == null) {
1416 return TypeInfoFactoryPackage.noTypeInfo(context);
1417 }
1418 return facade.getTypeInfo(baseExpression, context, isStatement);
1419 }
1420
1421 @Override
1422 public JetTypeInfo visitJetElement(@NotNull JetElement element, ExpressionTypingContext context) {
1423 context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1424 return TypeInfoFactoryPackage.noTypeInfo(context);
1425 }
1426
1427 @NotNull
1428 /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1429 return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1430 }
1431
1432 @NotNull
1433 /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1434 return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1435 }
1436
1437 @NotNull
1438 private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1439 @Nullable JetExpression rightHandSide, //only for 'set' method
1440 @NotNull ExpressionTypingContext oldContext,
1441 @NotNull BindingTrace traceForResolveResult,
1442 boolean isGet) {
1443 JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1444 if (arrayExpression == null) return TypeInfoFactoryPackage.noTypeInfo(oldContext);
1445
1446
1447 JetTypeInfo arrayTypeInfo = facade.safeGetTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1448 .replaceContextDependency(INDEPENDENT));
1449 JetType arrayType = ExpressionTypingUtils.safeGetType(arrayTypeInfo);
1450
1451 ExpressionTypingContext context = oldContext.replaceDataFlowInfo(arrayTypeInfo.getDataFlowInfo());
1452 ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1453 if (!isGet) assert rightHandSide != null;
1454
1455 Call call = isGet
1456 ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1457 : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD);
1458 OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1459 context, call, arrayAccessExpression, Name.identifier(isGet ? "get" : "set"));
1460
1461 List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1462 // The accumulated data flow info of all index expressions is saved on the last index
1463 JetTypeInfo resultTypeInfo = arrayTypeInfo;
1464 if (!indices.isEmpty()) {
1465 resultTypeInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context);
1466 }
1467
1468 if (!isGet) {
1469 resultTypeInfo = facade.getTypeInfo(rightHandSide, context);
1470 }
1471
1472 if (!functionResults.isSingleResult()) {
1473 traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1474 return resultTypeInfo.clearType();
1475 }
1476 traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression,
1477 functionResults.getResultingCall());
1478 return resultTypeInfo.replaceType(functionResults.getResultingDescriptor().getReturnType());
1479 }
1480 }