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