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