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.resolve;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.psi.PsiElement;
021    import kotlin.Pair;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
025    import org.jetbrains.kotlin.descriptors.*;
026    import org.jetbrains.kotlin.diagnostics.rendering.Renderers;
027    import org.jetbrains.kotlin.name.Name;
028    import org.jetbrains.kotlin.psi.*;
029    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
030    import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
031    import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
032    import org.jetbrains.kotlin.resolve.calls.inference.TypeVariableKt;
033    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
034    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
035    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
036    import org.jetbrains.kotlin.resolve.scopes.ScopeUtils;
037    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
038    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
039    import org.jetbrains.kotlin.resolve.validation.OperatorValidator;
040    import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
041    import org.jetbrains.kotlin.types.*;
042    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
043    import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
044    import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
045    import org.jetbrains.kotlin.types.expressions.FakeCallResolver;
046    import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
047    
048    import java.util.Collections;
049    import java.util.List;
050    
051    import static org.jetbrains.kotlin.diagnostics.Errors.*;
052    import static org.jetbrains.kotlin.psi.KtPsiFactoryKt.KtPsiFactory;
053    import static org.jetbrains.kotlin.resolve.BindingContext.*;
054    import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER;
055    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
056    import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
057    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType;
058    
059    public class DelegatedPropertyResolver {
060    
061        public static final Name PROPERTY_DELEGATED_FUNCTION_NAME = Name.identifier("propertyDelegated");
062        public static final Name GETTER_NAME = Name.identifier("getValue");
063        public static final Name SETTER_NAME = Name.identifier("setValue");
064    
065        public static final Name OLD_GETTER_NAME = Name.identifier("get");
066        public static final Name OLD_SETTER_NAME = Name.identifier("set");
067    
068        @NotNull private final ExpressionTypingServices expressionTypingServices;
069        @NotNull private final FakeCallResolver fakeCallResolver;
070        @NotNull private final KotlinBuiltIns builtIns;
071        @NotNull private final SymbolUsageValidator symbolUsageValidator;
072    
073        public DelegatedPropertyResolver(
074                @NotNull SymbolUsageValidator symbolUsageValidator,
075                @NotNull KotlinBuiltIns builtIns,
076                @NotNull FakeCallResolver fakeCallResolver,
077                @NotNull ExpressionTypingServices expressionTypingServices
078        ) {
079            this.symbolUsageValidator = symbolUsageValidator;
080            this.builtIns = builtIns;
081            this.fakeCallResolver = fakeCallResolver;
082            this.expressionTypingServices = expressionTypingServices;
083        }
084    
085        @Nullable
086        public KotlinType getDelegatedPropertyGetMethodReturnType(
087                @NotNull PropertyDescriptor propertyDescriptor,
088                @NotNull KtExpression delegateExpression,
089                @NotNull KotlinType delegateType,
090                @NotNull BindingTrace trace,
091                @NotNull LexicalScope delegateFunctionsScope
092        ) {
093            resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, true);
094            ResolvedCall<FunctionDescriptor> resolvedCall =
095                    trace.getBindingContext().get(DELEGATED_PROPERTY_RESOLVED_CALL, propertyDescriptor.getGetter());
096            return resolvedCall != null ? resolvedCall.getResultingDescriptor().getReturnType() : null;
097        }
098    
099        public void resolveDelegatedPropertyGetMethod(
100                @NotNull PropertyDescriptor propertyDescriptor,
101                @NotNull KtExpression delegateExpression,
102                @NotNull KotlinType delegateType,
103                @NotNull BindingTrace trace,
104                @NotNull LexicalScope delegateFunctionsScope
105        ) {
106            KotlinType returnType = getDelegatedPropertyGetMethodReturnType(
107                    propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
108            KotlinType propertyType = propertyDescriptor.getType();
109    
110            /* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
111            if (!(propertyType instanceof DeferredType) && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
112                Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter());
113                assert call != null : "Call should exists for " + propertyDescriptor.getGetter();
114                trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
115                                     .on(delegateExpression, renderCall(call, trace.getBindingContext()), propertyDescriptor.getType(), returnType));
116            }
117        }
118    
119        public void resolveDelegatedPropertySetMethod(
120                @NotNull PropertyDescriptor propertyDescriptor,
121                @NotNull KtExpression delegateExpression,
122                @NotNull KotlinType delegateType,
123                @NotNull BindingTrace trace,
124                @NotNull LexicalScope delegateFunctionsScope
125        ) {
126            resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, false);
127        }
128    
129        @NotNull
130        private static KtExpression createExpressionForProperty(@NotNull KtPsiFactory psiFactory) {
131            return psiFactory.createExpression("null as " + KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName().asString() + "<*>");
132        }
133    
134        public void resolveDelegatedPropertyPDMethod(
135                @NotNull PropertyDescriptor propertyDescriptor,
136                @NotNull KtExpression delegateExpression,
137                @NotNull KotlinType delegateType,
138                @NotNull BindingTrace trace,
139                @NotNull LexicalScope delegateFunctionsScope
140        ) {
141            TemporaryBindingTrace traceToResolvePDMethod = TemporaryBindingTrace.create(trace, "Trace to resolve propertyDelegated method in delegated property");
142            ExpressionTypingContext context = ExpressionTypingContext.newContext(
143                    traceToResolvePDMethod, delegateFunctionsScope,
144                    DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
145    
146            KtPsiFactory psiFactory = KtPsiFactory(delegateExpression);
147            List<KtExpression> arguments = Collections.singletonList(createExpressionForProperty(psiFactory));
148            ExpressionReceiver receiver = ExpressionReceiver.Companion.create(delegateExpression, delegateType, trace.getBindingContext());
149    
150            Pair<Call, OverloadResolutionResults<FunctionDescriptor>> resolutionResult =
151                    fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, PROPERTY_DELEGATED_FUNCTION_NAME, delegateExpression);
152    
153            Call call = resolutionResult.getFirst();
154            OverloadResolutionResults<FunctionDescriptor> functionResults = resolutionResult.getSecond();
155    
156            if (!functionResults.isSuccess()) {
157                String expectedFunction = renderCall(call, traceToResolvePDMethod.getBindingContext());
158                if (functionResults.isIncomplete() || functionResults.isSingleResult() ||
159                    functionResults.getResultCode() == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
160                    trace.report(DELEGATE_PD_METHOD_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
161                } else if (functionResults.isAmbiguity()) {
162                    trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
163                                         .on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
164                }
165                return;
166            }
167    
168            trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, propertyDescriptor, functionResults.getResultingCall());
169        }
170    
171        /* Resolve getValue() or setValue() methods from delegate */
172        private void resolveDelegatedPropertyConventionMethod(
173                @NotNull PropertyDescriptor propertyDescriptor,
174                @NotNull KtExpression delegateExpression,
175                @NotNull KotlinType delegateType,
176                @NotNull BindingTrace trace,
177                @NotNull LexicalScope delegateFunctionsScope,
178                boolean isGet
179        ) {
180            PropertyAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
181            assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
182    
183            if (trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor) != null) return;
184    
185            OverloadResolutionResults<FunctionDescriptor> functionResults = getDelegatedPropertyConventionMethod(
186                    propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, isGet, true);
187            Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor);
188            assert call != null : "'getDelegatedPropertyConventionMethod' didn't record a call";
189    
190            if (!functionResults.isSuccess()) {
191                String expectedFunction = renderCall(call, trace.getBindingContext());
192                if (functionResults.isSingleResult() || functionResults.isIncomplete() ||
193                         functionResults.getResultCode() == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
194                    trace.report(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE
195                                         .on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
196                }
197                else if (functionResults.isAmbiguity()) {
198                    trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
199                                                 .on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
200                }
201                else {
202                    trace.report(DELEGATE_SPECIAL_FUNCTION_MISSING.on(delegateExpression, expectedFunction, delegateType));
203                }
204                return;
205            }
206    
207            FunctionDescriptor resultingDescriptor = functionResults.getResultingDescriptor();
208    
209            ResolvedCall<FunctionDescriptor> resultingCall = functionResults.getResultingCall();
210            PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
211            if (declaration instanceof KtProperty) {
212                KtProperty property = (KtProperty) declaration;
213                KtPropertyDelegate delegate = property.getDelegate();
214                if (delegate != null) {
215                    PsiElement byKeyword = delegate.getByKeywordNode().getPsi();
216    
217                    if (!resultingDescriptor.isOperator()) {
218                        OperatorValidator.Companion.report(byKeyword, resultingDescriptor, trace);
219                    }
220    
221                    symbolUsageValidator.validateCall(resultingCall, resultingCall.getResultingDescriptor(), trace, byKeyword);
222                }
223            }
224            trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall);
225        }
226    
227        /* Resolve getValue() or setValue() methods from delegate */
228        public OverloadResolutionResults<FunctionDescriptor> getDelegatedPropertyConventionMethod(
229                @NotNull PropertyDescriptor propertyDescriptor,
230                @NotNull KtExpression delegateExpression,
231                @NotNull KotlinType delegateType,
232                @NotNull BindingTrace trace,
233                @NotNull LexicalScope delegateFunctionsScope,
234                boolean isGet,
235                boolean isComplete
236        ) {
237            PropertyAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
238            assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
239    
240            KotlinType expectedType = isComplete && isGet && !(propertyDescriptor.getType() instanceof DeferredType)
241                                   ? propertyDescriptor.getType() : TypeUtils.NO_EXPECTED_TYPE;
242    
243            ExpressionTypingContext context = ExpressionTypingContext.newContext(
244                    trace, delegateFunctionsScope,
245                    DataFlowInfo.EMPTY, expectedType);
246    
247            boolean hasThis = propertyDescriptor.getExtensionReceiverParameter() != null || propertyDescriptor.getDispatchReceiverParameter() != null;
248    
249            List<KtExpression> arguments = Lists.newArrayList();
250            KtPsiFactory psiFactory = KtPsiFactory(delegateExpression);
251            arguments.add(psiFactory.createExpression(hasThis ? "this" : "null"));
252            arguments.add(createExpressionForProperty(psiFactory));
253    
254            if (!isGet) {
255                KtReferenceExpression fakeArgument = (KtReferenceExpression) createFakeExpressionOfType(delegateExpression.getProject(), trace,
256                                                                                                          "fakeArgument" + arguments.size(),
257                                                                                                        propertyDescriptor.getType());
258                arguments.add(fakeArgument);
259                List<ValueParameterDescriptor> valueParameters = accessor.getValueParameters();
260                trace.record(REFERENCE_TARGET, fakeArgument, valueParameters.get(0));
261            }
262    
263            Name functionName = isGet ? GETTER_NAME : SETTER_NAME;
264            ExpressionReceiver receiver = ExpressionReceiver.Companion.create(delegateExpression, delegateType, trace.getBindingContext());
265    
266            Pair<Call, OverloadResolutionResults<FunctionDescriptor>> resolutionResult =
267                    fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression);
268    
269            OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolutionResult.getSecond();
270    
271            // Resolve get/set is getValue/setValue was not found. Temporary, for code migration
272            if (!resolutionResults.isSuccess() && !resolutionResults.isAmbiguity()) {
273                Name oldFunctionName = isGet ? OLD_GETTER_NAME : OLD_SETTER_NAME;
274                Pair<Call, OverloadResolutionResults<FunctionDescriptor>> additionalResolutionResult =
275                        fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, oldFunctionName, delegateExpression);
276                if (additionalResolutionResult.getSecond().isSuccess()) {
277                    FunctionDescriptor resultingDescriptor = additionalResolutionResult.getSecond().getResultingDescriptor();
278    
279                    PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
280                    if (declaration instanceof KtProperty) {
281                        KtProperty property = (KtProperty) declaration;
282                        KtPropertyDelegate delegate = property.getDelegate();
283                        if (delegate != null) {
284                            PsiElement byKeyword = delegate.getByKeywordNode().getPsi();
285    
286                            trace.report(DELEGATE_RESOLVED_TO_DEPRECATED_CONVENTION.on(
287                                    byKeyword, resultingDescriptor, delegateType, functionName.asString()));
288                        }
289                    }
290    
291                    trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, additionalResolutionResult.getFirst());
292                    return additionalResolutionResult.getSecond();
293                }
294            }
295    
296            trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.getFirst());
297            return resolutionResults;
298        }
299    
300        private static String renderCall(@NotNull Call call, @NotNull BindingContext context) {
301            KtExpression calleeExpression = call.getCalleeExpression();
302            assert calleeExpression != null : "CalleeExpression should exists for fake call of convention method";
303            StringBuilder builder = new StringBuilder(calleeExpression.getText());
304            builder.append("(");
305            List<KotlinType> argumentTypes = Lists.newArrayList();
306            for (ValueArgument argument : call.getValueArguments()) {
307                argumentTypes.add(context.getType(argument.getArgumentExpression()));
308    
309            }
310            builder.append(Renderers.RENDER_COLLECTION_OF_TYPES.render(argumentTypes));
311            builder.append(")");
312            return builder.toString();
313        }
314    
315        @NotNull
316        public KotlinType resolveDelegateExpression(
317                @NotNull KtExpression delegateExpression,
318                @NotNull KtProperty property,
319                @NotNull PropertyDescriptor propertyDescriptor,
320                @NotNull LexicalScope scopeForDelegate,
321                @NotNull BindingTrace trace,
322                @NotNull DataFlowInfo dataFlowInfo
323        ) {
324            TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property");
325            KtExpression calleeExpression = CallUtilKt.getCalleeExpressionIfAny(delegateExpression);
326            ConstraintSystemCompleter completer = createConstraintSystemCompleter(
327                    property, propertyDescriptor, delegateExpression, scopeForDelegate, trace);
328            if (calleeExpression != null) {
329                traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer);
330            }
331            KotlinType delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE,
332                                                                           dataFlowInfo, traceToResolveDelegatedProperty);
333            traceToResolveDelegatedProperty.commit(new TraceEntryFilter() {
334                @Override
335                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
336                    return slice != CONSTRAINT_SYSTEM_COMPLETER;
337                }
338            }, true);
339            return delegateType;
340        }
341    
342        @NotNull
343        private ConstraintSystemCompleter createConstraintSystemCompleter(
344                @NotNull KtProperty property,
345                @NotNull final PropertyDescriptor propertyDescriptor,
346                @NotNull final KtExpression delegateExpression,
347                @NotNull LexicalScope scopeForDelegate,
348                @NotNull final BindingTrace trace
349        ) {
350            final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, propertyDescriptor);
351            final KotlinType expectedType = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
352            return new ConstraintSystemCompleter() {
353                @Override
354                public void completeConstraintSystem(
355                        @NotNull ConstraintSystem.Builder constraintSystem, @NotNull ResolvedCall<?> resolvedCall
356                ) {
357                    KotlinType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
358                    if (returnType == null) return;
359    
360                    TypeSubstitutor typeVariableSubstitutor =
361                            constraintSystem.getTypeVariableSubstitutors().get(TypeVariableKt.toHandle(resolvedCall.getCall()));
362                    assert typeVariableSubstitutor != null : "No substitutor in the system for call: " + resolvedCall.getCall();
363    
364                    TemporaryBindingTrace traceToResolveConventionMethods =
365                            TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
366                    OverloadResolutionResults<FunctionDescriptor>
367                            getMethodResults = getDelegatedPropertyConventionMethod(
368                                    propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
369                                    true, false
370                            );
371    
372                    if (conventionMethodFound(getMethodResults)) {
373                        FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor();
374                        KotlinType returnTypeOfGetMethod = descriptor.getReturnType();
375                        if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
376                            KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
377                            if (returnTypeInSystem != null) {
378                                constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position());
379                            }
380                        }
381                        addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
382                    }
383                    if (!propertyDescriptor.isVar()) return;
384    
385                    // For the case: 'val v by d' (no declared type).
386                    // When we add a constraint for 'set' method for delegated expression 'd' we use a type of the declared variable 'v'.
387                    // But if the type isn't known yet, the constraint shouldn't be added (we try to infer the type of 'v' here as well).
388                    if (propertyDescriptor.getReturnType() instanceof DeferredType) return;
389    
390                    OverloadResolutionResults<FunctionDescriptor>
391                            setMethodResults = getDelegatedPropertyConventionMethod(
392                                    propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
393                                    false, false
394                            );
395    
396                    if (conventionMethodFound(setMethodResults)) {
397                        FunctionDescriptor descriptor = setMethodResults.getResultingDescriptor();
398                        List<ValueParameterDescriptor> valueParameters = descriptor.getValueParameters();
399                        if (valueParameters.size() == 3) {
400                            ValueParameterDescriptor valueParameterForThis = valueParameters.get(2);
401    
402                            if (!noExpectedType(expectedType)) {
403                                constraintSystem.addSubtypeConstraint(
404                                        expectedType,
405                                        typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
406                                        FROM_COMPLETER.position()
407                                );
408                            }
409                            addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
410                        }
411                    }
412                }
413    
414                private boolean conventionMethodFound(@NotNull OverloadResolutionResults<FunctionDescriptor> results) {
415                    return results.isSuccess() ||
416                           (results.isSingleResult() &&
417                            results.getResultCode() == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
418                }
419    
420                private void addConstraintForThisValue(
421                        ConstraintSystem.Builder constraintSystem,
422                        TypeSubstitutor typeVariableSubstitutor,
423                        FunctionDescriptor resultingDescriptor
424                ) {
425                    ReceiverParameterDescriptor extensionReceiver = propertyDescriptor.getExtensionReceiverParameter();
426                    ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter();
427                    KotlinType typeOfThis =
428                            extensionReceiver != null ? extensionReceiver.getType() :
429                            dispatchReceiver != null ? dispatchReceiver.getType() :
430                            builtIns.getNullableNothingType();
431    
432                    List<ValueParameterDescriptor> valueParameters = resultingDescriptor.getValueParameters();
433                    if (valueParameters.isEmpty()) return;
434                    ValueParameterDescriptor valueParameterForThis = valueParameters.get(0);
435    
436                    constraintSystem.addSubtypeConstraint(
437                            typeOfThis,
438                            typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
439                            FROM_COMPLETER.position()
440                    );
441                }
442            };
443        }
444    }