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