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