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 com.google.common.collect.Maps;
020    import com.google.common.collect.Sets;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.util.SmartList;
023    import com.intellij.util.containers.ContainerUtil;
024    import com.intellij.util.containers.SmartHashSet;
025    import kotlin.Unit;
026    import kotlin.collections.CollectionsKt;
027    import kotlin.jvm.functions.Function1;
028    import org.jetbrains.annotations.NotNull;
029    import org.jetbrains.annotations.Nullable;
030    import org.jetbrains.kotlin.descriptors.*;
031    import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
032    import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement;
033    import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
034    import org.jetbrains.kotlin.lexer.KtTokens;
035    import org.jetbrains.kotlin.psi.*;
036    import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
037    import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsKt;
038    import org.jetbrains.kotlin.types.*;
039    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
040    
041    import java.util.*;
042    
043    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION;
044    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
045    import static org.jetbrains.kotlin.diagnostics.Errors.*;
046    import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers;
047    import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
048    
049    public class OverrideResolver {
050        private final BindingTrace trace;
051    
052        public OverrideResolver(@NotNull BindingTrace trace) {
053            this.trace = trace;
054        }
055    
056        public void check(@NotNull TopDownAnalysisContext c) {
057            checkVisibility(c);
058            checkOverrides(c);
059            checkParameterOverridesForAllClasses(c);
060        }
061    
062        public static void resolveUnknownVisibilities(
063                @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
064                @NotNull BindingTrace trace
065        ) {
066            for (CallableMemberDescriptor descriptor : descriptors) {
067                OverridingUtil.resolveUnknownVisibilityForMember(descriptor, createCannotInferVisibilityReporter(trace));
068            }
069        }
070    
071        @NotNull
072        public static Function1<CallableMemberDescriptor, Unit> createCannotInferVisibilityReporter(@NotNull final BindingTrace trace) {
073            return new Function1<CallableMemberDescriptor, Unit>() {
074                @Override
075                public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
076                    DeclarationDescriptor reportOn;
077                    if (descriptor.getKind() == FAKE_OVERRIDE || descriptor.getKind() == DELEGATION) {
078                        reportOn = DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class);
079                    }
080                    else if (descriptor instanceof PropertyAccessorDescriptor && ((PropertyAccessorDescriptor) descriptor).isDefault()) {
081                        reportOn = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
082                    }
083                    else {
084                        reportOn = descriptor;
085                    }
086                    //noinspection ConstantConditions
087                    PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(reportOn);
088                    if (element instanceof KtDeclaration) {
089                        trace.report(CANNOT_INFER_VISIBILITY.on((KtDeclaration) element, descriptor));
090                    }
091                    return Unit.INSTANCE;
092                }
093            };
094        }
095    
096    
097        private void checkOverrides(@NotNull TopDownAnalysisContext c) {
098            for (Map.Entry<KtClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
099                checkOverridesInAClass(entry.getValue(), entry.getKey());
100            }
101        }
102    
103        private void checkOverridesInAClass(@NotNull ClassDescriptorWithResolutionScopes classDescriptor, @NotNull KtClassOrObject klass) {
104            // Check overrides for internal consistency
105            for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
106                checkOverrideForMember(member);
107            }
108    
109            CollectErrorInformationForInheritedMembersStrategy inheritedMemberErrors =
110                    new CollectErrorInformationForInheritedMembersStrategy(klass, classDescriptor);
111    
112            checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors);
113            inheritedMemberErrors.doReportErrors();
114        }
115    
116        @NotNull
117        public static Set<CallableMemberDescriptor> getMissingImplementations(@NotNull ClassDescriptor classDescriptor) {
118            CollectMissingImplementationsStrategy collector = new CollectMissingImplementationsStrategy();
119            checkInheritedAndDelegatedSignatures(classDescriptor, collector, null);
120            return collector.shouldImplement;
121        }
122    
123        private interface CheckInheritedSignaturesReportStrategy {
124            void abstractMemberNotImplemented(CallableMemberDescriptor descriptor);
125            void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor);
126            void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor);
127            void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor);
128            void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2);
129            void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2);
130        }
131    
132        private static class CollectMissingImplementationsStrategy implements CheckInheritedSignaturesReportStrategy {
133            private final Set<CallableMemberDescriptor> shouldImplement = new LinkedHashSet<CallableMemberDescriptor>();
134    
135            @Override
136            public void abstractMemberNotImplemented(CallableMemberDescriptor descriptor) {
137                shouldImplement.add(descriptor);
138            }
139    
140            @Override
141            public void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor) {
142                // don't care
143            }
144    
145            @Override
146            public void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor) {
147                shouldImplement.add(descriptor);
148            }
149    
150            @Override
151            public void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor) {
152                if (descriptor.getModality() == Modality.ABSTRACT) {
153                    shouldImplement.add(descriptor);
154                }
155            }
156    
157            @Override
158            public void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2) {
159                // don't care
160            }
161    
162            @Override
163            public void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2) {
164                // don't care
165            }
166        }
167    
168        private class CollectErrorInformationForInheritedMembersStrategy
169                implements CheckInheritedSignaturesReportStrategy, CheckOverrideReportStrategy {
170            private final KtClassOrObject klass;
171            private final ClassDescriptor classDescriptor;
172    
173            private final Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
174            private final Set<CallableMemberDescriptor> multipleImplementations = Sets.newLinkedHashSet();
175            private final Set<CallableMemberDescriptor> abstractInBaseClassNoImpl = Sets.newLinkedHashSet();
176            private final Set<CallableMemberDescriptor> conflictingInterfaceMembers = Sets.newLinkedHashSet();
177            private final Set<CallableMemberDescriptor> conflictingReturnTypes = Sets.newHashSet();
178    
179            private final Set<DiagnosticFactoryWithPsiElement> onceErrorsReported = new SmartHashSet<DiagnosticFactoryWithPsiElement>();
180    
181            public CollectErrorInformationForInheritedMembersStrategy(
182                    @NotNull KtClassOrObject klass,
183                    @NotNull ClassDescriptor classDescriptor
184            ) {
185                this.klass = klass;
186                this.classDescriptor = classDescriptor;
187            }
188    
189            @Override
190            public void abstractMemberNotImplemented(CallableMemberDescriptor descriptor) {
191                abstractNoImpl.add(descriptor);
192            }
193    
194            @Override
195            public void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor) {
196                abstractInBaseClassNoImpl.add(descriptor);
197            }
198    
199            @Override
200            public void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor) {
201                multipleImplementations.add(descriptor);
202            }
203    
204            @Override
205            public void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor) {
206                conflictingInterfaceMembers.add(descriptor);
207            }
208    
209            @Override
210            public void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2) {
211                conflictingReturnTypes.add(descriptor1);
212                conflictingReturnTypes.add(descriptor2);
213    
214                reportInheritanceConflictIfRequired(RETURN_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
215            }
216    
217            @Override
218            public void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2) {
219                conflictingReturnTypes.add(descriptor1);
220                conflictingReturnTypes.add(descriptor2);
221    
222                if (descriptor1.isVar() || descriptor2.isVar()) {
223                    reportInheritanceConflictIfRequired(VAR_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
224                }
225                else {
226                    reportInheritanceConflictIfRequired(PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
227                }
228            }
229    
230            private void reportInheritanceConflictIfRequired(
231                    @NotNull DiagnosticFactory2<KtClassOrObject, CallableMemberDescriptor, CallableMemberDescriptor> diagnosticFactory,
232                    @NotNull CallableMemberDescriptor descriptor1,
233                    @NotNull CallableMemberDescriptor descriptor2
234            ) {
235                if (!onceErrorsReported.contains(diagnosticFactory)) {
236                    onceErrorsReported.add(diagnosticFactory);
237                    trace.report(diagnosticFactory.on(klass, descriptor1, descriptor2));
238                }
239            }
240    
241            @Override
242            public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
243                reportDelegationProblemIfRequired(OVERRIDING_FINAL_MEMBER_BY_DELEGATION, overriding, overridden);
244            }
245    
246            @Override
247            public void returnTypeMismatchOnOverride(
248                    @NotNull CallableMemberDescriptor overriding,
249                    @NotNull CallableMemberDescriptor overridden
250            ) {
251                // Always reported as RETURN_TYPE_MISMATCH_ON_INHERITANCE
252            }
253    
254            @Override
255            public void propertyTypeMismatchOnOverride(
256                    @NotNull PropertyDescriptor overriding,
257                    @NotNull PropertyDescriptor overridden
258            ) {
259                // Always reported as PROPERTY_TYPE_MISMATCH_ON_INHERITANCE
260            }
261    
262            @Override
263            public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
264                reportDelegationProblemIfRequired(VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, overriding, overridden);
265            }
266    
267            private void reportDelegationProblemIfRequired(
268                    @NotNull DiagnosticFactory2<KtClassOrObject, CallableMemberDescriptor, CallableMemberDescriptor> diagnosticFactory,
269                    @NotNull CallableMemberDescriptor delegate,
270                    @NotNull CallableMemberDescriptor overridden
271            ) {
272                assert delegate.getKind() == DELEGATION : "Delegate expected, got " + delegate + " of kind " + delegate.getKind();
273    
274                if (!onceErrorsReported.contains(diagnosticFactory)) {
275                    onceErrorsReported.add(diagnosticFactory);
276                    trace.report(diagnosticFactory.on(klass, delegate, overridden));
277                }
278            }
279    
280            @Override
281            public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
282                assert overriding.getKind() == DELEGATION : "Delegate expected, got " + overriding + " of kind " + overriding.getKind();
283                assert overriding.getKind() != DELEGATION : "Delegated member can't override an invisible member; " + invisibleOverridden;
284            }
285    
286            @Override
287            public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
288                assert overriding.getKind() == DELEGATION : "Delegate expected, got " + overriding + " of kind " + overriding.getKind();
289                assert overriding.getKind() != DELEGATION : "Delegated member can't override nothing; " + overriding;
290            }
291    
292            void doReportErrors() {
293                if (!classCanHaveAbstractMembers(classDescriptor)) {
294                    if (!abstractInBaseClassNoImpl.isEmpty()) {
295                        trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.iterator().next()));
296                    }
297                    else if (!abstractNoImpl.isEmpty()) {
298                        trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.iterator().next()));
299                    }
300                }
301    
302                conflictingInterfaceMembers.removeAll(conflictingReturnTypes);
303                multipleImplementations.removeAll(conflictingReturnTypes);
304                if (!conflictingInterfaceMembers.isEmpty()) {
305                    trace.report(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED.on(klass, klass, conflictingInterfaceMembers.iterator().next()));
306                }
307                else if (!multipleImplementations.isEmpty()) {
308                    trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, multipleImplementations.iterator().next()));
309                }
310            }
311        }
312    
313        private static void checkInheritedAndDelegatedSignatures(
314                @NotNull ClassDescriptor classDescriptor,
315                @NotNull CheckInheritedSignaturesReportStrategy inheritedReportStrategy,
316                @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
317        ) {
318            for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
319                if (member instanceof CallableMemberDescriptor) {
320                    checkInheritedAndDelegatedSignatures((CallableMemberDescriptor) member, inheritedReportStrategy, overrideReportStrategyForDelegates);
321                }
322            }
323        }
324    
325        private static void checkInheritedAndDelegatedSignatures(
326                @NotNull CallableMemberDescriptor descriptor,
327                @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy,
328                @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
329        ) {
330            CallableMemberDescriptor.Kind kind = descriptor.getKind();
331            if (kind != FAKE_OVERRIDE && kind != DELEGATION) return;
332            if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
333    
334            Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
335            assert !directOverridden.isEmpty() : kind + " " + descriptor.getName().asString() + " must override something";
336    
337            // collects map from the directly overridden descriptor to the set of declarations:
338            // -- if directly overridden is not fake, the set consists of one element: this directly overridden
339            // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
340            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
341    
342            List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
343            Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
344                    Sets.newLinkedHashSet(allOverriddenDeclarations));
345    
346            Set<CallableMemberDescriptor> relevantDirectlyOverridden =
347                    getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
348    
349            checkInheritedDescriptorsGroup(relevantDirectlyOverridden, descriptor, reportingStrategy);
350    
351            if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
352                checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates);
353            }
354    
355            if (kind != DELEGATION) {
356                checkMissingOverridesByJava8Restrictions(relevantDirectlyOverridden, reportingStrategy);
357            }
358    
359            List<CallableMemberDescriptor> implementations = collectImplementations(relevantDirectlyOverridden);
360    
361            int numImplementations = implementations.size();
362    
363            // The most common case: there's one implementation in the supertypes with the matching return type
364            if (numImplementations == 1 && isReturnTypeOkForOverride(descriptor, implementations.get(0))) return;
365    
366            List<CallableMemberDescriptor> abstractOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
367            List<CallableMemberDescriptor> concreteOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
368            filterNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractOverridden, concreteOverridden);
369    
370            if (numImplementations == 0) {
371                if (kind != DELEGATION) {
372                    for (CallableMemberDescriptor member : abstractOverridden) {
373                        reportingStrategy.abstractMemberNotImplemented(member);
374                    }
375                }
376            }
377            else if (numImplementations > 1) {
378                for (CallableMemberDescriptor member : concreteOverridden) {
379                    reportingStrategy.multipleImplementationsMemberNotImplemented(member);
380                }
381            }
382            else {
383                if (kind != DELEGATION) {
384                    List<CallableMemberDescriptor> membersWithMoreSpecificReturnType =
385                            collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementations.get(0));
386                    for (CallableMemberDescriptor member : membersWithMoreSpecificReturnType) {
387                        reportingStrategy.abstractMemberNotImplemented(member);
388                    }
389                }
390            }
391        }
392    
393        private static void checkMissingOverridesByJava8Restrictions(
394                @NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden,
395                @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
396        ) {
397            // Java 8:
398            // -- class should implement an abstract member of a super-class,
399            //    even if relevant default implementation is provided in one of the super-interfaces;
400            // -- inheriting multiple override equivalent methods from an interface is a conflict
401            //    regardless of 'default' vs 'abstract'.
402    
403            boolean overridesClassMember = false;
404            boolean overridesNonAbstractInterfaceMember = false;
405            CallableMemberDescriptor overridesAbstractInBaseClass = null;
406            List<CallableMemberDescriptor> overriddenInterfaceMembers = new SmartList<CallableMemberDescriptor>();
407            for (CallableMemberDescriptor overridden : relevantDirectlyOverridden) {
408                DeclarationDescriptor containingDeclaration = overridden.getContainingDeclaration();
409                if (containingDeclaration instanceof ClassDescriptor) {
410                    ClassDescriptor baseClassOrInterface = (ClassDescriptor) containingDeclaration;
411                    if (baseClassOrInterface.getKind() == ClassKind.CLASS) {
412                        overridesClassMember = true;
413                        if (overridden.getModality() == Modality.ABSTRACT) {
414                            overridesAbstractInBaseClass = overridden;
415                        }
416                    }
417                    else if (baseClassOrInterface.getKind() == ClassKind.INTERFACE) {
418                        overriddenInterfaceMembers.add(overridden);
419                        if (overridden.getModality() != Modality.ABSTRACT) {
420                            overridesNonAbstractInterfaceMember = true;
421                        }
422                    }
423                }
424            }
425    
426            if (overridesAbstractInBaseClass != null) {
427                reportingStrategy.abstractBaseClassMemberNotImplemented(overridesAbstractInBaseClass);
428            }
429            if (!overridesClassMember && overridesNonAbstractInterfaceMember && overriddenInterfaceMembers.size() > 1) {
430                for (CallableMemberDescriptor member : overriddenInterfaceMembers) {
431                    reportingStrategy.conflictingInterfaceMemberNotImplemented(member);
432                }
433            }
434        }
435    
436        @NotNull
437        private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
438            List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
439            for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
440                if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
441                    result.add(overriddenDescriptor);
442                }
443            }
444            return result;
445        }
446    
447        private static void filterNotSynthesizedDescriptorsByModality(
448                @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
449                @NotNull List<CallableMemberDescriptor> abstractOverridden,
450                @NotNull List<CallableMemberDescriptor> concreteOverridden
451        ) {
452            for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
453                if (!CallResolverUtilKt.isOrOverridesSynthesized(overridden)) {
454                    if (overridden.getModality() == Modality.ABSTRACT) {
455                        abstractOverridden.add(overridden);
456                    }
457                    else {
458                        concreteOverridden.add(overridden);
459                    }
460                }
461            }
462        }
463    
464        @NotNull
465        private static List<CallableMemberDescriptor> collectAbstractMethodsWithMoreSpecificReturnType(
466                @NotNull List<CallableMemberDescriptor> abstractOverridden,
467                @NotNull final CallableMemberDescriptor implementation
468        ) {
469            return CollectionsKt.filter(abstractOverridden, new Function1<CallableMemberDescriptor, Boolean>() {
470                @Override
471                public Boolean invoke(@NotNull CallableMemberDescriptor abstractMember) {
472                    return !isReturnTypeOkForOverride(abstractMember, implementation);
473                }
474            });
475        }
476    
477        @NotNull
478        private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
479                @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
480                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
481        ) {
482            /* Let the following class hierarchy is declared:
483    
484            trait A { fun foo() = 1 }
485            trait B : A
486            trait C : A
487            trait D : A { override fun foo() = 2 }
488            trait E : B, C, D {}
489    
490            Traits B and C have fake descriptors for function foo.
491            The map 'overriddenByParent' is:
492            { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
493            This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
494            that are overridden by this descriptor.
495    
496            The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
497            In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
498            So only 'foo in D' is relevant.
499    
500            Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
501            More precisely directly overridden descriptor is not relevant if:
502            - it's declaration set is a subset of declaration set for other directly overridden descriptor
503            ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
504            - each member of it's declaration set is overridden by a member of other declaration set
505            ('foo in C' is not relevant, because 'foo in A' is overridden by 'foo in D', so 'foo in A' is not appropriate non-fake declaration for 'foo')
506    
507            For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
508            is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
509            are overridden by some other function and corresponding directly overridden descriptor is not relevant.
510            */
511    
512            for (Iterator<Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>>> iterator =
513                         overriddenByParent.entrySet().iterator(); iterator.hasNext(); ) {
514                if (!isRelevant(iterator.next().getValue(), overriddenByParent.values(), allFilteredOverriddenDeclarations)) {
515                    iterator.remove();
516                }
517            }
518            return overriddenByParent.keySet();
519        }
520    
521        private static boolean isRelevant(
522                @NotNull Set<CallableMemberDescriptor> declarationSet,
523                @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
524                @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
525        ) {
526            for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
527                if (otherSet == declarationSet) continue;
528                if (otherSet.containsAll(declarationSet)) return false;
529                if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
530            }
531            return true;
532        }
533    
534        @NotNull
535        private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
536                @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
537        ) {
538            Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
539            for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
540                Set<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
541                Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(overriddenDeclarations);
542                overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
543            }
544            return overriddenDeclarationsByDirectParent;
545        }
546    
547        private interface CheckOverrideReportStrategy {
548            void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
549            void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
550            void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden);
551            void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
552            void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden);
553            void nothingToOverride(@NotNull CallableMemberDescriptor overriding);
554        }
555    
556        private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
557            if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
558                if (DataClassUtilsKt.isComponentLike(declared.getName())) {
559                    checkOverrideForComponentFunction(declared);
560                }
561                return;
562            }
563    
564            if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
565                return;
566            }
567    
568            final KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(declared);
569            if (member == null) {
570                throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
571            }
572    
573            KtModifierList modifierList = member.getModifierList();
574            boolean hasOverrideNode = modifierList != null && modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD);
575            Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
576    
577            if (hasOverrideNode) {
578                checkOverridesForMemberMarkedOverride(declared, true, new CheckOverrideReportStrategy() {
579                    private boolean finalOverriddenError = false;
580                    private boolean typeMismatchError = false;
581                    private boolean kindMismatchError = false;
582    
583                    @Override
584                    public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
585                        if (!finalOverriddenError) {
586                            finalOverriddenError = true;
587                            trace.report(OVERRIDING_FINAL_MEMBER.on(member, overridden, overridden.getContainingDeclaration()));
588                        }
589                    }
590    
591                    @Override
592                    public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
593                        if (!typeMismatchError) {
594                            typeMismatchError = true;
595                            trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
596                        }
597                    }
598    
599                    @Override
600                    public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
601                        if (!typeMismatchError) {
602                            typeMismatchError = true;
603                            if (overridden.isVar()) {
604                                trace.report(VAR_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
605                            }
606                            else {
607                                trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
608                            }
609                        }
610                    }
611    
612                    @Override
613                    public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
614                        if (!kindMismatchError) {
615                            kindMismatchError = true;
616                            trace.report(VAR_OVERRIDDEN_BY_VAL.on(member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
617                        }
618                    }
619    
620                    @Override
621                    public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
622                        trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden));
623                    }
624    
625                    @Override
626                    public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
627                        trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
628                    }
629                });
630            }
631            else if (!overriddenDescriptors.isEmpty()) {
632                CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
633                trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
634            }
635        }
636    
637        private static void checkInheritedDescriptorsGroup(
638                @NotNull Collection<CallableMemberDescriptor> inheritedDescriptors,
639                @NotNull CallableMemberDescriptor mostSpecific,
640                @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
641        ) {
642            if (inheritedDescriptors.size() > 1) {
643                PropertyDescriptor mostSpecificProperty = mostSpecific instanceof PropertyDescriptor ? (PropertyDescriptor) mostSpecific : null;
644    
645                for (CallableMemberDescriptor inheritedDescriptor : inheritedDescriptors) {
646                    if (mostSpecificProperty != null) {
647                        assert inheritedDescriptor instanceof PropertyDescriptor
648                                : inheritedDescriptor + " inherited from " + mostSpecificProperty + " is not a property";
649                        PropertyDescriptor inheritedPropertyDescriptor = (PropertyDescriptor) inheritedDescriptor;
650    
651                        if (!isPropertyTypeOkForOverride(inheritedPropertyDescriptor, mostSpecificProperty)) {
652                            reportingStrategy.propertyTypeMismatchOnInheritance(mostSpecificProperty, inheritedPropertyDescriptor);
653                        }
654                    }
655                    else if (!isReturnTypeOkForOverride(inheritedDescriptor, mostSpecific)) {
656                        reportingStrategy.returnTypeMismatchOnInheritance(mostSpecific, inheritedDescriptor);
657                    }
658                }
659            }
660        }
661    
662        private static void checkOverridesForMemberMarkedOverride(
663                @NotNull CallableMemberDescriptor declared,
664                boolean checkIfOverridesNothing,
665                @NotNull CheckOverrideReportStrategy reportError
666        ) {
667            Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
668    
669            checkOverridesForMember(declared, overriddenDescriptors, reportError);
670    
671            if (checkIfOverridesNothing && overriddenDescriptors.isEmpty()) {
672                DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
673                assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
674                ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
675    
676                CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
677                if (invisibleOverriddenDescriptor != null) {
678                    reportError.cannotOverrideInvisibleMember(declared, invisibleOverriddenDescriptor);
679                }
680                else {
681                    reportError.nothingToOverride(declared);
682                }
683            }
684        }
685    
686        private static void checkOverridesForMember(
687                @NotNull CallableMemberDescriptor memberDescriptor,
688                @NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors,
689                @NotNull CheckOverrideReportStrategy reportError
690        ) {
691            PropertyDescriptor propertyMemberDescriptor =
692                    memberDescriptor instanceof PropertyDescriptor ? (PropertyDescriptor) memberDescriptor : null;
693    
694            for (CallableMemberDescriptor overridden : overriddenDescriptors) {
695                if (overridden == null) continue;
696    
697                if (!ModalityKt.isOverridable(overridden)) {
698                    reportError.overridingFinalMember(memberDescriptor, overridden);
699                }
700    
701                if (propertyMemberDescriptor != null) {
702                    assert overridden instanceof PropertyDescriptor : overridden + " is overridden by property " + propertyMemberDescriptor;
703                    PropertyDescriptor overriddenProperty = (PropertyDescriptor) overridden;
704                    if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
705                        reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty);
706                    }
707                }
708                else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
709                    reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden);
710                }
711    
712                if (checkPropertyKind(overridden, true) && checkPropertyKind(memberDescriptor, false)) {
713                    reportError.varOverriddenByVal(memberDescriptor, overridden);
714                }
715            }
716        }
717    
718        private static boolean isReturnTypeOkForOverride(
719                @NotNull CallableDescriptor superDescriptor,
720                @NotNull CallableDescriptor subDescriptor
721        ) {
722            TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
723            if (typeSubstitutor == null) return false;
724    
725            KotlinType superReturnType = superDescriptor.getReturnType();
726            assert superReturnType != null;
727    
728            KotlinType subReturnType = subDescriptor.getReturnType();
729            assert subReturnType != null;
730    
731            KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
732            assert substitutedSuperReturnType != null;
733    
734            return KotlinTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
735        }
736    
737        @Nullable
738        private static TypeSubstitutor prepareTypeSubstitutor(
739                @NotNull CallableDescriptor superDescriptor,
740                @NotNull CallableDescriptor subDescriptor
741        ) {
742            List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
743            List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
744            if (subTypeParameters.size() != superTypeParameters.size()) return null;
745    
746            ArrayList<TypeProjection> arguments = new ArrayList<TypeProjection>(subTypeParameters.size());
747            for (int i = 0; i < superTypeParameters.size(); i++) {
748                arguments.add(new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType()));
749            }
750    
751            return new IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor();
752        }
753    
754        private static boolean isPropertyTypeOkForOverride(
755                @NotNull PropertyDescriptor superDescriptor,
756                @NotNull PropertyDescriptor subDescriptor
757        ) {
758            TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
759            if (typeSubstitutor == null) return false;
760    
761            KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
762            assert substitutedSuperReturnType != null;
763    
764            if (superDescriptor.isVar()) {
765                return KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
766            }
767            else {
768                return KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.getType(), substitutedSuperReturnType);
769            }
770        }
771    
772        private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
773            final PsiElement dataModifier = findDataModifierForDataClass(componentFunction.getContainingDeclaration());
774    
775            checkOverridesForMemberMarkedOverride(componentFunction, false, new CheckOverrideReportStrategy() {
776                private boolean overrideConflict = false;
777    
778                @Override
779                public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
780                    if (!overrideConflict) {
781                        overrideConflict = true;
782                        trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
783                    }
784                }
785    
786                @Override
787                public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
788                    if (!overrideConflict) {
789                        overrideConflict = true;
790                        trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
791                    }
792                }
793    
794                @Override
795                public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
796                    throw new IllegalStateException("Component functions are not properties");
797                }
798    
799                @Override
800                public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
801                    throw new IllegalStateException("Component functions are not properties");
802                }
803    
804                @Override
805                public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
806                    throw new IllegalStateException("CANNOT_OVERRIDE_INVISIBLE_MEMBER should be reported on the corresponding property");
807                }
808    
809                @Override
810                public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
811                    throw new IllegalStateException("Component functions are OK to override nothing");
812                }
813            });
814        }
815    
816        @NotNull
817        private static PsiElement findDataModifierForDataClass(@NotNull DeclarationDescriptor dataClass) {
818            KtClassOrObject classDeclaration = (KtClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(dataClass);
819            if (classDeclaration != null && classDeclaration.getModifierList() != null) {
820                PsiElement modifier = classDeclaration.getModifierList().getModifier(KtTokens.DATA_KEYWORD);
821                if (modifier != null) {
822                    return modifier;
823                }
824            }
825    
826            throw new IllegalStateException("No data modifier is found for data class " + dataClass);
827        }
828    
829        @Nullable
830        private static CallableMemberDescriptor findInvisibleOverriddenDescriptor(
831                @NotNull CallableMemberDescriptor declared,
832                @NotNull ClassDescriptor declaringClass
833        ) {
834            for (KotlinType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
835                Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
836                all.addAll(supertype.getMemberScope().getContributedFunctions(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
837                //noinspection unchecked
838                all.addAll((Collection) supertype.getMemberScope().getContributedVariables(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
839                for (CallableMemberDescriptor fromSuper : all) {
840                    if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).getResult() == OVERRIDABLE) {
841                        if (Visibilities.isVisibleIgnoringReceiver(fromSuper, declared)) {
842                            throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
843                                                            " and visible but does not appear in its getOverriddenDescriptors()");
844                        }
845                        return fromSuper;
846                    }
847                }
848            }
849            return null;
850        }
851    
852        private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
853            for (ClassDescriptorWithResolutionScopes classDescriptor : c.getDeclaredClasses().values()) {
854                for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
855                    if (member instanceof CallableMemberDescriptor) {
856                        checkOverridesForParameters((CallableMemberDescriptor) member);
857                    }
858                }
859            }
860        }
861    
862        private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
863            boolean isDeclaration = declared.getKind() == CallableMemberDescriptor.Kind.DECLARATION;
864            if (isDeclaration) {
865                // No check if the function is not marked as 'override'
866                KtModifierListOwner declaration = (KtModifierListOwner) DescriptorToSourceUtils.descriptorToDeclaration(declared);
867                if (declaration != null && !declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
868                    return;
869                }
870            }
871    
872            // Let p1 be a parameter of the overriding function
873            // Let p2 be a parameter of the function being overridden
874            // Then
875            //  a) p1 is not allowed to have a default value declared
876            //  b) p1 must have the same name as p2
877            for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
878                int defaultsInSuper = 0;
879                for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
880                    if (parameterFromSuperclass.declaresDefaultValue()) {
881                        defaultsInSuper++;
882                    }
883                }
884                boolean multipleDefaultsInSuper = defaultsInSuper > 1;
885    
886                if (isDeclaration) {
887                    checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper);
888                }
889                else {
890                    checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper);
891                }
892            }
893        }
894    
895        private void checkNameAndDefaultForDeclaredParameter(@NotNull ValueParameterDescriptor descriptor, boolean multipleDefaultsInSuper) {
896            KtParameter parameter = (KtParameter) DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
897            assert parameter != null : "Declaration not found for parameter: " + descriptor;
898    
899            if (descriptor.declaresDefaultValue()) {
900                trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
901            }
902    
903            if (multipleDefaultsInSuper) {
904                trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, descriptor));
905            }
906    
907            for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
908                if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
909                    //noinspection ConstantConditions
910                    trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
911                            parameter,
912                            (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(),
913                            parameterFromSuperclass)
914                    );
915                }
916            }
917        }
918    
919        private void checkNameAndDefaultForFakeOverrideParameter(
920                @NotNull CallableMemberDescriptor containingFunction,
921                @NotNull ValueParameterDescriptor descriptor,
922                boolean multipleDefaultsInSuper
923        ) {
924            DeclarationDescriptor containingClass = containingFunction.getContainingDeclaration();
925            KtClassOrObject classElement = (KtClassOrObject) DescriptorToSourceUtils.descriptorToDeclaration(containingClass);
926            assert classElement != null : "Declaration not found for class: " + containingClass;
927    
928            if (multipleDefaultsInSuper) {
929                trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor));
930            }
931    
932            for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
933                if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
934                    trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
935                            classElement,
936                            containingFunction.getOverriddenDescriptors(),
937                            parameterFromSuperclass.getIndex() + 1)
938                    );
939                }
940            }
941        }
942    
943        public static boolean shouldReportParameterNameOverrideWarning(
944                @NotNull ValueParameterDescriptor parameterFromSubclass,
945                @NotNull ValueParameterDescriptor parameterFromSuperclass
946        ) {
947            return parameterFromSubclass.getContainingDeclaration().hasStableParameterNames() &&
948                   parameterFromSuperclass.getContainingDeclaration().hasStableParameterNames() &&
949                   !parameterFromSuperclass.getName().equals(parameterFromSubclass.getName());
950        }
951    
952        private static boolean checkPropertyKind(@NotNull CallableMemberDescriptor descriptor, boolean isVar) {
953            return descriptor instanceof PropertyDescriptor && ((PropertyDescriptor) descriptor).isVar() == isVar;
954        }
955    
956        private void checkVisibility(@NotNull TopDownAnalysisContext c) {
957            for (Map.Entry<KtCallableDeclaration, CallableMemberDescriptor> entry : c.getMembers().entrySet()) {
958                checkVisibilityForMember(entry.getKey(), entry.getValue());
959                if (entry.getKey() instanceof KtProperty && entry.getValue() instanceof PropertyDescriptor) {
960                    KtPropertyAccessor setter = ((KtProperty) entry.getKey()).getSetter();
961                    PropertySetterDescriptor setterDescriptor = ((PropertyDescriptor) entry.getValue()).getSetter();
962                    if (setter != null && setterDescriptor != null) {
963                        checkVisibilityForMember(setter, setterDescriptor);
964                    }
965                }
966            }
967        }
968    
969        private void checkVisibilityForMember(@NotNull KtDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
970            Visibility visibility = memberDescriptor.getVisibility();
971            for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
972                Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
973                if (compare == null) {
974                    trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
975                    return;
976                }
977                else if (compare < 0) {
978                    trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
979                    return;
980                }
981            }
982        }
983    }