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 }