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