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