001 /*
002 * Copyright 2010-2015 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.kotlin.types.expressions;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Maps;
021 import com.intellij.lang.ASTNode;
022 import com.intellij.openapi.diagnostic.Logger;
023 import com.intellij.openapi.util.Ref;
024 import com.intellij.psi.util.PsiTreeUtil;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.kotlin.descriptors.*;
028 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
029 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
030 import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
031 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
032 import org.jetbrains.kotlin.lexer.KtTokens;
033 import org.jetbrains.kotlin.name.Name;
034 import org.jetbrains.kotlin.psi.*;
035 import org.jetbrains.kotlin.resolve.BindingContextUtils;
036 import org.jetbrains.kotlin.resolve.BindingTrace;
037 import org.jetbrains.kotlin.resolve.calls.CallResolver;
038 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
039 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus;
040 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintsUtil;
041 import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
042 import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
043 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
044 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
045 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
046 import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
047 import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
048 import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
049 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
050 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
051 import org.jetbrains.kotlin.types.KotlinType;
052 import org.jetbrains.kotlin.types.TypeUtils;
053 import org.jetbrains.kotlin.types.Variance;
054
055 import java.util.*;
056
057 import static org.jetbrains.kotlin.resolve.BindingContext.CALL;
058 import static org.jetbrains.kotlin.resolve.BindingContext.RESOLVED_CALL;
059 import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION;
060
061 public class ControlStructureTypingUtils {
062 private static final Logger LOG = Logger.getInstance(ControlStructureTypingUtils.class);
063
064 private final CallResolver callResolver;
065 private final DataFlowAnalyzer dataFlowAnalyzer;
066 private final ModuleDescriptor moduleDescriptor;
067
068 public ControlStructureTypingUtils(
069 @NotNull CallResolver callResolver,
070 @NotNull DataFlowAnalyzer dataFlowAnalyzer,
071 @NotNull ModuleDescriptor moduleDescriptor
072 ) {
073 this.callResolver = callResolver;
074 this.dataFlowAnalyzer = dataFlowAnalyzer;
075 this.moduleDescriptor = moduleDescriptor;
076 }
077
078 /*package*/ ResolvedCall<FunctionDescriptor> resolveSpecialConstructionAsCall(
079 @NotNull Call call,
080 @NotNull String constructionName,
081 @NotNull List<String> argumentNames,
082 @NotNull List<Boolean> isArgumentNullable,
083 @NotNull ExpressionTypingContext context,
084 @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
085 ) {
086 SimpleFunctionDescriptorImpl function = createFunctionDescriptorForSpecialConstruction(
087 constructionName.toUpperCase(), argumentNames, isArgumentNullable);
088 TracingStrategy tracing = createTracingForSpecialConstruction(call, constructionName, context);
089 ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(call, function);
090 OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithKnownCandidate(
091 call, tracing, context, resolutionCandidate, dataFlowInfoForArguments);
092 assert results.isSingleResult() : "Not single result after resolving one known candidate";
093 return results.getResultingCall();
094 }
095
096 private SimpleFunctionDescriptorImpl createFunctionDescriptorForSpecialConstruction(
097 @NotNull String constructionName,
098 @NotNull List<String> argumentNames,
099 @NotNull List<Boolean> isArgumentNullable
100 ) {
101 assert argumentNames.size() == isArgumentNullable.size();
102
103 Name specialFunctionName = Name.identifier("<SPECIAL-FUNCTION-FOR-" + constructionName + "-RESOLVE>");
104
105 SimpleFunctionDescriptorImpl function = SimpleFunctionDescriptorImpl.create(
106 moduleDescriptor, Annotations.Companion.getEMPTY(), specialFunctionName, CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE
107 );
108
109 TypeParameterDescriptor typeParameter = TypeParameterDescriptorImpl.createWithDefaultBound(
110 function, Annotations.Companion.getEMPTY(), false, Variance.INVARIANT,
111 Name.identifier("<TYPE-PARAMETER-FOR-" + constructionName + "-RESOLVE>"), 0);
112
113 KotlinType type = typeParameter.getDefaultType();
114 KotlinType nullableType = TypeUtils.makeNullable(type);
115
116 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(argumentNames.size());
117 for (int i = 0; i < argumentNames.size(); i++) {
118 KotlinType argumentType = isArgumentNullable.get(i) ? nullableType : type;
119 ValueParameterDescriptorImpl valueParameter = new ValueParameterDescriptorImpl(
120 function, null, i, Annotations.Companion.getEMPTY(), Name.identifier(argumentNames.get(i)),
121 argumentType,
122 /* declaresDefaultValue = */ false,
123 /* isCrossinline = */ false,
124 /* isNoinline = */ false,
125 null, SourceElement.NO_SOURCE
126 );
127 valueParameters.add(valueParameter);
128 }
129 function.initialize(
130 null,
131 null,
132 Lists.newArrayList(typeParameter),
133 valueParameters,
134 type,
135 Modality.FINAL,
136 Visibilities.PUBLIC
137 );
138 return function;
139 }
140
141 /*package*/ static MutableDataFlowInfoForArguments createIndependentDataFlowInfoForArgumentsForCall(
142 final Map<ValueArgument, DataFlowInfo> dataFlowInfoForArgumentsMap
143 ) {
144 return new MutableDataFlowInfoForArguments() {
145 private DataFlowInfo initialDataFlowInfo;
146
147 @Override
148 public void setInitialDataFlowInfo(@NotNull DataFlowInfo dataFlowInfo) {
149 this.initialDataFlowInfo = dataFlowInfo;
150 }
151
152 @Override
153 public void updateInfo(@NotNull ValueArgument valueArgument, @NotNull DataFlowInfo dataFlowInfo) {
154 //todo
155 }
156
157 @NotNull
158 @Override
159 public DataFlowInfo getInfo(@NotNull ValueArgument valueArgument) {
160 return dataFlowInfoForArgumentsMap.get(valueArgument);
161 }
162
163 @NotNull
164 @Override
165 public DataFlowInfo getResultInfo() {
166 //todo merge and use
167 return initialDataFlowInfo;
168 }
169 };
170 }
171
172 public static MutableDataFlowInfoForArguments createDataFlowInfoForArgumentsForIfCall(
173 @NotNull Call callForIf,
174 @NotNull DataFlowInfo thenInfo,
175 @NotNull DataFlowInfo elseInfo
176 ) {
177 Map<ValueArgument, DataFlowInfo> dataFlowInfoForArgumentsMap = Maps.newHashMap();
178 dataFlowInfoForArgumentsMap.put(callForIf.getValueArguments().get(0), thenInfo);
179 dataFlowInfoForArgumentsMap.put(callForIf.getValueArguments().get(1), elseInfo);
180 return createIndependentDataFlowInfoForArgumentsForCall(dataFlowInfoForArgumentsMap);
181 }
182
183 /*package*/ static Call createCallForSpecialConstruction(
184 @NotNull final KtExpression expression,
185 @NotNull final KtExpression calleeExpression,
186 @NotNull List<? extends KtExpression> arguments
187 ) {
188 final List<ValueArgument> valueArguments = Lists.newArrayList();
189 for (KtExpression argument : arguments) {
190 valueArguments.add(CallMaker.makeValueArgument(argument));
191 }
192 return new Call() {
193 @Nullable
194 @Override
195 public ASTNode getCallOperationNode() {
196 return expression.getNode();
197 }
198
199 @NotNull
200 @Override
201 public ReceiverValue getExplicitReceiver() {
202 return ReceiverValue.NO_RECEIVER;
203 }
204
205 @NotNull
206 @Override
207 public ReceiverValue getDispatchReceiver() {
208 return ReceiverValue.NO_RECEIVER;
209 }
210
211 @Nullable
212 @Override
213 public KtExpression getCalleeExpression() {
214 return calleeExpression;
215 }
216
217 @Nullable
218 @Override
219 public KtValueArgumentList getValueArgumentList() {
220 return null;
221 }
222
223 @NotNull
224 @Override
225 public List<? extends ValueArgument> getValueArguments() {
226 return valueArguments;
227 }
228
229 @NotNull
230 @Override
231 public List<FunctionLiteralArgument> getFunctionLiteralArguments() {
232 return Collections.emptyList();
233 }
234
235 @NotNull
236 @Override
237 public List<KtTypeProjection> getTypeArguments() {
238 return Collections.emptyList();
239 }
240
241 @Nullable
242 @Override
243 public KtTypeArgumentList getTypeArgumentList() {
244 return null;
245 }
246
247 @NotNull
248 @Override
249 public KtElement getCallElement() {
250 return expression;
251 }
252
253 @NotNull
254 @Override
255 public CallType getCallType() {
256 return CallType.DEFAULT;
257 }
258 };
259 }
260
261 @NotNull
262 /*package*/ TracingStrategy createTracingForSpecialConstruction(
263 final @NotNull Call call,
264 @NotNull String constructionName,
265 final @NotNull ExpressionTypingContext context
266 ) {
267 class CheckTypeContext {
268 public BindingTrace trace;
269 public KotlinType expectedType;
270
271 CheckTypeContext(@NotNull BindingTrace trace, @NotNull KotlinType expectedType) {
272 this.trace = trace;
273 this.expectedType = expectedType;
274 }
275
276 CheckTypeContext makeTypeNullable() {
277 if (TypeUtils.noExpectedType(expectedType)) return this;
278 return new CheckTypeContext(trace, TypeUtils.makeNullable(expectedType));
279 }
280 }
281
282 final KtVisitor<Boolean, CheckTypeContext> checkTypeVisitor = new KtVisitor<Boolean, CheckTypeContext>() {
283
284 private boolean checkExpressionType(@NotNull KtExpression expression, CheckTypeContext c) {
285 JetTypeInfo typeInfo = BindingContextUtils.getRecordedTypeInfo(expression, c.trace.getBindingContext());
286 if (typeInfo == null) return false;
287
288 Ref<Boolean> hasError = Ref.create();
289 dataFlowAnalyzer.checkType(
290 typeInfo.getType(),
291 expression,
292 context
293 .replaceExpectedType(c.expectedType)
294 .replaceDataFlowInfo(typeInfo.getDataFlowInfo())
295 .replaceBindingTrace(c.trace),
296 hasError
297 );
298 return hasError.get();
299 }
300
301 private boolean checkExpressionTypeRecursively(@Nullable KtExpression expression, CheckTypeContext c) {
302 if (expression == null) return false;
303 return expression.accept(this, c);
304 }
305
306 private boolean checkSubExpressions(
307 KtExpression firstSub, KtExpression secondSub, KtExpression expression,
308 CheckTypeContext firstContext, CheckTypeContext secondContext, CheckTypeContext context
309 ) {
310 boolean errorWasReported = checkExpressionTypeRecursively(firstSub, firstContext);
311 errorWasReported |= checkExpressionTypeRecursively(secondSub, secondContext);
312 return errorWasReported || checkExpressionType(expression, context);
313 }
314
315 @Override
316 public Boolean visitIfExpression(@NotNull KtIfExpression ifExpression, CheckTypeContext c) {
317 KtExpression thenBranch = ifExpression.getThen();
318 KtExpression elseBranch = ifExpression.getElse();
319 if (thenBranch == null || elseBranch == null) {
320 return checkExpressionType(ifExpression, c);
321 }
322 return checkSubExpressions(thenBranch, elseBranch, ifExpression, c, c, c);
323 }
324
325 @Override
326 public Boolean visitBlockExpression(@NotNull KtBlockExpression expression, CheckTypeContext c) {
327 if (expression.getStatements().isEmpty()) {
328 return checkExpressionType(expression, c);
329 }
330 KtExpression lastStatement = KtPsiUtil.getLastStatementInABlock(expression);
331 if (lastStatement != null) {
332 return checkExpressionTypeRecursively(lastStatement, c);
333 }
334 return false;
335 }
336
337 @Override
338 public Boolean visitPostfixExpression(@NotNull KtPostfixExpression expression, CheckTypeContext c) {
339 if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) {
340 return checkExpressionTypeRecursively(expression.getBaseExpression(), c.makeTypeNullable());
341 }
342 return super.visitPostfixExpression(expression, c);
343 }
344
345 @Override
346 public Boolean visitBinaryExpression(@NotNull KtBinaryExpression expression, CheckTypeContext c) {
347 if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.ELVIS) {
348
349 return checkSubExpressions(expression.getLeft(), expression.getRight(), expression, c.makeTypeNullable(), c, c);
350 }
351 return super.visitBinaryExpression(expression, c);
352 }
353
354 @Override
355 public Boolean visitExpression(@NotNull KtExpression expression, CheckTypeContext c) {
356 return checkExpressionType(expression, c);
357 }
358 };
359
360 return new ThrowingOnErrorTracingStrategy("resolve " + constructionName + " as a call") {
361 @Override
362 public <D extends CallableDescriptor> void bindReference(
363 @NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall
364 ) {
365 //do nothing
366 }
367
368 @Override
369 public void bindCall(@NotNull BindingTrace trace, @NotNull Call call) {
370 trace.record(CALL, call.getCalleeExpression(), call);
371 }
372
373 @Override
374 public <D extends CallableDescriptor> void bindResolvedCall(
375 @NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall
376 ) {
377 trace.record(RESOLVED_CALL, call, resolvedCall);
378 }
379
380 @Override
381 public void typeInferenceFailed(
382 @NotNull BindingTrace trace, @NotNull InferenceErrorData data
383 ) {
384 ConstraintSystem constraintSystem = data.constraintSystem;
385 ConstraintSystemStatus status = constraintSystem.getStatus();
386 assert !status.isSuccessful() : "Report error only for not successful constraint system";
387
388 if (status.hasErrorInConstrainingTypes() || status.hasUnknownParameters()) {
389 return;
390 }
391 KtExpression expression = (KtExpression) call.getCallElement();
392 if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints()
393 || status.hasTypeInferenceIncorporationError()) { // todo after KT-... remove this line
394 expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType));
395 return;
396 }
397 KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtNamedDeclaration.class);
398 logError("Expression: " + (parentDeclaration != null ? parentDeclaration.getText() : expression.getText()) +
399 "\nConstraint system status: \n" + ConstraintsUtil.getDebugMessageForStatus(status));
400 }
401 };
402 }
403
404 private abstract static class ThrowingOnErrorTracingStrategy implements TracingStrategy {
405 private final String debugName;
406
407 protected ThrowingOnErrorTracingStrategy(String debugName) {
408 this.debugName = debugName;
409 }
410
411 private void logError() {
412 logError(null);
413 }
414
415 protected void logError(@Nullable String additionalInformation) {
416 String errorMessage = "Resolution error of this type shouldn't occur for " + debugName;
417 if (additionalInformation != null) {
418 errorMessage += ".\n" + additionalInformation;
419 }
420 LOG.error(errorMessage);
421 }
422
423 @Override
424 public void unresolvedReference(@NotNull BindingTrace trace) {
425 logError();
426 }
427
428 @Override
429 public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(
430 @NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> candidates
431 ) {
432 logError();
433 }
434
435 @Override
436 public <D extends CallableDescriptor> void recordAmbiguity(
437 @NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> candidates
438 ) {
439 logError();
440 }
441
442 @Override
443 public void missingReceiver(
444 @NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver
445 ) {
446 logError();
447 }
448
449 @Override
450 public void wrongReceiverType(
451 @NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument
452 ) {
453 logError();
454 }
455
456 @Override
457 public void noReceiverAllowed(@NotNull BindingTrace trace) {
458 logError();
459 }
460
461 @Override
462 public void noValueForParameter(
463 @NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter
464 ) {
465 logError();
466 }
467
468 @Override
469 public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
470 logError();
471 }
472
473 @Override
474 public <D extends CallableDescriptor> void ambiguity(
475 @NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors
476 ) {
477 logError();
478 }
479
480 @Override
481 public <D extends CallableDescriptor> void noneApplicable(
482 @NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors
483 ) {
484 logError();
485 }
486
487 @Override
488 public <D extends CallableDescriptor> void cannotCompleteResolve(
489 @NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors
490 ) {
491 logError();
492 }
493
494 @Override
495 public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
496 logError();
497 }
498
499 @Override
500 public void abstractSuperCall(@NotNull BindingTrace trace) {
501 logError();
502 }
503
504 @Override
505 public void nestedClassAccessViaInstanceReference(
506 @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor,
507 @NotNull ExplicitReceiverKind explicitReceiverKind
508 ) {
509 logError();
510 }
511
512 @Override
513 public void unsafeCall(
514 @NotNull BindingTrace trace, @NotNull KotlinType type, boolean isCallForImplicitInvoke
515 ) {
516 logError();
517 }
518
519 @Override
520 public void unnecessarySafeCall(
521 @NotNull BindingTrace trace, @NotNull KotlinType type
522 ) {
523 logError();
524 }
525
526 @Override
527 public void invisibleMember(
528 @NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor
529 ) {
530 logError();
531 }
532
533 @Override
534 public void typeInferenceFailed(
535 @NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData
536 ) {
537 logError();
538 }
539
540 @Override
541 public void nonExtensionFunctionCalledAsExtension(@NotNull BindingTrace trace) {
542 logError();
543 }
544 }
545 }