001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.resolve;
018
019 import kotlin.CollectionsKt;
020 import kotlin.Unit;
021 import kotlin.jvm.functions.Function1;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.kotlin.descriptors.*;
025 import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
026 import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
027 import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
028 import org.jetbrains.kotlin.name.Name;
029 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
030 import org.jetbrains.kotlin.types.KotlinType;
031 import org.jetbrains.kotlin.types.TypeConstructor;
032 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
033
034 import java.util.*;
035
036 import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*;
037
038 public class OverridingUtil {
039
040 private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
041 CollectionsKt.toList(ServiceLoader.load(
042 ExternalOverridabilityCondition.class,
043 ExternalOverridabilityCondition.class.getClassLoader()
044 ));
045
046 public static final OverridingUtil DEFAULT = new OverridingUtil(new KotlinTypeChecker.TypeConstructorEquality() {
047 @Override
048 public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
049 return a.equals(b);
050 }
051 });
052
053 @NotNull
054 public static OverridingUtil createWithEqualityAxioms(@NotNull KotlinTypeChecker.TypeConstructorEquality equalityAxioms) {
055 return new OverridingUtil(equalityAxioms);
056 }
057
058 private final KotlinTypeChecker.TypeConstructorEquality equalityAxioms;
059
060 private OverridingUtil(KotlinTypeChecker.TypeConstructorEquality axioms) {
061 equalityAxioms = axioms;
062 }
063
064 @NotNull
065 public OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
066 return isOverridableBy(superDescriptor, subDescriptor, false);
067 }
068
069 @NotNull
070 public OverrideCompatibilityInfo isOverridableByIncludingReturnType(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
071 return isOverridableBy(superDescriptor, subDescriptor, true);
072 }
073
074 @NotNull
075 private OverrideCompatibilityInfo isOverridableBy(
076 @NotNull CallableDescriptor superDescriptor,
077 @NotNull CallableDescriptor subDescriptor,
078 boolean checkReturnType
079 ) {
080 if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) ||
081 superDescriptor instanceof PropertyDescriptor && !(subDescriptor instanceof PropertyDescriptor)) {
082 return OverrideCompatibilityInfo.incompatible("Member kind mismatch");
083 }
084
085 if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof PropertyDescriptor)) {
086 throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
087 }
088
089 // TODO: check outside of this method
090 if (!superDescriptor.getName().equals(subDescriptor.getName())) {
091 return OverrideCompatibilityInfo.incompatible("Name mismatch");
092 }
093
094 OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor);
095 if (receiverAndParameterResult != null) {
096 return receiverAndParameterResult;
097 }
098
099 List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
100 List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);
101
102 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
103 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
104
105 if (superTypeParameters.size() != subTypeParameters.size()) {
106 for (int i = 0; i < superValueParameters.size(); ++i) {
107 // TODO: compare erasure
108 if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameters.get(i), subValueParameters.get(i))) {
109 return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
110 }
111 }
112 return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
113 }
114
115 KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters);
116
117 for (int i = 0; i < superTypeParameters.size(); i++) {
118 if (!areTypeParametersEquivalent(superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) {
119 return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
120 }
121 }
122
123 for (int i = 0; i < superValueParameters.size(); i++) {
124 if (!areTypesEquivalent(superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
125 return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
126 }
127 }
128
129 if (checkReturnType) {
130 KotlinType superReturnType = superDescriptor.getReturnType();
131 KotlinType subReturnType = subDescriptor.getReturnType();
132
133 if (superReturnType != null && subReturnType != null) {
134 boolean bothErrors = subReturnType.isError() && superReturnType.isError();
135 if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) {
136 return OverrideCompatibilityInfo.conflict("Return type mismatch");
137 }
138 }
139 }
140
141 for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
142 if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) {
143 return OverrideCompatibilityInfo.incompatible("External condition failed");
144 }
145 }
146
147 return OverrideCompatibilityInfo.success();
148 }
149
150 @NotNull
151 private KotlinTypeChecker createTypeChecker(
152 @NotNull List<TypeParameterDescriptor> firstParameters,
153 @NotNull List<TypeParameterDescriptor> secondParameters
154 ) {
155 assert firstParameters.size() == secondParameters.size() :
156 "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;
157 if (firstParameters.isEmpty()) return KotlinTypeChecker.withAxioms(equalityAxioms);
158
159 final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
160 for (int i = 0; i < firstParameters.size(); i++) {
161 matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
162 }
163
164 return KotlinTypeChecker.withAxioms(new KotlinTypeChecker.TypeConstructorEquality() {
165 @Override
166 public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
167 if (equalityAxioms.equals(a, b)) return true;
168 TypeConstructor img1 = matchingTypeConstructors.get(a);
169 TypeConstructor img2 = matchingTypeConstructors.get(b);
170 return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a));
171 }
172 });
173 }
174
175 @Nullable
176 static OverrideCompatibilityInfo checkReceiverAndParameterCount(
177 CallableDescriptor superDescriptor,
178 CallableDescriptor subDescriptor
179 ) {
180 if ((superDescriptor.getExtensionReceiverParameter() == null) != (subDescriptor.getExtensionReceiverParameter() == null)) {
181 return OverrideCompatibilityInfo.incompatible("Receiver presence mismatch");
182 }
183
184 if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
185 return OverrideCompatibilityInfo.incompatible("Value parameter number mismatch");
186 }
187
188 return null;
189 }
190
191 private static boolean areTypesEquivalent(
192 @NotNull KotlinType typeInSuper,
193 @NotNull KotlinType typeInSub,
194 @NotNull KotlinTypeChecker typeChecker
195 ) {
196 boolean bothErrors = typeInSuper.isError() && typeInSub.isError();
197 return bothErrors || typeChecker.equalTypes(typeInSuper, typeInSub);
198 }
199
200 // See JLS 8, 8.4.4 Generic Methods
201 // TODO: use TypeSubstitutor instead
202 private static boolean areTypeParametersEquivalent(
203 @NotNull TypeParameterDescriptor superTypeParameter,
204 @NotNull TypeParameterDescriptor subTypeParameter,
205 @NotNull KotlinTypeChecker typeChecker
206 ) {
207 List<KotlinType> superBounds = superTypeParameter.getUpperBounds();
208 List<KotlinType> subBounds = new ArrayList<KotlinType>(subTypeParameter.getUpperBounds());
209 if (superBounds.size() != subBounds.size()) return false;
210
211 outer:
212 for (KotlinType superBound : superBounds) {
213 ListIterator<KotlinType> it = subBounds.listIterator();
214 while (it.hasNext()) {
215 KotlinType subBound = it.next();
216 if (areTypesEquivalent(superBound, subBound, typeChecker)) {
217 it.remove();
218 continue outer;
219 }
220 }
221 return false;
222 }
223
224 return true;
225 }
226
227 static List<KotlinType> compiledValueParameters(CallableDescriptor callableDescriptor) {
228 ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
229 List<KotlinType> parameters = new ArrayList<KotlinType>();
230 if (receiverParameter != null) {
231 parameters.add(receiverParameter.getType());
232 }
233 for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
234 parameters.add(valueParameterDescriptor.getType());
235 }
236 return parameters;
237 }
238
239 public static void generateOverridesInFunctionGroup(
240 @SuppressWarnings("UnusedParameters")
241 @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
242 @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
243 @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
244 @NotNull ClassDescriptor current,
245 @NotNull DescriptorSink sink
246 ) {
247 Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes);
248
249 for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
250 Collection<CallableMemberDescriptor> bound =
251 extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
252 notOverridden.removeAll(bound);
253 }
254
255 createAndBindFakeOverrides(current, notOverridden, sink);
256 }
257
258 private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
259 @NotNull CallableMemberDescriptor fromCurrent,
260 @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
261 @NotNull ClassDescriptor current,
262 @NotNull DescriptorSink sink
263 ) {
264 Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size());
265 for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
266 OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult();
267
268 boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current);
269 switch (result) {
270 case OVERRIDABLE:
271 if (isVisible) {
272 fromCurrent.addOverriddenDescriptor(fromSupertype);
273 }
274 bound.add(fromSupertype);
275 break;
276 case CONFLICT:
277 if (isVisible) {
278 sink.conflict(fromSupertype, fromCurrent);
279 }
280 bound.add(fromSupertype);
281 break;
282 case INCOMPATIBLE:
283 break;
284 }
285 }
286 return bound;
287 }
288
289 private static void createAndBindFakeOverrides(
290 @NotNull ClassDescriptor current,
291 @NotNull Collection<CallableMemberDescriptor> notOverridden,
292 @NotNull DescriptorSink sink
293 ) {
294 Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
295 while (!fromSuperQueue.isEmpty()) {
296 CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue);
297 Collection<CallableMemberDescriptor> overridables =
298 extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink);
299 createAndBindFakeOverride(overridables, current, sink);
300 }
301 }
302
303 private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
304 if (a instanceof SimpleFunctionDescriptor) {
305 assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
306
307 KotlinType aReturnType = a.getReturnType();
308 assert aReturnType != null;
309 KotlinType bReturnType = b.getReturnType();
310 assert bReturnType != null;
311
312 return KotlinTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType);
313 }
314 if (a instanceof PropertyDescriptor) {
315 assert b instanceof PropertyDescriptor : "b is " + b.getClass();
316
317 if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
318 return ((PropertyDescriptor) a).isVar();
319 }
320
321 // both vals
322 return KotlinTypeChecker.DEFAULT.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
323 }
324 throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
325 }
326
327 private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
328 CallableMemberDescriptor result = null;
329 for (CallableMemberDescriptor overridable : overridables) {
330 if (result == null || isMoreSpecific(overridable, result)) {
331 result = overridable;
332 }
333 }
334 return result;
335 }
336
337 private static void createAndBindFakeOverride(
338 @NotNull Collection<CallableMemberDescriptor> overridables,
339 @NotNull ClassDescriptor current,
340 @NotNull DescriptorSink sink
341 ) {
342 Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
343 boolean allInvisible = visibleOverridables.isEmpty();
344 Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
345
346 Modality modality = getMinimalModality(effectiveOverridden);
347 Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
348 CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
349 CallableMemberDescriptor fakeOverride =
350 mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
351 for (CallableMemberDescriptor descriptor : effectiveOverridden) {
352 fakeOverride.addOverriddenDescriptor(descriptor);
353 }
354 sink.addFakeOverride(fakeOverride);
355 }
356
357 @NotNull
358 private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
359 Modality modality = Modality.ABSTRACT;
360 for (CallableMemberDescriptor descriptor : descriptors) {
361 if (descriptor.getModality().compareTo(modality) < 0) {
362 modality = descriptor.getModality();
363 }
364 }
365 return modality;
366 }
367
368 @NotNull
369 private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
370 @NotNull final ClassDescriptor current,
371 @NotNull Collection<CallableMemberDescriptor> toFilter
372 ) {
373 return CollectionsKt.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() {
374 @Override
375 public Boolean invoke(CallableMemberDescriptor descriptor) {
376 //nested class could capture private member, so check for private visibility added
377 return !Visibilities.isPrivate(descriptor.getVisibility()) &&
378 Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, current);
379 }
380 });
381 }
382
383 @NotNull
384 private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
385 @NotNull CallableMemberDescriptor overrider,
386 @NotNull Queue<CallableMemberDescriptor> extractFrom,
387 @NotNull DescriptorSink sink
388 ) {
389 Collection<CallableMemberDescriptor> overridable = new ArrayList<CallableMemberDescriptor>();
390 overridable.add(overrider);
391 for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
392 CallableMemberDescriptor candidate = iterator.next();
393 if (overrider == candidate) {
394 iterator.remove();
395 continue;
396 }
397
398 OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidate, overrider).getResult();
399 OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overrider, candidate).getResult();
400 if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) {
401 overridable.add(candidate);
402 iterator.remove();
403 }
404 else if (result1 == CONFLICT || result2 == CONFLICT) {
405 sink.conflict(overrider, candidate);
406 iterator.remove();
407 }
408 }
409 return overridable;
410 }
411
412 public static void resolveUnknownVisibilityForMember(
413 @NotNull CallableMemberDescriptor memberDescriptor,
414 @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility
415 ) {
416 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
417 if (descriptor.getVisibility() == Visibilities.INHERITED) {
418 resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility);
419 }
420 }
421
422 if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
423 return;
424 }
425
426 Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor);
427 Visibility visibilityToInherit;
428 if (maxVisibility == null) {
429 if (cannotInferVisibility != null) {
430 cannotInferVisibility.invoke(memberDescriptor);
431 }
432 visibilityToInherit = Visibilities.PUBLIC;
433 }
434 else {
435 visibilityToInherit = maxVisibility;
436 }
437
438 if (memberDescriptor instanceof PropertyDescriptorImpl) {
439 ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
440 for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
441 // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors
442 resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility);
443 }
444 }
445 else if (memberDescriptor instanceof FunctionDescriptorImpl) {
446 ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
447 }
448 else {
449 assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
450 ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
451 }
452 }
453
454 @Nullable
455 private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) {
456 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
457 Visibility maxVisibility = findMaxVisibility(overriddenDescriptors);
458 if (maxVisibility == null) {
459 return null;
460 }
461 if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
462 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
463 // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility
464 if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) {
465 return null;
466 }
467 }
468 return maxVisibility;
469 }
470 return maxVisibility.normalize();
471 }
472
473 @Nullable
474 public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
475 if (descriptors.isEmpty()) {
476 return Visibilities.DEFAULT_VISIBILITY;
477 }
478 Visibility maxVisibility = null;
479 for (CallableMemberDescriptor descriptor : descriptors) {
480 Visibility visibility = descriptor.getVisibility();
481 assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor;
482 if (maxVisibility == null) {
483 maxVisibility = visibility;
484 continue;
485 }
486 Integer compareResult = Visibilities.compare(visibility, maxVisibility);
487 if (compareResult == null) {
488 maxVisibility = null;
489 }
490 else if (compareResult > 0) {
491 maxVisibility = visibility;
492 }
493 }
494 if (maxVisibility == null) {
495 return null;
496 }
497 for (CallableMemberDescriptor descriptor : descriptors) {
498 Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
499 if (compareResult == null || compareResult < 0) {
500 return null;
501 }
502 }
503 return maxVisibility;
504 }
505
506 public interface DescriptorSink {
507 void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride);
508
509 void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent);
510 }
511
512 public static class OverrideCompatibilityInfo {
513 public enum Result {
514 OVERRIDABLE,
515 INCOMPATIBLE,
516 CONFLICT,
517 }
518
519 private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(OVERRIDABLE, "SUCCESS");
520
521 @NotNull
522 public static OverrideCompatibilityInfo success() {
523 return SUCCESS;
524 }
525
526 @NotNull
527 public static OverrideCompatibilityInfo incompatible(@NotNull String debugMessage) {
528 return new OverrideCompatibilityInfo(INCOMPATIBLE, debugMessage);
529 }
530
531 @NotNull
532 public static OverrideCompatibilityInfo conflict(@NotNull String debugMessage) {
533 return new OverrideCompatibilityInfo(CONFLICT, debugMessage);
534 }
535
536 private final Result overridable;
537 private final String debugMessage;
538
539 public OverrideCompatibilityInfo(@NotNull Result success, @NotNull String debugMessage) {
540 this.overridable = success;
541 this.debugMessage = debugMessage;
542 }
543
544 @NotNull
545 public Result getResult() {
546 return overridable;
547 }
548
549 @NotNull
550 public String getDebugMessage() {
551 return debugMessage;
552 }
553 }
554 }