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