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