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.intellij.psi.PsiElement;
021 import com.intellij.psi.tree.IElementType;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.JetNodeTypes;
025 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
026 import org.jetbrains.jet.lang.descriptors.*;
027 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
028 import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
029 import org.jetbrains.jet.lang.diagnostics.Errors;
030 import org.jetbrains.jet.lang.psi.*;
031 import org.jetbrains.jet.lang.resolve.*;
032 import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
033 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
034 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
035 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
036 import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
037 import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
038 import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
039 import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
040 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
041 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
042 import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
043 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
044 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
045 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
046 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
047 import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
048 import org.jetbrains.jet.lang.resolve.constants.*;
049 import org.jetbrains.jet.lang.resolve.constants.StringValue;
050 import org.jetbrains.jet.lang.resolve.name.LabelName;
051 import org.jetbrains.jet.lang.resolve.name.Name;
052 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
053 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
054 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
055 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
056 import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
057 import org.jetbrains.jet.lang.types.*;
058 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
059 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
060 import org.jetbrains.jet.lexer.JetTokens;
061 import org.jetbrains.jet.utils.ThrowingList;
062
063 import java.util.*;
064
065 import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
066 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
067 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
068 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
069 import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
070 import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
071 import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
072 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
073 import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
074 import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
075 import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.resolveSpecialConstructionAsCall;
076 import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
077
078 @SuppressWarnings("SuspiciousMethodCalls")
079 public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
080
081 private final PlatformToKotlinClassMap platformToKotlinClassMap;
082
083 protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade, @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
084 super(facade);
085 this.platformToKotlinClassMap = platformToKotlinClassMap;
086 }
087
088 @Override
089 public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) {
090 // TODO : other members
091 // TODO : type substitutions???
092 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver();
093 JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
094 JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context);
095 ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope);
096 return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this
097 }
098
099 @Override
100 public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
101 return visitParenthesizedExpression(expression, context, false);
102 }
103
104 public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
105 JetExpression innerExpression = expression.getExpression();
106 if (innerExpression == null) {
107 return JetTypeInfo.create(null, context.dataFlowInfo);
108 }
109 JetTypeInfo typeInfo = facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement);
110 return DataFlowUtils.checkType(typeInfo, expression, context);
111 }
112
113 private static JetTypeInfo createNumberValueTypeInfo(
114 @NotNull NumberValueTypeConstructor numberValueTypeConstructor,
115 @NotNull Number value,
116 @NotNull DataFlowInfo dataFlowInfo
117 ) {
118 return JetTypeInfo.create(new JetTypeImpl(
119 Collections.<AnnotationDescriptor>emptyList(), numberValueTypeConstructor,
120 false, Collections.<TypeProjection>emptyList(),
121 ErrorUtils.createErrorScope("Scope for number value type (" + value + ")", true)), dataFlowInfo);
122 }
123
124 @Override
125 public JetTypeInfo visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) {
126 IElementType elementType = expression.getNode().getElementType();
127 String text = expression.getNode().getText();
128 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
129 CompileTimeConstantResolver compileTimeConstantResolver = context.getCompileTimeConstantResolver();
130
131 if (noExpectedType(context.expectedType) && context.contextDependency == DEPENDENT) {
132 if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
133 Long longValue = CompileTimeConstantResolver.parseLongValue(text);
134 if (longValue != null) {
135 return createNumberValueTypeInfo(IntegerValueTypeConstructor.create(longValue), longValue, context.dataFlowInfo);
136 }
137 }
138 else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
139 Double doubleValue = CompileTimeConstantResolver.parseDoubleValue(text);
140 if (doubleValue != null) {
141 return createNumberValueTypeInfo(DoubleValueTypeConstructor.create(doubleValue), doubleValue, context.dataFlowInfo);
142 }
143 }
144 }
145
146 CompileTimeConstant<?> value = compileTimeConstantResolver.getCompileTimeConstant(expression, context.expectedType);
147 if (value instanceof ErrorValue) {
148 // 'checkType' for 'ContextDependency.DEPENDENT' will take place in 'completeInferenceForArgument'
149 if (context.contextDependency == INDEPENDENT) {
150 context.trace.report(ERROR_COMPILE_TIME_VALUE.on(expression, ((ErrorValue) value).getMessage()));
151 }
152 return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo);
153 }
154 context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, value);
155 return DataFlowUtils.checkType(value.getType(builtIns), expression, context, context.dataFlowInfo);
156 }
157
158 @Override
159 public JetTypeInfo visitBinaryWithTypeRHSExpression(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 JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
166 return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
167 }
168
169 JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true);
170 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
171
172 if (isTypeFlexible(left) || operationType == JetTokens.COLON) {
173
174 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
175 checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
176 return DataFlowUtils.checkType(targetType, expression, context, typeInfo.getDataFlowInfo());
177 }
178
179 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
180
181 DataFlowInfo dataFlowInfo = context.dataFlowInfo;
182 if (typeInfo.getType() != null) {
183 checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType());
184 dataFlowInfo = typeInfo.getDataFlowInfo();
185 if (operationType == JetTokens.AS_KEYWORD) {
186 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext());
187 dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
188 }
189 }
190 JetType result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
191 return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
192 }
193
194 private void checkBinaryWithTypeRHS(
195 @NotNull JetBinaryExpressionWithTypeRHS expression,
196 @NotNull ExpressionTypingContext context,
197 @NotNull JetType targetType,
198 @Nullable JetType actualType
199 ) {
200 if (actualType == null) return;
201 JetSimpleNameExpression operationSign = expression.getOperationReference();
202 IElementType operationType = operationSign.getReferencedNameElementType();
203 if (operationType == JetTokens.COLON) {
204 return;
205 }
206 if (operationType != JetTokens.AS_KEYWORD && operationType != JetTokens.AS_SAFE) {
207 context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
208 return;
209 }
210 checkForCastImpossibility(expression, actualType, targetType, context);
211 }
212
213 private void checkForCastImpossibility(
214 JetBinaryExpressionWithTypeRHS expression,
215 JetType actualType,
216 JetType targetType,
217 ExpressionTypingContext context
218 ) {
219 if (actualType == null || noExpectedType(targetType)) return;
220
221 if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, platformToKotlinClassMap)) {
222 context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
223 }
224 else {
225 JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
226 // Upcast?
227 if (typeChecker.isSubtypeOf(actualType, targetType)) {
228 if (!typeChecker.isSubtypeOf(targetType, actualType)) {
229 // proper upcast: String as Any
230 context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationReference()));
231 }
232 else {
233 // cast to itself: String as String
234 context.trace.report(USELESS_CAST.on(expression.getOperationReference()));
235 }
236 }
237 else if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
238 context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
239 }
240 }
241 }
242
243 @Override
244 public JetTypeInfo visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) {
245 JetType result = null;
246 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false);
247
248 switch (resolutionResult.getCode()) {
249 case LABEL_RESOLUTION_ERROR:
250 // Do nothing, the error is already reported
251 break;
252 case NO_THIS:
253 context.trace.report(NO_THIS.on(expression));
254 break;
255 case SUCCESS:
256 result = resolutionResult.getReceiverParameterDescriptor().getType();
257 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
258 break;
259 }
260 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
261 }
262
263 @Override
264 public JetTypeInfo visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) {
265 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
266
267 if (context.expressionPosition == ExpressionPosition.FREE) {
268 context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
269 return errorInSuper(expression, context);
270 }
271 switch (resolutionResult.getCode()) {
272 case LABEL_RESOLUTION_ERROR:
273 // The error is already reported
274 return errorInSuper(expression, context);
275 case NO_THIS:
276 context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
277 return errorInSuper(expression, context);
278 case SUCCESS:
279 JetType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor());
280 if (result != null) {
281 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
282 }
283 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
284 }
285 throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
286 }
287
288 private static JetTypeInfo errorInSuper(JetSuperExpression expression, ExpressionTypingContext context) {
289 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
290 if (superTypeQualifier != null) {
291 context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
292 }
293 return JetTypeInfo.create(null, context.dataFlowInfo);
294 }
295
296 private static JetType checkPossiblyQualifiedSuper(
297 JetSuperExpression expression,
298 ExpressionTypingContext context,
299 ReceiverParameterDescriptor thisReceiver
300 ) {
301 JetType result = null;
302 JetType thisType = thisReceiver.getType();
303 Collection<JetType> supertypes = thisType.getConstructor().getSupertypes();
304 TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
305
306 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
307 if (superTypeQualifier != null) {
308 JetTypeElement typeElement = superTypeQualifier.getTypeElement();
309
310 DeclarationDescriptor classifierCandidate = null;
311 JetType supertype = null;
312 PsiElement redundantTypeArguments = null;
313 if (typeElement instanceof JetUserType) {
314 JetUserType userType = (JetUserType) typeElement;
315 // This may be just a superclass name even if the superclass is generic
316 if (userType.getTypeArguments().isEmpty()) {
317 classifierCandidate = context.expressionTypingServices.getTypeResolver().resolveClass(context.scope, userType, context.trace);
318 }
319 else {
320 supertype = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
321 redundantTypeArguments = userType.getTypeArgumentList();
322 }
323 }
324 else {
325 supertype = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
326 }
327
328 if (supertype != null) {
329 if (supertypes.contains(supertype)) {
330 result = supertype;
331 }
332 }
333 else if (classifierCandidate instanceof ClassDescriptor) {
334 ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
335
336 for (JetType declaredSupertype : supertypes) {
337 if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
338 result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
339 break;
340 }
341 }
342 }
343
344 boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
345 boolean validType = supertype != null && !ErrorUtils.isErrorType(supertype);
346 if (result == null && (validClassifier || validType)) {
347 context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
348 }
349 else if (redundantTypeArguments != null) {
350 context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
351 }
352 }
353 else {
354 if (supertypes.size() > 1) {
355 context.trace.report(AMBIGUOUS_SUPER.on(expression));
356 }
357 else {
358 // supertypes may be empty when all the supertypes are error types (are not resolved, for example)
359 JetType type = supertypes.isEmpty()
360 ? KotlinBuiltIns.getInstance().getAnyType()
361 : supertypes.iterator().next();
362 result = substitutor.substitute(type, Variance.INVARIANT);
363 }
364 }
365 if (result != null) {
366 if (DescriptorUtils.isKindOf(thisType, ClassKind.TRAIT)) {
367 if (DescriptorUtils.isKindOf(result, ClassKind.CLASS)) {
368 context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression));
369 }
370 }
371 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
372 context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
373 if (superTypeQualifier != null) {
374 context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope);
375 }
376 }
377 return result;
378 }
379
380 @NotNull // No class receivers
381 private static LabelResolver.LabeledReceiverResolutionResult resolveToReceiver(
382 JetLabelQualifiedInstanceExpression expression,
383 ExpressionTypingContext context,
384 boolean onlyClassReceivers
385 ) {
386 String labelName = expression.getLabelName();
387 if (labelName != null) {
388 LabelResolver.LabeledReceiverResolutionResult resolutionResult = context.labelResolver.resolveThisLabel(
389 expression.getInstanceReference(), expression.getTargetLabel(), context, new LabelName(labelName));
390 if (onlyClassReceivers && resolutionResult.success()) {
391 if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) {
392 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
393 }
394 }
395 return resolutionResult;
396 }
397 else {
398 ReceiverParameterDescriptor result = NO_RECEIVER_PARAMETER;
399 List<ReceiverParameterDescriptor> receivers = context.scope.getImplicitReceiversHierarchy();
400 if (onlyClassReceivers) {
401 for (ReceiverParameterDescriptor receiver : receivers) {
402 if (isDeclaredInClass(receiver)) {
403 result = receiver;
404 break;
405 }
406 }
407 }
408 else if (!receivers.isEmpty()) {
409 result = receivers.get(0);
410 }
411 if (result != NO_RECEIVER_PARAMETER) {
412 context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
413 }
414 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
415 }
416 }
417
418 private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
419 return receiver.getContainingDeclaration() instanceof ClassDescriptor;
420 }
421
422 @Override
423 public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
424 return visitBlockExpression(expression, context, false);
425 }
426
427 public static JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
428 return context.expressionTypingServices.getBlockReturnedType(
429 expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
430 }
431
432 @Override
433 public JetTypeInfo visitCallableReferenceExpression(JetCallableReferenceExpression expression, ExpressionTypingContext context) {
434 JetTypeReference typeReference = expression.getTypeReference();
435
436 JetType receiverType =
437 typeReference == null
438 ? null
439 : context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
440
441 JetSimpleNameExpression callableReference = expression.getCallableReference();
442 if (callableReference.getReferencedName().isEmpty()) {
443 context.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
444 JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
445 return DataFlowUtils.checkType(errorType, expression, context, context.dataFlowInfo);
446 }
447
448 JetType result = getCallableReferenceType(expression, receiverType, context);
449 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
450 }
451
452 @Nullable
453 private static JetType getCallableReferenceType(
454 @NotNull JetCallableReferenceExpression expression,
455 @Nullable JetType lhsType,
456 @NotNull ExpressionTypingContext context
457 ) {
458 JetSimpleNameExpression reference = expression.getCallableReference();
459
460 boolean[] result = new boolean[1];
461 FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
462
463 if (!result[0]) {
464 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
465 }
466 if (descriptor == null) return null;
467
468 ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
469 ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
470 if (receiverParameter != null && expectedThisObject != null) {
471 context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor));
472 return null;
473 }
474
475 JetType receiverType = null;
476 if (receiverParameter != null) {
477 receiverType = receiverParameter.getType();
478 }
479 else if (expectedThisObject != null) {
480 receiverType = expectedThisObject.getType();
481 }
482
483 //noinspection ConstantConditions
484 JetType type = KotlinBuiltIns.getInstance().getKFunctionType(
485 Collections.<AnnotationDescriptor>emptyList(),
486 receiverType,
487 DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()),
488 descriptor.getReturnType(),
489 receiverParameter != null
490 );
491
492 ExpressionAsFunctionDescriptor functionDescriptor = new ExpressionAsFunctionDescriptor(
493 context.scope.getContainingDeclaration(),
494 Name.special("<callable-reference>")
495 );
496 FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
497
498 context.trace.record(CALLABLE_REFERENCE, expression, functionDescriptor);
499
500 return type;
501 }
502
503 @Nullable
504 private static FunctionDescriptor resolveCallableReferenceTarget(
505 @Nullable JetType lhsType,
506 @NotNull ExpressionTypingContext context,
507 @NotNull JetCallableReferenceExpression expression,
508 @NotNull boolean[] result
509 ) {
510 JetSimpleNameExpression reference = expression.getCallableReference();
511
512 if (lhsType == null) {
513 return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
514 }
515
516 ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
517 if (!(classifier instanceof ClassDescriptor)) {
518 context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
519 return null;
520 }
521
522 ReceiverValue receiver = new TransientReceiver(lhsType);
523 TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
524 context, "trace to resolve callable reference with receiver", reference);
525 FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
526 reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
527 if (result[0]) {
528 temporaryWithReceiver.commit();
529 return descriptor;
530 }
531
532 JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
533 TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
534 context, "trace to resolve callable reference in static scope", reference);
535 FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
536 context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
537 if (result[0]) {
538 temporaryForStatic.commit();
539 return possibleStaticNestedClassConstructor;
540 }
541
542 return null;
543 }
544
545 @Nullable
546 private static FunctionDescriptor resolveCallableNotCheckingArguments(
547 @NotNull JetSimpleNameExpression reference,
548 @NotNull ReceiverValue receiver,
549 @NotNull ExpressionTypingContext context,
550 @NotNull boolean[] result
551 ) {
552 Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
553
554 TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference);
555
556 ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE);
557 ResolvedCallWithTrace<FunctionDescriptor> function = contextForResolve.expressionTypingServices.getCallExpressionResolver()
558 .getResolvedCallForFunction(call, reference, contextForResolve, CheckValueArgumentsMode.DISABLED, result);
559 if (!result[0]) return null;
560
561 if (function instanceof VariableAsFunctionResolvedCall) {
562 // TODO: KProperty
563 context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
564 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
565 return null;
566 }
567
568 trace.commit();
569 return function != null ? function.getResultingDescriptor() : null;
570 }
571
572 @Override
573 public JetTypeInfo visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) {
574 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver();
575 return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
576 }
577
578 @Override
579 public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) {
580 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver();
581 return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
582 }
583
584 @Override
585 public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
586 return visitUnaryExpression(expression, context, false);
587 }
588
589 public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) {
590 JetExpression baseExpression = expression.getBaseExpression();
591 if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
592
593 JetSimpleNameExpression operationSign = expression.getOperationReference();
594
595 IElementType operationType = operationSign.getReferencedNameElementType();
596 // If it's a labeled expression
597 if (JetTokens.LABELS.contains(operationType)) {
598 return visitLabeledExpression(expression, context, isStatement);
599 }
600
601 // Special case for expr!!
602 if (operationType == JetTokens.EXCLEXCL) {
603 return visitExclExclExpression(expression, context);
604 }
605
606 // Type check the base expression
607 JetTypeInfo typeInfo = facade.getTypeInfo(
608 baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
609 JetType type = typeInfo.getType();
610 if (type == null) {
611 return typeInfo;
612 }
613 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
614
615 // Conventions for unary operations
616 Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
617 if (name == null) {
618 context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
619 return JetTypeInfo.create(null, dataFlowInfo);
620 }
621
622 // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
623 if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
624 JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
625 resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression,
626 stubExpression,
627 context.replaceExpectedType(NO_EXPECTED_TYPE).replaceBindingTrace(
628 TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression)),
629 context.trace);
630 }
631
632 ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
633
634 // Resolve the operation reference
635 OverloadResolutionResults<FunctionDescriptor> resolutionResults = context.resolveCallWithGivenName(
636 CallMaker.makeCall(receiver, expression),
637 expression.getOperationReference(),
638 name);
639
640 if (!resolutionResults.isSuccess()) {
641 return JetTypeInfo.create(null, dataFlowInfo);
642 }
643
644 // Computing the return type
645 JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
646 JetType result;
647 if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
648 assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
649 if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) {
650 result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
651 context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
652 }
653 else {
654 JetType receiverType = receiver.getType();
655 if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) {
656 context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
657 }
658 else {
659 context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
660
661 checkLValue(context.trace, baseExpression);
662 }
663 // TODO : Maybe returnType?
664 result = receiverType;
665 }
666 }
667 else {
668 result = returnType;
669 }
670 return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
671 }
672
673 private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
674 JetExpression baseExpression = expression.getBaseExpression();
675 assert baseExpression != null;
676 JetSimpleNameExpression operationSign = expression.getOperationReference();
677 assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
678
679 Call call = createCallForSpecialConstruction(expression, Collections.singletonList(baseExpression));
680 resolveSpecialConstructionAsCall(
681 call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
682 JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
683 assert baseTypeInfo != null : "Base expression was not processed: " + expression;
684 JetType baseType = baseTypeInfo.getType();
685 if (baseType == null) {
686 return baseTypeInfo;
687 }
688 DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
689 if (isKnownToBeNotNull(baseExpression, context) && !ErrorUtils.isErrorType(baseType)) {
690 context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
691 }
692 else {
693 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(baseExpression, baseType, context.trace.getBindingContext());
694 dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
695 }
696 return JetTypeInfo.create(TypeUtils.makeNotNullable(baseType), dataFlowInfo);
697 }
698
699 private JetTypeInfo visitLabeledExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context,
700 boolean isStatement) {
701 JetExpression baseExpression = expression.getBaseExpression();
702 assert baseExpression != null;
703 JetSimpleNameExpression operationSign = expression.getOperationReference();
704 assert JetTokens.LABELS.contains(operationSign.getReferencedNameElementType());
705
706 String referencedName = operationSign.getReferencedName();
707 context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression);
708 // TODO : Some processing for the label?
709 JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement);
710 context.labelResolver.exitLabeledElement(baseExpression);
711 return DataFlowUtils.checkType(typeInfo, expression, context);
712 }
713
714 private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
715 JetType type = context.trace.get(EXPRESSION_TYPE, expression);
716 assert type != null : "This method is only supposed to be called when the type is not null";
717 return isKnownToBeNotNull(expression, type, context);
718 }
719
720 private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
721 DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, jetType, context.trace.getBindingContext());
722 return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
723 }
724
725 public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
726 checkLValue(trace, expression, false);
727 }
728
729 private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
730 JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
731 if (expression instanceof JetArrayAccessExpression) {
732 JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
733 if (arrayExpression != null) {
734 checkLValue(trace, arrayExpression, true);
735 }
736 return;
737 }
738 if (canBeThis && expression instanceof JetThisExpression) return;
739 VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
740 if (variable == null) {
741 trace.report(VARIABLE_EXPECTED.on(expression != null ? expression : expressionWithParenthesis));
742 }
743 }
744
745 @Override
746 public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
747 ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
748 ? contextWithExpectedType
749 : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
750
751 JetSimpleNameExpression operationSign = expression.getOperationReference();
752 JetExpression left = expression.getLeft();
753 JetExpression right = expression.getRight();
754 IElementType operationType = operationSign.getReferencedNameElementType();
755
756 JetTypeInfo result;
757
758 //Expressions that can depend on expected type
759 if (operationType == JetTokens.IDENTIFIER) {
760 Name referencedName = operationSign.getReferencedNameAsName();
761 result = getTypeInfoForBinaryCall(referencedName, context, expression);
762 }
763 else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
764 Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
765 result = getTypeInfoForBinaryCall(referencedName, context, expression);
766 }
767 else if (operationType == JetTokens.ELVIS) {
768 //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
769 return visitElvisExpression(expression, context);
770 }
771
772 //Expressions that don't depend on expected type
773 else if (operationType == JetTokens.EQ) {
774 result = visitAssignment(expression, context);
775 }
776 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
777 result = visitAssignmentOperation(expression, context);
778 }
779 else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
780 result = visitComparison(expression, context, operationSign);
781 }
782 else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
783 result = visitEquality(expression, context, operationSign, left, right);
784 }
785 else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
786 ensureNonemptyIntersectionOfOperandTypes(expression, context);
787 // TODO : Check comparison pointlessness
788 result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
789 }
790 else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
791 result = checkInExpression(expression, operationSign, left, right, context);
792 }
793 else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
794 result = visitBooleanOperationExpression(operationType, left, right, context);
795 }
796 else {
797 context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
798 result = JetTypeInfo.create(null, context.dataFlowInfo);
799 }
800 return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
801 }
802
803 private JetTypeInfo visitEquality(
804 JetBinaryExpression expression,
805 ExpressionTypingContext context,
806 JetSimpleNameExpression operationSign,
807 JetExpression left,
808 JetExpression right
809 ) {
810 JetTypeInfo result;DataFlowInfo dataFlowInfo = context.dataFlowInfo;
811 if (right != null && left != null) {
812 ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
813
814 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
815
816 dataFlowInfo = leftTypeInfo.getDataFlowInfo();
817 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
818
819 OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall(
820 contextWithDataFlow, receiver, OperatorConventions.EQUALS, KotlinBuiltIns.getInstance().getNullableAnyType());
821
822 dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo();
823
824 if (resolutionResults.isSuccess()) {
825 FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
826 context.trace.record(REFERENCE_TARGET, operationSign, equals);
827 context.trace.record(RESOLVED_CALL, operationSign, resolutionResults.getResultingCall());
828 if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
829 ensureNonemptyIntersectionOfOperandTypes(expression, context);
830 }
831 }
832 else {
833 if (resolutionResults.isAmbiguity()) {
834 context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
835 }
836 else {
837 context.trace.report(EQUALS_MISSING.on(operationSign));
838 }
839 }
840 }
841 result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
842 return result;
843 }
844
845 @NotNull
846 private JetTypeInfo visitComparison(
847 @NotNull JetBinaryExpression expression,
848 @NotNull ExpressionTypingContext context,
849 @NotNull JetSimpleNameExpression operationSign
850 ) {
851 JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
852 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
853 JetType compareToReturnType = typeInfo.getType();
854 JetType type = null;
855 if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) {
856 TypeConstructor constructor = compareToReturnType.getConstructor();
857 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
858 TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor();
859 if (constructor.equals(intTypeConstructor)) {
860 type = builtIns.getBooleanType();
861 }
862 else {
863 context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
864 }
865 }
866 return JetTypeInfo.create(type, dataFlowInfo);
867 }
868
869 @NotNull
870 private JetTypeInfo visitBooleanOperationExpression(
871 @Nullable IElementType operationType,
872 @Nullable JetExpression left,
873 @Nullable JetExpression right,
874 @NotNull ExpressionTypingContext context
875 ) {
876 JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
877 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
878
879 JetType leftType = leftTypeInfo.getType();
880 DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
881
882 WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
883 // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
884 boolean isAnd = operationType == JetTokens.ANDAND;
885 DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
886 WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
887
888 ExpressionTypingContext contextForRightExpr = context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope);
889 JetType rightType = right != null ? facade.getTypeInfo(right, contextForRightExpr).getType() : null;
890 if (left != null && leftType != null && !isBoolean(leftType)) {
891 context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
892 }
893 if (rightType != null && !isBoolean(rightType)) {
894 context.trace.report(TYPE_MISMATCH.on(right, booleanType, rightType));
895 }
896 return JetTypeInfo.create(booleanType, dataFlowInfo);
897 }
898
899 @NotNull
900 private JetTypeInfo visitElvisExpression(
901 @NotNull JetBinaryExpression expression,
902 @NotNull ExpressionTypingContext contextWithExpectedType
903 ) {
904 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
905 JetExpression left = expression.getLeft();
906 JetExpression right = expression.getRight();
907
908 if (left == null || right == null) {
909 getTypeInfoOrNullType(left, context, facade);
910 return JetTypeInfo.create(null, context.dataFlowInfo);
911 }
912
913 Call call = createCallForSpecialConstruction(expression, Lists.newArrayList(left, right));
914 ResolvedCall<FunctionDescriptor> resolvedCall = resolveSpecialConstructionAsCall(
915 call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
916 JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
917 assert leftTypeInfo != null : "Left expression was not processed: " + expression;
918 JetType leftType = leftTypeInfo.getType();
919 if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
920 context.trace.report(USELESS_ELVIS.on(left, leftType));
921 }
922 JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
923 assert rightTypeInfo != null : "Right expression was not processed: " + expression;
924 JetType rightType = rightTypeInfo.getType();
925
926 DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
927 JetType type = resolvedCall.getResultingDescriptor().getReturnType();
928 if (type == null || rightType == null) return JetTypeInfo.create(null, dataFlowInfo);
929
930 return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(type, rightType.isNullable()), dataFlowInfo);
931 }
932
933 @NotNull
934 public JetTypeInfo checkInExpression(
935 @NotNull JetElement callElement,
936 @NotNull JetSimpleNameExpression operationSign,
937 @Nullable JetExpression left,
938 @Nullable JetExpression right,
939 @NotNull ExpressionTypingContext context
940 ) {
941 ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
942 if (right == null) {
943 if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
944 return JetTypeInfo.create(null, context.dataFlowInfo);
945 }
946
947 DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo();
948
949 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
950 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
951
952 OverloadResolutionResults<FunctionDescriptor> resolutionResult = contextWithDataFlow.resolveCallWithGivenName(
953 CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
954 operationSign,
955 OperatorConventions.CONTAINS);
956 JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
957 ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
958
959 if (left != null) {
960 dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
961 }
962
963 return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo);
964 }
965
966 private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
967 JetExpression left = expression.getLeft();
968 if (left == null) return;
969
970 JetExpression right = expression.getRight();
971
972 // TODO : duplicated effort for == and !=
973 JetType leftType = facade.getTypeInfo(left, context).getType();
974 if (leftType != null && right != null) {
975 JetType rightType = facade.getTypeInfo(right, context).getType();
976
977 if (rightType != null) {
978 if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
979 context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
980 }
981 checkSenselessComparisonWithNull(expression, left, right, context);
982 }
983 }
984 }
985
986 private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
987 JetExpression expr;
988 if (JetPsiUtil.isNullConstant(left)) {
989 expr = right;
990 }
991 else if (JetPsiUtil.isNullConstant(right)) {
992 expr = left;
993 }
994 else return;
995
996 JetSimpleNameExpression operationSign = expression.getOperationReference();
997 JetType type = facade.getTypeInfo(expr, context).getType();
998 if (type == null || ErrorUtils.isErrorType(type)) return;
999
1000 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(expr, type, context.trace.getBindingContext());
1001 Nullability nullability = context.dataFlowInfo.getNullability(value);
1002
1003 boolean expressionIsAlways;
1004 boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
1005
1006 if (nullability == Nullability.NULL) {
1007 expressionIsAlways = equality;
1008 }
1009 else if (nullability == Nullability.NOT_NULL) {
1010 expressionIsAlways = !equality;
1011 }
1012 else return;
1013
1014 context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
1015 }
1016
1017 @NotNull
1018 private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1019 return assignmentIsNotAnExpressionError(expression, context);
1020 }
1021
1022 @NotNull
1023 private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1024 return assignmentIsNotAnExpressionError(expression, context);
1025 }
1026
1027 @NotNull
1028 private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1029 facade.checkStatementType(expression, context);
1030 context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1031 return JetTypeInfo.create(null, context.dataFlowInfo);
1032 }
1033
1034 @Override
1035 public JetTypeInfo visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) {
1036 JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context);
1037 return DataFlowUtils.checkType(typeInfo, expression, context);
1038 }
1039
1040 @NotNull
1041 public JetTypeInfo getTypeInfoForBinaryCall(
1042 @NotNull Name name,
1043 @NotNull ExpressionTypingContext context,
1044 @NotNull JetBinaryExpression binaryExpression
1045 ) {
1046 JetExpression left = binaryExpression.getLeft();
1047 DataFlowInfo dataFlowInfo = context.dataFlowInfo;
1048 if (left != null) {
1049 //left here is a receiver, so it doesn't depend on expected type
1050 dataFlowInfo = facade.getTypeInfo(
1051 left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
1052 }
1053 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1054
1055 OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1056 if (left != null) {
1057 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1058 resolutionResults = getResolutionResultsForBinaryCall(context.scope, name, contextWithDataFlow, binaryExpression, receiver);
1059 }
1060 else {
1061 resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1062 }
1063
1064 JetExpression right = binaryExpression.getRight();
1065 if (right != null) {
1066 dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo();
1067 }
1068
1069 return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency), dataFlowInfo);
1070 }
1071
1072 @NotNull
1073 static
1074 /*package*/ OverloadResolutionResults<FunctionDescriptor> getResolutionResultsForBinaryCall(
1075 JetScope scope,
1076 Name name,
1077 ExpressionTypingContext context,
1078 JetBinaryExpression binaryExpression,
1079 ExpressionReceiver receiver
1080 ) {
1081 // ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
1082 return context.replaceScope(scope).resolveCallWithGivenName(
1083 CallMaker.makeCall(receiver, binaryExpression),
1084 binaryExpression.getOperationReference(),
1085 name
1086 );
1087 }
1088
1089 @Override
1090 public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
1091 context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1092 return JetTypeInfo.create(null, context.dataFlowInfo);
1093 }
1094
1095 @Override
1096 public JetTypeInfo visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) {
1097 if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT) {
1098 return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context, context.dataFlowInfo);
1099 }
1100 context.trace.report(NAMESPACE_IS_NOT_AN_EXPRESSION.on(expression));
1101 return JetTypeInfo.create(null, context.dataFlowInfo);
1102 }
1103
1104
1105 @Override
1106 public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1107 final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1108 final StringBuilder builder = new StringBuilder();
1109 final CompileTimeConstant<?>[] value = new CompileTimeConstant<?>[1];
1110 final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[1];
1111 dataFlowInfo[0] = context.dataFlowInfo;
1112
1113 for (JetStringTemplateEntry entry : expression.getEntries()) {
1114 entry.accept(new JetVisitorVoid() {
1115
1116 @Override
1117 public void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry) {
1118 JetExpression entryExpression = entry.getExpression();
1119 if (entryExpression != null) {
1120 JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
1121 dataFlowInfo[0] = typeInfo.getDataFlowInfo();
1122 }
1123 value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
1124 }
1125
1126 @Override
1127 public void visitLiteralStringTemplateEntry(JetLiteralStringTemplateEntry entry) {
1128 builder.append(entry.getText());
1129 }
1130
1131 @Override
1132 public void visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry) {
1133 String text = entry.getText();
1134
1135 CompileTimeConstant<?> character = CompileTimeConstantResolver.escapedStringToCharValue(text);
1136 if (character instanceof ErrorValue) {
1137 context.trace.report(ILLEGAL_ESCAPE_SEQUENCE.on(entry));
1138 value[0] = CompileTimeConstantResolver.OUT_OF_RANGE;
1139 }
1140 else {
1141 builder.append(((CharValue) character).getValue());
1142 }
1143 }
1144 });
1145 }
1146 if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) {
1147 context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new StringValue(builder.toString()));
1148 }
1149 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
1150 }
1151
1152 @Override
1153 public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) {
1154 JetExpression baseExpression = expression.getBaseExpression();
1155 if (baseExpression == null) {
1156 return JetTypeInfo.create(null, data.dataFlowInfo);
1157 }
1158 return facade.getTypeInfo(baseExpression, data);
1159 }
1160
1161 @Override
1162 public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) {
1163 context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1164 return JetTypeInfo.create(null, context.dataFlowInfo);
1165 }
1166
1167 @NotNull
1168 /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1169 return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1170 }
1171
1172 @NotNull
1173 /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1174 return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1175 }
1176
1177 @NotNull
1178 private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1179 @Nullable JetExpression rightHandSide, //only for 'set' method
1180 @NotNull ExpressionTypingContext oldContext,
1181 @NotNull BindingTrace traceForResolveResult,
1182 boolean isGet) {
1183 JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1184 if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
1185
1186 JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1187 .replaceContextDependency(INDEPENDENT));
1188 JetType arrayType = arrayTypeInfo.getType();
1189 if (arrayType == null) return arrayTypeInfo;
1190
1191 DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
1192 ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
1193 ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1194 if (!isGet) assert rightHandSide != null;
1195
1196 OverloadResolutionResults<FunctionDescriptor> functionResults = context.resolveCallWithGivenName(
1197 isGet
1198 ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1199 : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD),
1200 arrayAccessExpression,
1201 Name.identifier(isGet ? "get" : "set"));
1202
1203 List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1204 // The accumulated data flow info of all index expressions is saved on the last index
1205 if (!indices.isEmpty()) {
1206 dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo();
1207 }
1208
1209 if (!isGet) {
1210 dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
1211 }
1212
1213 if (!functionResults.isSingleResult()) {
1214 traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1215 return JetTypeInfo.create(null, dataFlowInfo);
1216 }
1217 traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
1218 return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo);
1219 }
1220 }