001    /*
002     * Copyright 2010-2016 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 kotlin.Unit;
020    import kotlin.collections.CollectionsKt;
021    import kotlin.jvm.functions.Function1;
022    import org.jetbrains.annotations.Mutable;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.kotlin.descriptors.*;
026    import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
028    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
029    import org.jetbrains.kotlin.name.Name;
030    import org.jetbrains.kotlin.types.FlexibleTypesKt;
031    import org.jetbrains.kotlin.types.KotlinType;
032    import org.jetbrains.kotlin.types.TypeConstructor;
033    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
034    import org.jetbrains.kotlin.utils.FunctionsKt;
035    import org.jetbrains.kotlin.utils.SmartSet;
036    
037    import java.util.*;
038    
039    import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*;
040    
041    public class OverridingUtil {
042    
043        private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
044                CollectionsKt.toList(ServiceLoader.load(
045                        ExternalOverridabilityCondition.class,
046                        ExternalOverridabilityCondition.class.getClassLoader()
047                ));
048    
049        public static final OverridingUtil DEFAULT = new OverridingUtil(new KotlinTypeChecker.TypeConstructorEquality() {
050            @Override
051            public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
052                return a.equals(b);
053            }
054        });
055    
056        @NotNull
057        public static OverridingUtil createWithEqualityAxioms(@NotNull KotlinTypeChecker.TypeConstructorEquality equalityAxioms) {
058            return new OverridingUtil(equalityAxioms);
059        }
060    
061        private final KotlinTypeChecker.TypeConstructorEquality equalityAxioms;
062    
063        private OverridingUtil(KotlinTypeChecker.TypeConstructorEquality axioms) {
064            equalityAxioms = axioms;
065        }
066    
067        /**
068         * Given a set of descriptors, returns a set containing all the given descriptors except those which _are overridden_ by at least
069         * one other descriptor from the original set.
070         */
071        @NotNull
072        public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
073            return filterOverrides(candidateSet, FunctionsKt.<CallableDescriptor>identity());
074        }
075    
076        @NotNull
077        public static <D> Set<D> filterOverrides(
078                @NotNull Set<D> candidateSet,
079                @NotNull Function1<? super D, ? extends CallableDescriptor> transform
080        ) {
081            if (candidateSet.size() <= 1) return candidateSet;
082    
083            Set<D> result = new LinkedHashSet<D>();
084            outerLoop:
085            for (D meD : candidateSet) {
086                CallableDescriptor me = transform.invoke(meD);
087                for (Iterator<D> iterator = result.iterator(); iterator.hasNext(); ) {
088                    D otherD = iterator.next();
089                    CallableDescriptor other = transform.invoke(otherD);
090                    if (overrides(me, other)) {
091                        iterator.remove();
092                    }
093                    else if (overrides(other, me)) {
094                        continue outerLoop;
095                    }
096                }
097                result.add(meD);
098            }
099    
100            assert !result.isEmpty() : "All candidates filtered out from " + candidateSet;
101    
102            return result;
103        }
104    
105        /**
106         * @return whether f overrides g
107         */
108        public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
109            // In a multi-module project different "copies" of the same class may be present in different libraries,
110            // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).
111    
112            // This first check cover the case of duplicate classes in different modules:
113            // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions,
114            // we'll be getting sets of members that do not override each other, but are structurally equivalent.
115            // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
116            // Note that this is needed for the usage of this function in the IDE code
117            if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal())) return true;
118    
119            CallableDescriptor originalG = g.getOriginal();
120            for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) {
121                if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction.getOriginal())) return true;
122            }
123            return false;
124        }
125    
126        /**
127         * @return overridden real descriptors (not fake overrides). Note that most usages of this method should be followed by calling
128         * {@link #filterOutOverridden(Set)}, because some of the declarations can override the other.
129         */
130        @NotNull
131        public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
132            Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
133            collectOverriddenDeclarations(descriptor, result);
134            return result;
135        }
136    
137        private static void collectOverriddenDeclarations(
138                @NotNull CallableMemberDescriptor descriptor,
139                @NotNull Set<CallableMemberDescriptor> result
140        ) {
141            if (descriptor.getKind().isReal()) {
142                result.add(descriptor);
143            }
144            else {
145                if (descriptor.getOverriddenDescriptors().isEmpty()) {
146                    throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
147                }
148                for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
149                    collectOverriddenDeclarations(overridden, result);
150                }
151            }
152        }
153    
154        @NotNull
155        public OverrideCompatibilityInfo isOverridableBy(
156                @NotNull CallableDescriptor superDescriptor,
157                @NotNull CallableDescriptor subDescriptor,
158                @Nullable ClassDescriptor subClassDescriptor
159        ) {
160            return isOverridableBy(superDescriptor, subDescriptor, subClassDescriptor, false);
161        }
162    
163        @NotNull
164        public OverrideCompatibilityInfo isOverridableBy(
165                @NotNull CallableDescriptor superDescriptor,
166                @NotNull CallableDescriptor subDescriptor,
167                @Nullable ClassDescriptor subClassDescriptor,
168                boolean checkReturnType
169        ) {
170            OverrideCompatibilityInfo basicResult = isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType);
171            boolean wasSuccess = basicResult.getResult() == OVERRIDABLE;
172    
173            for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
174                // Do not run CONFLICTS_ONLY while there was no success
175                if (externalCondition.getContract() == ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY) continue;
176                if (wasSuccess && externalCondition.getContract() == ExternalOverridabilityCondition.Contract.SUCCESS_ONLY) continue;
177    
178                ExternalOverridabilityCondition.Result result =
179                        externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);
180    
181                switch (result) {
182                    case OVERRIDABLE:
183                        wasSuccess = true;
184                        break;
185                    case CONFLICT:
186                        return OverrideCompatibilityInfo.conflict("External condition failed");
187                    case INCOMPATIBLE:
188                        return OverrideCompatibilityInfo.incompatible("External condition");
189                    case UNKNOWN:
190                        // do nothing
191                        // go to the next external condition or default override check
192                }
193            }
194    
195            if (!wasSuccess) {
196                return basicResult;
197            }
198    
199            // Search for conflicts from external conditions
200            for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
201                // Run all conditions that was not run before (i.e. CONFLICTS_ONLY)
202                if (externalCondition.getContract() != ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY) continue;
203    
204                ExternalOverridabilityCondition.Result result =
205                        externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);
206                switch (result) {
207                    case CONFLICT:
208                        return OverrideCompatibilityInfo.conflict("External condition failed");
209                    case INCOMPATIBLE:
210                        return OverrideCompatibilityInfo.incompatible("External condition");
211                    case OVERRIDABLE:
212                        throw new IllegalStateException(
213                                "Contract violation in " + externalCondition.getClass().getName() + " condition. It's not supposed to end with success");
214                    case UNKNOWN:
215                        // do nothing
216                        // go to the next external condition or default override check
217                }
218            }
219    
220            return OverrideCompatibilityInfo.success();
221        }
222    
223        @NotNull
224        public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions(
225                @NotNull CallableDescriptor superDescriptor,
226                @NotNull CallableDescriptor subDescriptor,
227                boolean checkReturnType
228        ) {
229            OverrideCompatibilityInfo basicOverridability = getBasicOverridabilityProblem(superDescriptor, subDescriptor);
230            if (basicOverridability != null) return basicOverridability;
231    
232            List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
233            List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);
234    
235            List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
236            List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
237    
238            if (superTypeParameters.size() != subTypeParameters.size()) {
239                for (int i = 0; i < superValueParameters.size(); ++i) {
240                    // TODO: compare erasure
241                    if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameters.get(i), subValueParameters.get(i))) {
242                        return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
243                    }
244                }
245                return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
246            }
247    
248            KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters);
249    
250            for (int i = 0; i < superTypeParameters.size(); i++) {
251                if (!areTypeParametersEquivalent(superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) {
252                    return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
253                }
254            }
255    
256            for (int i = 0; i < superValueParameters.size(); i++) {
257                if (!areTypesEquivalent(superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
258                    return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
259                }
260            }
261    
262            if (checkReturnType) {
263                KotlinType superReturnType = superDescriptor.getReturnType();
264                KotlinType subReturnType = subDescriptor.getReturnType();
265    
266                if (superReturnType != null && subReturnType != null) {
267                    boolean bothErrors = subReturnType.isError() && superReturnType.isError();
268                    if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) {
269                        return OverrideCompatibilityInfo.conflict("Return type mismatch");
270                    }
271                }
272            }
273    
274            return OverrideCompatibilityInfo.success();
275        }
276    
277        @Nullable
278        public static OverrideCompatibilityInfo getBasicOverridabilityProblem(
279                @NotNull CallableDescriptor superDescriptor,
280                @NotNull CallableDescriptor subDescriptor
281        ) {
282            if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) ||
283                superDescriptor instanceof PropertyDescriptor && !(subDescriptor instanceof PropertyDescriptor)) {
284                return OverrideCompatibilityInfo.incompatible("Member kind mismatch");
285            }
286    
287            if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof PropertyDescriptor)) {
288                throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
289            }
290    
291            // TODO: check outside of this method
292            if (!superDescriptor.getName().equals(subDescriptor.getName())) {
293                return OverrideCompatibilityInfo.incompatible("Name mismatch");
294            }
295    
296            OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor);
297            if (receiverAndParameterResult != null) {
298                return receiverAndParameterResult;
299            }
300    
301            return null;
302        }
303    
304        @NotNull
305        private KotlinTypeChecker createTypeChecker(
306                @NotNull List<TypeParameterDescriptor> firstParameters,
307                @NotNull List<TypeParameterDescriptor> secondParameters
308        ) {
309            assert firstParameters.size() == secondParameters.size() :
310                    "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;
311            if (firstParameters.isEmpty()) return KotlinTypeChecker.withAxioms(equalityAxioms);
312    
313            final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
314            for (int i = 0; i < firstParameters.size(); i++) {
315                matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
316            }
317    
318            return KotlinTypeChecker.withAxioms(new KotlinTypeChecker.TypeConstructorEquality() {
319                @Override
320                public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
321                    if (equalityAxioms.equals(a, b)) return true;
322                    TypeConstructor img1 = matchingTypeConstructors.get(a);
323                    TypeConstructor img2 = matchingTypeConstructors.get(b);
324                    return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a));
325                }
326            });
327        }
328    
329        @Nullable
330        private static OverrideCompatibilityInfo checkReceiverAndParameterCount(
331                CallableDescriptor superDescriptor,
332                CallableDescriptor subDescriptor
333        ) {
334            if ((superDescriptor.getExtensionReceiverParameter() == null) != (subDescriptor.getExtensionReceiverParameter() == null)) {
335                return OverrideCompatibilityInfo.incompatible("Receiver presence mismatch");
336            }
337    
338            if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
339                return OverrideCompatibilityInfo.incompatible("Value parameter number mismatch");
340            }
341    
342            return null;
343        }
344    
345        private static boolean areTypesEquivalent(
346                @NotNull KotlinType typeInSuper,
347                @NotNull KotlinType typeInSub,
348                @NotNull KotlinTypeChecker typeChecker
349        ) {
350            boolean bothErrors = typeInSuper.isError() && typeInSub.isError();
351            return bothErrors || typeChecker.equalTypes(typeInSuper, typeInSub);
352        }
353    
354        // See JLS 8, 8.4.4 Generic Methods
355        // TODO: use TypeSubstitutor instead
356        private static boolean areTypeParametersEquivalent(
357                @NotNull TypeParameterDescriptor superTypeParameter,
358                @NotNull TypeParameterDescriptor subTypeParameter,
359                @NotNull KotlinTypeChecker typeChecker
360        ) {
361            List<KotlinType> superBounds = superTypeParameter.getUpperBounds();
362            List<KotlinType> subBounds = new ArrayList<KotlinType>(subTypeParameter.getUpperBounds());
363            if (superBounds.size() != subBounds.size()) return false;
364    
365            outer:
366            for (KotlinType superBound : superBounds) {
367                ListIterator<KotlinType> it = subBounds.listIterator();
368                while (it.hasNext()) {
369                    KotlinType subBound = it.next();
370                    if (areTypesEquivalent(superBound, subBound, typeChecker)) {
371                        it.remove();
372                        continue outer;
373                    }
374                }
375                return false;
376            }
377    
378            return true;
379        }
380    
381        private static List<KotlinType> compiledValueParameters(CallableDescriptor callableDescriptor) {
382            ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
383            List<KotlinType> parameters = new ArrayList<KotlinType>();
384            if (receiverParameter != null) {
385                parameters.add(receiverParameter.getType());
386            }
387            for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
388                parameters.add(valueParameterDescriptor.getType());
389            }
390            return parameters;
391        }
392    
393        public static void generateOverridesInFunctionGroup(
394                @SuppressWarnings("UnusedParameters")
395                @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
396                @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
397                @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
398                @NotNull ClassDescriptor current,
399                @NotNull OverridingStrategy strategy
400        ) {
401            Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes);
402    
403            for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
404                Collection<CallableMemberDescriptor> bound =
405                        extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, strategy);
406                notOverridden.removeAll(bound);
407            }
408    
409            createAndBindFakeOverrides(current, notOverridden, strategy);
410        }
411    
412        private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
413                @NotNull CallableMemberDescriptor fromCurrent,
414                @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
415                @NotNull ClassDescriptor current,
416                @NotNull OverridingStrategy strategy
417        ) {
418            Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size());
419            Collection<CallableMemberDescriptor> overridden = SmartSet.create();
420            for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
421                OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent, current).getResult();
422    
423                boolean isVisible = Visibilities.isVisibleIgnoringReceiver(fromSupertype, current);
424                switch (result) {
425                    case OVERRIDABLE:
426                        if (isVisible) {
427                            overridden.add(fromSupertype);
428                        }
429                        bound.add(fromSupertype);
430                        break;
431                    case CONFLICT:
432                        if (isVisible) {
433                            strategy.overrideConflict(fromSupertype, fromCurrent);
434                        }
435                        bound.add(fromSupertype);
436                        break;
437                    case INCOMPATIBLE:
438                        break;
439                }
440            }
441    
442            strategy.setOverriddenDescriptors(fromCurrent, overridden);
443    
444            return bound;
445        }
446    
447        private static boolean allHasSameContainingDeclaration(@NotNull Collection<CallableMemberDescriptor> notOverridden) {
448            if (notOverridden.size() < 2) return true;
449    
450            final DeclarationDescriptor containingDeclaration = notOverridden.iterator().next().getContainingDeclaration();
451            return CollectionsKt.all(notOverridden, new Function1<CallableMemberDescriptor, Boolean>() {
452                @Override
453                public Boolean invoke(CallableMemberDescriptor descriptor) {
454                    return descriptor.getContainingDeclaration() == containingDeclaration;
455                }
456            });
457        }
458    
459        private static void createAndBindFakeOverrides(
460                @NotNull ClassDescriptor current,
461                @NotNull Collection<CallableMemberDescriptor> notOverridden,
462                @NotNull OverridingStrategy strategy
463        ) {
464            // Optimization: If all notOverridden descriptors have the same containing declaration,
465            // then we can just create fake overrides for them, because they should be matched correctly in their containing declaration
466            if (allHasSameContainingDeclaration(notOverridden)) {
467                for (CallableMemberDescriptor descriptor : notOverridden) {
468                    createAndBindFakeOverride(Collections.singleton(descriptor), current, strategy);
469                }
470                return;
471            }
472    
473            Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
474            while (!fromSuperQueue.isEmpty()) {
475                CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue);
476                Collection<CallableMemberDescriptor> overridables =
477                        extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, strategy);
478                createAndBindFakeOverride(overridables, current, strategy);
479            }
480        }
481    
482        public static boolean isMoreSpecific(@NotNull CallableDescriptor a, @NotNull CallableDescriptor b) {
483            KotlinType aReturnType = a.getReturnType();
484            KotlinType bReturnType = b.getReturnType();
485    
486            assert aReturnType != null : "Return type of " + a + " is null";
487            assert bReturnType != null : "Return type of " + b + " is null";
488    
489            if (!isVisibilityMoreSpecific(a, b)) return false;
490    
491            if (a instanceof SimpleFunctionDescriptor) {
492                assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
493    
494                return isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType);
495            }
496            if (a instanceof PropertyDescriptor) {
497                assert b instanceof PropertyDescriptor : "b is " + b.getClass();
498    
499                PropertyDescriptor pa = (PropertyDescriptor) a;
500                PropertyDescriptor pb = (PropertyDescriptor) b;
501    
502                if (!isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false;
503    
504                if (pa.isVar() && pb.isVar()) {
505                    return DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters()).equalTypes(aReturnType, bReturnType);
506                }
507                else {
508                    // both vals or var vs val: val can't be more specific then var
509                    return !(!pa.isVar() && pb.isVar()) && isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType);
510                }
511            }
512            throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
513        }
514    
515        private static boolean isVisibilityMoreSpecific(
516                @NotNull DeclarationDescriptorWithVisibility a,
517                @NotNull DeclarationDescriptorWithVisibility b
518        ) {
519            Integer result = Visibilities.compare(a.getVisibility(), b.getVisibility());
520            return result == null || result >= 0;
521        }
522    
523        private static boolean isAccessorMoreSpecific(@Nullable PropertyAccessorDescriptor a, @Nullable PropertyAccessorDescriptor b) {
524            if (a == null || b == null) return true;
525            return isVisibilityMoreSpecific(a, b);
526        }
527    
528        private static boolean isMoreSpecificThenAllOf(@NotNull CallableDescriptor candidate, @NotNull Collection<CallableDescriptor> descriptors) {
529            // NB subtyping relation in Kotlin is not transitive in presence of flexible types:
530            //  String? <: String! <: String, but not String? <: String
531            for (CallableDescriptor descriptor : descriptors) {
532                if (!isMoreSpecific(candidate, descriptor)) {
533                    return false;
534                }
535            }
536            return true;
537        }
538    
539        private static boolean isReturnTypeMoreSpecific(
540                @NotNull CallableDescriptor a,
541                @NotNull KotlinType aReturnType,
542                @NotNull CallableDescriptor b,
543                @NotNull KotlinType bReturnType
544        ) {
545            KotlinTypeChecker typeChecker = DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters());
546            return typeChecker.isSubtypeOf(aReturnType, bReturnType);
547        }
548    
549        @NotNull
550        public static <H> H selectMostSpecificMember(
551                @NotNull Collection<H> overridables,
552                @NotNull Function1<H, CallableDescriptor> descriptorByHandle
553        ) {
554            assert !overridables.isEmpty() : "Should have at least one overridable descriptor";
555    
556            if (overridables.size() == 1) {
557                return CollectionsKt.first(overridables);
558            }
559    
560            Collection<H> candidates = new ArrayList<H>(2);
561            List<CallableDescriptor> callableMemberDescriptors = CollectionsKt.map(overridables, descriptorByHandle);
562    
563            H transitivelyMostSpecific = CollectionsKt.first(overridables);
564            CallableDescriptor transitivelyMostSpecificDescriptor = descriptorByHandle.invoke(transitivelyMostSpecific);
565    
566            for (H overridable : overridables) {
567                CallableDescriptor descriptor = descriptorByHandle.invoke(overridable);
568                if (isMoreSpecificThenAllOf(descriptor, callableMemberDescriptors)) {
569                    candidates.add(overridable);
570                }
571                if (isMoreSpecific(descriptor, transitivelyMostSpecificDescriptor)
572                    && !isMoreSpecific(transitivelyMostSpecificDescriptor, descriptor)) {
573                    transitivelyMostSpecific = overridable;
574                }
575            }
576    
577            if (candidates.isEmpty()) {
578                return transitivelyMostSpecific;
579            }
580            else if (candidates.size() == 1) {
581                return CollectionsKt.first(candidates);
582            }
583    
584            H firstNonFlexible = null;
585            for (H candidate : candidates) {
586                //noinspection ConstantConditions
587                if (!FlexibleTypesKt.isFlexible(descriptorByHandle.invoke(candidate).getReturnType())) {
588                    firstNonFlexible = candidate;
589                    break;
590                }
591            }
592            if (firstNonFlexible != null) {
593                return firstNonFlexible;
594            }
595    
596            return CollectionsKt.first(candidates);
597        }
598    
599        private static void createAndBindFakeOverride(
600                @NotNull Collection<CallableMemberDescriptor> overridables,
601                @NotNull ClassDescriptor current,
602                @NotNull OverridingStrategy strategy
603        ) {
604            Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
605            boolean allInvisible = visibleOverridables.isEmpty();
606            Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
607    
608            Modality modality = determineModality(effectiveOverridden);
609            Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
610    
611            // FIXME doesn't work as expected for flexible types: should create a refined signature.
612            // Current algorithm produces bad results in presence of annotated Java signatures such as:
613            //      J: foo(s: String!): String -- @NotNull String foo(String s);
614            //      K: foo(s: String): String?
615            //  --> 'foo(s: String!): String' as an inherited signature with most specific return type.
616            // This is bad because it can be overridden by 'foo(s: String?): String', which is not override-equivalent with K::foo above.
617            // Should be 'foo(s: String): String'.
618            CallableMemberDescriptor mostSpecific =
619                    selectMostSpecificMember(effectiveOverridden,
620                                             new Function1<CallableMemberDescriptor, CallableDescriptor>() {
621                                                  @Override
622                                                  public CallableMemberDescriptor invoke(CallableMemberDescriptor descriptor) {
623                                                      return descriptor;
624                                                  }
625                                             });
626            CallableMemberDescriptor fakeOverride =
627                    mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
628            strategy.setOverriddenDescriptors(fakeOverride, effectiveOverridden);
629            assert !fakeOverride.getOverriddenDescriptors().isEmpty()
630                    : "Overridden descriptors should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
631            strategy.addFakeOverride(fakeOverride);
632        }
633    
634        @NotNull
635        private static Modality determineModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
636            // Optimization: avoid creating hash sets in frequent cases when modality can be computed trivially
637            boolean hasOpen = false;
638            boolean hasAbstract = false;
639            for (CallableMemberDescriptor descriptor : descriptors) {
640                switch (descriptor.getModality()) {
641                    case FINAL:
642                        return Modality.FINAL;
643                    case SEALED:
644                        throw new IllegalStateException("Member cannot have SEALED modality: " + descriptor);
645                    case OPEN:
646                        hasOpen = true;
647                        break;
648                    case ABSTRACT:
649                        hasAbstract = true;
650                        break;
651                }
652            }
653    
654            if (hasOpen && !hasAbstract) return Modality.OPEN;
655            if (!hasOpen && hasAbstract) return Modality.ABSTRACT;
656    
657            Set<CallableMemberDescriptor> allOverriddenDeclarations = new HashSet<CallableMemberDescriptor>();
658            for (CallableMemberDescriptor descriptor : descriptors) {
659                allOverriddenDeclarations.addAll(getOverriddenDeclarations(descriptor));
660            }
661            return getMinimalModality(filterOutOverridden(allOverriddenDeclarations));
662        }
663    
664        @NotNull
665        private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
666            Modality modality = Modality.ABSTRACT;
667            for (CallableMemberDescriptor descriptor : descriptors) {
668                if (descriptor.getModality().compareTo(modality) < 0) {
669                    modality = descriptor.getModality();
670                }
671            }
672            return modality;
673        }
674    
675        @NotNull
676        private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
677                @NotNull final ClassDescriptor current,
678                @NotNull Collection<CallableMemberDescriptor> toFilter
679        ) {
680            return CollectionsKt.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() {
681                @Override
682                public Boolean invoke(CallableMemberDescriptor descriptor) {
683                    //nested class could capture private member, so check for private visibility added
684                    return !Visibilities.isPrivate(descriptor.getVisibility()) &&
685                           Visibilities.isVisibleIgnoringReceiver(descriptor, current);
686                }
687            });
688        }
689    
690        /**
691         * @param <H> is something that handles CallableDescriptor inside
692         * @return
693         */
694        @NotNull
695        public static <H> Collection<H> extractMembersOverridableInBothWays(
696                @NotNull H overrider,
697                @NotNull @Mutable Collection<H> extractFrom,
698                @NotNull Function1<H, CallableDescriptor> descriptorByHandle,
699                @NotNull Function1<H, Unit> onConflict
700        ) {
701            Collection<H> overridable = new ArrayList<H>();
702            overridable.add(overrider);
703            CallableDescriptor overriderDescriptor = descriptorByHandle.invoke(overrider);
704            for (Iterator<H> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
705                H candidate = iterator.next();
706                CallableDescriptor candidateDescriptor = descriptorByHandle.invoke(candidate);
707                if (overrider == candidate) {
708                    iterator.remove();
709                    continue;
710                }
711    
712                OverrideCompatibilityInfo.Result finalResult = getBothWaysOverridability(overriderDescriptor, candidateDescriptor);
713    
714                if (finalResult == OVERRIDABLE) {
715                    overridable.add(candidate);
716                    iterator.remove();
717                }
718                else if (finalResult == CONFLICT) {
719                    onConflict.invoke(candidate);
720                    iterator.remove();
721                }
722            }
723            return overridable;
724        }
725    
726        @Nullable
727        public static OverrideCompatibilityInfo.Result getBothWaysOverridability(
728                CallableDescriptor overriderDescriptor,
729                CallableDescriptor candidateDescriptor
730        ) {
731            OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidateDescriptor, overriderDescriptor, null).getResult();
732            OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overriderDescriptor, candidateDescriptor, null).getResult();
733    
734            return result1 == OVERRIDABLE && result2 == OVERRIDABLE
735                   ? OVERRIDABLE
736                   : ((result1 == CONFLICT || result2 == CONFLICT) ? CONFLICT : INCOMPATIBLE);
737        }
738    
739        @NotNull
740        private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
741                @NotNull final CallableMemberDescriptor overrider,
742                @NotNull Queue<CallableMemberDescriptor> extractFrom,
743                @NotNull final OverridingStrategy strategy
744        ) {
745            return extractMembersOverridableInBothWays(overrider, extractFrom,
746                    // ID
747                    new Function1<CallableMemberDescriptor, CallableDescriptor>() {
748                        @Override
749                        public CallableDescriptor invoke(CallableMemberDescriptor descriptor) {
750                            return descriptor;
751                        }
752                    },
753                    new Function1<CallableMemberDescriptor, Unit>() {
754                        @Override
755                        public Unit invoke(CallableMemberDescriptor descriptor) {
756                            strategy.inheritanceConflict(overrider, descriptor);
757                            return Unit.INSTANCE;
758                        }
759                    });
760        }
761    
762    
763        public static void resolveUnknownVisibilityForMember(
764                @NotNull CallableMemberDescriptor memberDescriptor,
765                @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility
766        ) {
767            for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
768                if (descriptor.getVisibility() == Visibilities.INHERITED) {
769                    resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility);
770                }
771            }
772    
773            if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
774                return;
775            }
776    
777            Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor);
778            Visibility visibilityToInherit;
779            if (maxVisibility == null) {
780                if (cannotInferVisibility != null) {
781                    cannotInferVisibility.invoke(memberDescriptor);
782                }
783                visibilityToInherit = Visibilities.PUBLIC;
784            }
785            else {
786                visibilityToInherit = maxVisibility;
787            }
788    
789            if (memberDescriptor instanceof PropertyDescriptorImpl) {
790                ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
791                for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
792                    // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors
793                    resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility);
794                }
795            }
796            else if (memberDescriptor instanceof FunctionDescriptorImpl) {
797                ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
798            }
799            else {
800                assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
801                ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
802            }
803        }
804    
805        @Nullable
806        private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) {
807            Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
808            Visibility maxVisibility = findMaxVisibility(overriddenDescriptors);
809            if (maxVisibility == null) {
810                return null;
811            }
812            if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
813                for (CallableMemberDescriptor overridden : overriddenDescriptors) {
814                    // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility
815                    if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) {
816                        return null;
817                    }
818                }
819                return maxVisibility;
820            }
821            return maxVisibility.normalize();
822        }
823    
824        @Nullable
825        public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
826            if (descriptors.isEmpty()) {
827                return Visibilities.DEFAULT_VISIBILITY;
828            }
829            Visibility maxVisibility = null;
830            for (CallableMemberDescriptor descriptor : descriptors) {
831                Visibility visibility = descriptor.getVisibility();
832                assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor;
833                if (maxVisibility == null) {
834                    maxVisibility = visibility;
835                    continue;
836                }
837                Integer compareResult = Visibilities.compare(visibility, maxVisibility);
838                if (compareResult == null) {
839                    maxVisibility = null;
840                }
841                else if (compareResult > 0) {
842                    maxVisibility = visibility;
843                }
844            }
845            if (maxVisibility == null) {
846                return null;
847            }
848            for (CallableMemberDescriptor descriptor : descriptors) {
849                Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
850                if (compareResult == null || compareResult < 0) {
851                    return null;
852                }
853            }
854            return maxVisibility;
855        }
856    
857        public static class OverrideCompatibilityInfo {
858            public enum Result {
859                OVERRIDABLE,
860                INCOMPATIBLE,
861                CONFLICT,
862            }
863    
864            private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(OVERRIDABLE, "SUCCESS");
865    
866            @NotNull
867            public static OverrideCompatibilityInfo success() {
868                return SUCCESS;
869            }
870    
871            @NotNull
872            public static OverrideCompatibilityInfo incompatible(@NotNull String debugMessage) {
873                return new OverrideCompatibilityInfo(INCOMPATIBLE, debugMessage);
874            }
875    
876            @NotNull
877            public static OverrideCompatibilityInfo conflict(@NotNull String debugMessage) {
878                return new OverrideCompatibilityInfo(CONFLICT, debugMessage);
879            }
880    
881            private final Result overridable;
882            private final String debugMessage;
883    
884            public OverrideCompatibilityInfo(@NotNull Result success, @NotNull String debugMessage) {
885                this.overridable = success;
886                this.debugMessage = debugMessage;
887            }
888    
889            @NotNull
890            public Result getResult() {
891                return overridable;
892            }
893    
894            @NotNull
895            public String getDebugMessage() {
896                return debugMessage;
897            }
898        }
899    }