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