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.jvm.kotlinSignature;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Multimap;
021 import com.google.common.collect.Sets;
022 import com.intellij.util.Function;
023 import com.intellij.util.containers.ContainerUtil;
024 import kotlin.KotlinPackage;
025 import kotlin.jvm.functions.Function1;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
029 import org.jetbrains.kotlin.descriptors.*;
030 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
031 import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
032 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
033 import org.jetbrains.kotlin.load.java.components.TypeUsage;
034 import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
035 import org.jetbrains.kotlin.load.java.structure.JavaMethod;
036 import org.jetbrains.kotlin.name.FqNameUnsafe;
037 import org.jetbrains.kotlin.name.Name;
038 import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
039 import org.jetbrains.kotlin.renderer.DescriptorRenderer;
040 import org.jetbrains.kotlin.resolve.DescriptorUtils;
041 import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
042 import org.jetbrains.kotlin.resolve.jvm.JvmPackage;
043 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
044 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmSignaturePackage;
045 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper;
046 import org.jetbrains.kotlin.resolve.scopes.JetScope;
047 import org.jetbrains.kotlin.types.*;
048
049 import java.util.*;
050
051 import static org.jetbrains.kotlin.load.java.components.TypeUsage.*;
052 import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
053 import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
054 import static org.jetbrains.kotlin.types.Variance.INVARIANT;
055
056 public class SignaturesPropagationData {
057
058 private static final KotlinToJvmSignatureMapper SIGNATURE_MAPPER = ServiceLoader.load(
059 KotlinToJvmSignatureMapper.class,
060 KotlinToJvmSignatureMapper.class.getClassLoader()
061 ).iterator().next();
062
063 private final JavaMethodDescriptor autoMethodDescriptor;
064
065 private final List<TypeParameterDescriptor> modifiedTypeParameters;
066 private final ValueParameters modifiedValueParameters;
067
068 private final JetType modifiedReturnType;
069 private final List<String> signatureErrors = Lists.newArrayList();
070 private final List<FunctionDescriptor> superFunctions;
071 private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> autoTypeParameterToModified;
072 final ClassDescriptor containingClass;
073
074 public SignaturesPropagationData(
075 @NotNull ClassDescriptor containingClass,
076 @NotNull JetType autoReturnType, // type built by JavaTypeTransformer from Java signature and @NotNull annotations
077 @Nullable JetType receiverType,
078 @NotNull List<ValueParameterDescriptor> autoValueParameters, // descriptors built by parameters resolver
079 @NotNull List<TypeParameterDescriptor> autoTypeParameters, // descriptors built by signature resolver
080 @NotNull JavaMethod method
081 ) {
082 this.containingClass = containingClass;
083
084 autoMethodDescriptor =
085 createAutoMethodDescriptor(containingClass, method, autoReturnType, receiverType, autoValueParameters, autoTypeParameters);
086
087 superFunctions = getSuperFunctionsForMethod(method, autoMethodDescriptor, containingClass);
088
089 autoTypeParameterToModified = JavaResolverUtils.recreateTypeParametersAndReturnMapping(autoTypeParameters, null);
090
091 modifiedTypeParameters = modifyTypeParametersAccordingToSuperMethods(autoTypeParameters);
092 modifiedReturnType = modifyReturnTypeAccordingToSuperMethods(autoReturnType);
093 modifiedValueParameters = modifyValueParametersAccordingToSuperMethods(receiverType, autoValueParameters);
094 }
095
096 @NotNull
097 private static JavaMethodDescriptor createAutoMethodDescriptor(
098 @NotNull ClassDescriptor containingClass,
099 @NotNull JavaMethod method, JetType autoReturnType,
100 @Nullable JetType receiverType,
101 @NotNull List<ValueParameterDescriptor> autoValueParameters,
102 @NotNull List<TypeParameterDescriptor> autoTypeParameters
103 ) {
104 JavaMethodDescriptor autoMethodDescriptor = JavaMethodDescriptor.createJavaMethod(
105 containingClass,
106 Annotations.EMPTY,
107 method.getName(),
108 //TODO: what to do?
109 SourceElement.NO_SOURCE
110 );
111 autoMethodDescriptor.initialize(
112 receiverType,
113 containingClass.getThisAsReceiverParameter(),
114 autoTypeParameters,
115 autoValueParameters,
116 autoReturnType,
117 Modality.OPEN,
118 Visibilities.PUBLIC
119 );
120 return autoMethodDescriptor;
121 }
122
123 public List<TypeParameterDescriptor> getModifiedTypeParameters() {
124 return modifiedTypeParameters;
125 }
126
127 public JetType getModifiedReceiverType() {
128 return modifiedValueParameters.receiverType;
129 }
130
131 public List<ValueParameterDescriptor> getModifiedValueParameters() {
132 return modifiedValueParameters.descriptors;
133 }
134
135 public boolean getModifiedHasStableParameterNames() {
136 return modifiedValueParameters.hasStableParameterNames;
137 }
138
139 public JetType getModifiedReturnType() {
140 return modifiedReturnType;
141 }
142
143 public List<String> getSignatureErrors() {
144 return signatureErrors;
145 }
146
147 public List<FunctionDescriptor> getSuperFunctions() {
148 return superFunctions;
149 }
150
151 void reportError(String error) {
152 signatureErrors.add(error);
153 }
154
155 private JetType modifyReturnTypeAccordingToSuperMethods(
156 @NotNull JetType autoType // type built by JavaTypeTransformer
157 ) {
158 if (JvmPackage.getPLATFORM_TYPES()) return autoType;
159
160 List<TypeAndVariance> typesFromSuperMethods = ContainerUtil.map(superFunctions,
161 new Function<FunctionDescriptor, TypeAndVariance>() {
162 @Override
163 public TypeAndVariance fun(FunctionDescriptor superFunction) {
164 return new TypeAndVariance(superFunction.getReturnType(), Variance.OUT_VARIANCE);
165 }
166 });
167
168 return modifyTypeAccordingToSuperMethods(autoType, typesFromSuperMethods, MEMBER_SIGNATURE_COVARIANT);
169 }
170
171 private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods(List<TypeParameterDescriptor> autoTypeParameters) {
172 if (JvmPackage.getPLATFORM_TYPES()) return autoTypeParameters;
173
174 List<TypeParameterDescriptor> result = Lists.newArrayList();
175
176 for (TypeParameterDescriptor autoParameter : autoTypeParameters) {
177 int index = autoParameter.getIndex();
178 TypeParameterDescriptorImpl modifiedTypeParameter = autoTypeParameterToModified.get(autoParameter);
179
180 List<Iterator<JetType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList();
181 for (FunctionDescriptor superFunction : superFunctions) {
182 upperBoundFromSuperFunctionsIterators.add(superFunction.getTypeParameters().get(index).getUpperBounds().iterator());
183 }
184
185 for (JetType autoUpperBound : autoParameter.getUpperBounds()) {
186 List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList();
187
188 for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
189 assert iterator.hasNext();
190 upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT));
191 }
192
193 JetType modifiedUpperBound = modifyTypeAccordingToSuperMethods(autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND);
194 modifiedTypeParameter.addUpperBound(modifiedUpperBound);
195 }
196
197 for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
198 assert !iterator.hasNext();
199 }
200
201 modifiedTypeParameter.setInitialized();
202 result.add(modifiedTypeParameter);
203 }
204
205 return result;
206 }
207
208 private ValueParameters modifyValueParametersAccordingToSuperMethods(
209 @Nullable JetType receiverType,
210 @NotNull List<ValueParameterDescriptor> parameters // descriptors built by parameters resolver
211 ) {
212 assert receiverType == null : "Parameters before propagation have receiver type," +
213 " but propagation should be disabled for functions compiled from Kotlin in class: " +
214 DescriptorUtils.getFqName(containingClass);
215
216 JetType resultReceiverType = null;
217 List<ValueParameterDescriptor> resultParameters = Lists.newArrayList();
218
219 boolean shouldBeExtension = checkIfShouldBeExtension();
220
221 for (final ValueParameterDescriptor originalParam : parameters) {
222 final int originalIndex = originalParam.getIndex();
223 List<TypeAndName> typesFromSuperMethods = ContainerUtil.map(superFunctions,
224 new Function<FunctionDescriptor, TypeAndName>() {
225 @Override
226 public TypeAndName fun(FunctionDescriptor superFunction) {
227 ReceiverParameterDescriptor receiver = superFunction.getExtensionReceiverParameter();
228 int index = receiver != null ? originalIndex - 1 : originalIndex;
229 if (index == -1) {
230 assert receiver != null : "can't happen: index is -1, while function is not extension";
231 return new TypeAndName(receiver.getType(), originalParam.getName());
232 }
233 ValueParameterDescriptor parameter = superFunction.getValueParameters().get(index);
234 return new TypeAndName(parameter.getType(), parameter.getName());
235 }
236 });
237
238 VarargCheckResult varargCheckResult = checkVarargInSuperFunctions(originalParam);
239
240 JetType altType = modifyTypeAccordingToSuperMethods(varargCheckResult.parameterType,
241 convertToTypeVarianceList(typesFromSuperMethods),
242 MEMBER_SIGNATURE_CONTRAVARIANT);
243
244 if (shouldBeExtension && originalIndex == 0) {
245 resultReceiverType = altType;
246 }
247 else {
248 Name stableName = null;
249 for (int i = 0; i < superFunctions.size(); i++) {
250 if (superFunctions.get(i).hasStableParameterNames()) {
251 // When there's more than one stable name in super functions, we pick the first one. This behaviour is similar to
252 // the compiler front-end, except that it reports a warning in such cases
253 // TODO: report a warning somewhere if there's more than one stable name in super functions
254 stableName = typesFromSuperMethods.get(i).name;
255 break;
256 }
257 }
258
259 resultParameters.add(new ValueParameterDescriptorImpl(
260 originalParam.getContainingDeclaration(),
261 null,
262 shouldBeExtension ? originalIndex - 1 : originalIndex,
263 originalParam.getAnnotations(),
264 stableName != null ? stableName : originalParam.getName(),
265 altType,
266 originalParam.declaresDefaultValue(),
267 varargCheckResult.isVararg ? getBuiltIns(originalParam).getArrayElementType(altType) : null,
268 SourceElement.NO_SOURCE
269 ));
270 }
271 }
272
273 boolean hasStableParameterNames = KotlinPackage.any(superFunctions, new Function1<FunctionDescriptor, Boolean>() {
274 @Override
275 public Boolean invoke(FunctionDescriptor descriptor) {
276 return descriptor.hasStableParameterNames();
277 }
278 });
279
280 return new ValueParameters(resultReceiverType, resultParameters, hasStableParameterNames);
281 }
282
283 @NotNull
284 private static List<TypeAndVariance> convertToTypeVarianceList(@NotNull List<TypeAndName> list) {
285 return KotlinPackage.map(list, new Function1<TypeAndName, TypeAndVariance>() {
286 @Override
287 public TypeAndVariance invoke(TypeAndName tvn) {
288 return new TypeAndVariance(tvn.type, INVARIANT);
289 }
290 });
291 }
292
293 private static List<FunctionDescriptor> getSuperFunctionsForMethod(
294 @NotNull JavaMethod method,
295 @NotNull JavaMethodDescriptor autoMethodDescriptor,
296 @NotNull ClassDescriptor containingClass
297 ) {
298 List<FunctionDescriptor> superFunctions = Lists.newArrayList();
299
300 // TODO: Add propagation for other kotlin descriptors (KT-3621)
301 Name name = method.getName();
302 JvmMethodSignature autoSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(autoMethodDescriptor);
303 for (JetType supertype : containingClass.getTypeConstructor().getSupertypes()) {
304 Collection<FunctionDescriptor> superFunctionCandidates = supertype.getMemberScope().getFunctions(name);
305 for (FunctionDescriptor candidate : superFunctionCandidates) {
306 JvmMethodSignature candidateSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(candidate);
307 if (JvmSignaturePackage.erasedSignaturesEqualIgnoringReturnTypes(autoSignature, candidateSignature)) {
308 superFunctions.add(candidate);
309 }
310 }
311 }
312
313 // sorting for diagnostic stability
314 Collections.sort(superFunctions, new Comparator<FunctionDescriptor>() {
315 @Override
316 public int compare(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
317 FqNameUnsafe fqName1 = getFqName(fun1.getContainingDeclaration());
318 FqNameUnsafe fqName2 = getFqName(fun2.getContainingDeclaration());
319 return fqName1.asString().compareTo(fqName2.asString());
320 }
321 });
322 return superFunctions;
323 }
324
325 private boolean checkIfShouldBeExtension() {
326 boolean someSupersExtension = false;
327 boolean someSupersNotExtension = false;
328
329 for (FunctionDescriptor superFunction : superFunctions) {
330 if (superFunction.getExtensionReceiverParameter() != null) {
331 someSupersExtension = true;
332 }
333 else {
334 someSupersNotExtension = true;
335 }
336 }
337
338 if (someSupersExtension) {
339 if (someSupersNotExtension) {
340 reportError("Incompatible super methods: some are extension functions, some are not");
341 }
342 else {
343 return true;
344 }
345 }
346 return false;
347 }
348
349 @NotNull
350 private VarargCheckResult checkVarargInSuperFunctions(@NotNull ValueParameterDescriptor originalParam) {
351 boolean someSupersVararg = false;
352 boolean someSupersNotVararg = false;
353 for (FunctionDescriptor superFunction : superFunctions) {
354 int originalIndex = originalParam.getIndex();
355 int index = superFunction.getExtensionReceiverParameter() != null ? originalIndex - 1 : originalIndex;
356 if (index != -1 && superFunction.getValueParameters().get(index).getVarargElementType() != null) {
357 someSupersVararg = true;
358 }
359 else {
360 someSupersNotVararg = true;
361 }
362 }
363
364 JetType originalVarargElementType = originalParam.getVarargElementType();
365 JetType originalType = originalParam.getType();
366
367 if (someSupersVararg && someSupersNotVararg) {
368 reportError("Incompatible super methods: some have vararg parameter, some have not");
369 return new VarargCheckResult(originalType, originalVarargElementType != null);
370 }
371
372 if (someSupersVararg && originalVarargElementType == null) {
373 // convert to vararg
374
375 assert isArrayType(originalType);
376 return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true);
377 }
378 else if (someSupersNotVararg && originalVarargElementType != null) {
379 // convert to non-vararg
380
381 assert isArrayType(originalType);
382 return new VarargCheckResult(TypeUtils.makeNullable(originalType), false);
383 }
384 return new VarargCheckResult(originalType, originalVarargElementType != null);
385 }
386
387 @NotNull
388 private JetType modifyTypeAccordingToSuperMethods(
389 @NotNull JetType autoType,
390 @NotNull List<TypeAndVariance> typesFromSuper,
391 @NotNull TypeUsage howThisTypeIsUsed
392 ) {
393 if (autoType.isError()) return autoType;
394
395 if (JvmPackage.getPLATFORM_TYPES()) return autoType;
396
397 boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, howThisTypeIsUsed);
398 ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper);
399 List<TypeProjection> resultArguments = getTypeArgsOfType(autoType, resultClassifier, typesFromSuper);
400 JetScope resultScope;
401 if (resultClassifier instanceof ClassDescriptor) {
402 resultScope = ((ClassDescriptor) resultClassifier).getMemberScope(resultArguments);
403 }
404 else {
405 resultScope = autoType.getMemberScope();
406 }
407
408 JetTypeImpl type = new JetTypeImpl(autoType.getAnnotations(),
409 resultClassifier.getTypeConstructor(),
410 resultNullable,
411 resultArguments,
412 resultScope);
413
414 PropagationHeuristics.checkArrayInReturnType(this, type, typesFromSuper);
415 return type;
416 }
417
418 @NotNull
419 private List<TypeProjection> getTypeArgsOfType(
420 @NotNull JetType autoType,
421 @NotNull ClassifierDescriptor classifier,
422 @NotNull List<TypeAndVariance> typesFromSuper
423 ) {
424 if (typesFromSuper.isEmpty()) return autoType.getArguments();
425
426 List<TypeProjection> autoArguments = autoType.getArguments();
427
428 if (!(classifier instanceof ClassDescriptor)) {
429 assert autoArguments.isEmpty() :
430 "Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType +
431 ", classifier = " + classifier + ", classifier class = " + classifier.getClass();
432 return autoArguments;
433 }
434
435 List<List<TypeProjectionAndVariance>> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper((ClassDescriptor) classifier,
436 typesFromSuper);
437
438 // Modify type arguments using info from typesFromSuper
439 List<TypeProjection> resultArguments = Lists.newArrayList();
440 for (TypeParameterDescriptor parameter : classifier.getTypeConstructor().getParameters()) {
441 TypeProjection argument = autoArguments.get(parameter.getIndex());
442
443 JetType argumentType = argument.getType();
444 List<TypeProjectionAndVariance> projectionsFromSuper = typeArgumentsFromSuper.get(parameter.getIndex());
445 List<TypeAndVariance> argTypesFromSuper = getTypes(projectionsFromSuper);
446
447 JetType type = modifyTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, TYPE_ARGUMENT);
448 Variance projectionKind = calculateArgumentProjectionKindFromSuper(argument, projectionsFromSuper);
449
450 resultArguments.add(new TypeProjectionImpl(projectionKind, type));
451 }
452 return resultArguments;
453 }
454
455 private Variance calculateArgumentProjectionKindFromSuper(
456 @NotNull TypeProjection argument,
457 @NotNull List<TypeProjectionAndVariance> projectionsFromSuper
458 ) {
459 if (projectionsFromSuper.isEmpty()) return argument.getProjectionKind();
460
461 Set<Variance> projectionKindsInSuper = Sets.newLinkedHashSet();
462 for (TypeProjectionAndVariance projectionAndVariance : projectionsFromSuper) {
463 projectionKindsInSuper.add(projectionAndVariance.typeProjection.getProjectionKind());
464 }
465
466 Variance defaultProjectionKind = argument.getProjectionKind();
467 if (projectionKindsInSuper.size() == 0) {
468 return defaultProjectionKind;
469 }
470 else if (projectionKindsInSuper.size() == 1) {
471 Variance projectionKindInSuper = projectionKindsInSuper.iterator().next();
472 if (defaultProjectionKind == INVARIANT || defaultProjectionKind == projectionKindInSuper) {
473 return projectionKindInSuper;
474 }
475 else {
476 reportError("Incompatible projection kinds in type arguments of super methods' return types: "
477 + projectionsFromSuper + ", defined in current: " + argument);
478 return defaultProjectionKind;
479 }
480 }
481 else {
482 reportError("Incompatible projection kinds in type arguments of super methods' return types: " + projectionsFromSuper);
483 return defaultProjectionKind;
484 }
485 }
486
487 @NotNull
488 private static List<TypeAndVariance> getTypes(@NotNull List<TypeProjectionAndVariance> projections) {
489 List<TypeAndVariance> types = Lists.newArrayList();
490 for (TypeProjectionAndVariance projection : projections) {
491 types.add(new TypeAndVariance(projection.typeProjection.getType(),
492 merge(projection.varianceOfPosition, projection.typeProjection.getProjectionKind())));
493 }
494 return types;
495 }
496
497 private static Variance merge(Variance positionOfOuter, Variance projectionKind) {
498 // Inv<Inv<out X>>, X is in invariant position
499 if (positionOfOuter == INVARIANT) return INVARIANT;
500 // Out<X>, X is in out-position
501 if (projectionKind == INVARIANT) return positionOfOuter;
502 // Out<Out<X>>, X is in out-position
503 // In<In<X>>, X is in out-position
504 // Out<In<X>>, X is in in-position
505 // In<Out<X>>, X is in in-position
506 return positionOfOuter.superpose(projectionKind);
507 }
508
509 // Returns list with type arguments info from supertypes
510 // Example:
511 // - Foo<A, B> is a subtype of Bar<A, List<B>>, Baz<Boolean, A>
512 // - input: klass = Foo, typesFromSuper = [Bar<String, List<Int>>, Baz<Boolean, CharSequence>]
513 // - output[0] = [String, CharSequence], output[1] = []
514 private static List<List<TypeProjectionAndVariance>> calculateTypeArgumentsFromSuper(
515 @NotNull ClassDescriptor klass,
516 @NotNull Collection<TypeAndVariance> typesFromSuper
517 ) {
518 // For each superclass of klass and its parameters, hold their mapping to klass' parameters
519 // #0 of Bar -> A
520 // #1 of Bar -> List<B>
521 // #0 of Baz -> Boolean
522 // #1 of Baz -> A
523 // #0 of Foo -> A (mapped to itself)
524 // #1 of Foo -> B (mapped to itself)
525 Multimap<TypeConstructor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
526 TypeUtils.makeUnsubstitutedType(klass, ErrorUtils.createErrorScope("Do not access this scope", true)));
527
528 // for each parameter of klass, hold arguments in corresponding supertypes
529 List<List<TypeProjectionAndVariance>> parameterToArgumentsFromSuper = Lists.newArrayList();
530 for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) {
531 parameterToArgumentsFromSuper.add(new ArrayList<TypeProjectionAndVariance>());
532 }
533
534 // Enumerate all types from super and all its parameters
535 for (TypeAndVariance typeFromSuper : typesFromSuper) {
536 for (TypeParameterDescriptor parameter : typeFromSuper.type.getConstructor().getParameters()) {
537 TypeProjection argument = typeFromSuper.type.getArguments().get(parameter.getIndex());
538
539 // for given example, this block is executed four times:
540 // 1. typeFromSuper = Bar<String, List<Int>>, parameter = "#0 of Bar", argument = String
541 // 2. typeFromSuper = Bar<String, List<Int>>, parameter = "#1 of Bar", argument = List<Int>
542 // 3. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#0 of Baz", argument = Boolean
543 // 4. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#1 of Baz", argument = CharSequence
544
545 // if it is mapped to klass' parameter, then store it into map
546 for (TypeProjection projection : substitution.get(parameter.getTypeConstructor())) {
547 // 1. projection = A
548 // 2. projection = List<B>
549 // 3. projection = Boolean
550 // 4. projection = A
551 ClassifierDescriptor classifier = projection.getType().getConstructor().getDeclarationDescriptor();
552
553 // this condition is true for 1 and 4, false for 2 and 3
554 if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == klass) {
555 int parameterIndex = ((TypeParameterDescriptor) classifier).getIndex();
556 Variance effectiveVariance = parameter.getVariance().superpose(typeFromSuper.varianceOfPosition);
557 parameterToArgumentsFromSuper.get(parameterIndex).add(new TypeProjectionAndVariance(argument, effectiveVariance));
558 }
559 }
560 }
561 }
562 return parameterToArgumentsFromSuper;
563 }
564
565 private boolean typeMustBeNullable(
566 @NotNull JetType autoType,
567 @NotNull List<TypeAndVariance> typesFromSuper,
568 @NotNull TypeUsage howThisTypeIsUsed
569 ) {
570 boolean someSupersNotCovariantNullable = false;
571 boolean someSupersCovariantNullable = false;
572 boolean someSupersNotNull = false;
573 for (TypeAndVariance typeFromSuper : typesFromSuper) {
574 if (!TypeUtils.isNullableType(typeFromSuper.type)) {
575 someSupersNotNull = true;
576 }
577 else {
578 if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
579 someSupersCovariantNullable = true;
580 }
581 else {
582 someSupersNotCovariantNullable = true;
583 }
584 }
585 }
586
587 if (someSupersNotNull && someSupersNotCovariantNullable) {
588 reportError("Incompatible types in superclasses: " + typesFromSuper);
589 return TypeUtils.isNullableType(autoType);
590 }
591 else if (someSupersNotNull) {
592 return false;
593 }
594 else if (someSupersNotCovariantNullable || someSupersCovariantNullable) {
595 boolean annotatedAsNotNull = howThisTypeIsUsed != TYPE_ARGUMENT && !TypeUtils.isNullableType(autoType);
596
597 if (annotatedAsNotNull && someSupersNotCovariantNullable) {
598 DescriptorRenderer renderer = DescriptorRenderer.SHORT_NAMES_IN_TYPES;
599 reportError("In superclass type is nullable: " + typesFromSuper + ", in subclass it is not: " + renderer.renderType(autoType));
600 return true;
601 }
602
603 return !annotatedAsNotNull;
604 }
605 return TypeUtils.isNullableType(autoType);
606 }
607
608 @NotNull
609 private ClassifierDescriptor modifyTypeClassifier(
610 @NotNull JetType autoType,
611 @NotNull List<TypeAndVariance> typesFromSuper
612 ) {
613 ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor();
614 if (!(classifier instanceof ClassDescriptor)) {
615 assert classifier != null : "no declaration descriptor for type " + autoType + ", auto method descriptor: " + autoMethodDescriptor;
616
617 if (classifier instanceof TypeParameterDescriptor && autoTypeParameterToModified.containsKey(classifier)) {
618 return autoTypeParameterToModified.get(classifier);
619 }
620 return classifier;
621 }
622 ClassDescriptor klass = (ClassDescriptor) classifier;
623
624 boolean someSupersMutable = false;
625 boolean someSupersCovariantReadOnly = false;
626 boolean someSupersNotCovariantReadOnly = false;
627 for (TypeAndVariance typeFromSuper : typesFromSuper) {
628 ClassifierDescriptor classifierFromSuper = typeFromSuper.type.getConstructor().getDeclarationDescriptor();
629 if (classifierFromSuper instanceof ClassDescriptor) {
630 ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper;
631
632 if (JavaToKotlinClassMap.INSTANCE.isMutableCollection(classFromSuper)) {
633 someSupersMutable = true;
634 }
635 else if (JavaToKotlinClassMap.INSTANCE.isReadOnlyCollection(classFromSuper)) {
636 if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
637 someSupersCovariantReadOnly = true;
638 }
639 else {
640 someSupersNotCovariantReadOnly = true;
641 }
642 }
643 }
644 }
645
646 if (someSupersMutable && someSupersNotCovariantReadOnly) {
647 reportError("Incompatible types in superclasses: " + typesFromSuper);
648 return classifier;
649 }
650 else if (someSupersMutable) {
651 if (JavaToKotlinClassMap.INSTANCE.isReadOnlyCollection(klass)) {
652 return JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(klass);
653 }
654 }
655 else if (someSupersNotCovariantReadOnly || someSupersCovariantReadOnly) {
656 if (JavaToKotlinClassMap.INSTANCE.isMutableCollection(klass)) {
657 return JavaToKotlinClassMap.INSTANCE.convertMutableToReadOnly(klass);
658 }
659 }
660
661 ClassifierDescriptor fixed = PropagationHeuristics.tryToFixOverridingTWithRawType(this, typesFromSuper);
662 return fixed != null ? fixed : classifier;
663 }
664
665 private static boolean isArrayType(@NotNull JetType type) {
666 return KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type);
667 }
668
669 private static class VarargCheckResult {
670 public final JetType parameterType;
671 public final boolean isVararg;
672
673 public VarargCheckResult(JetType parameterType, boolean isVararg) {
674 this.parameterType = parameterType;
675 this.isVararg = isVararg;
676 }
677 }
678
679 private static class TypeProjectionAndVariance {
680 public final TypeProjection typeProjection;
681 public final Variance varianceOfPosition;
682
683 public TypeProjectionAndVariance(TypeProjection typeProjection, Variance varianceOfPosition) {
684 this.typeProjection = typeProjection;
685 this.varianceOfPosition = varianceOfPosition;
686 }
687
688 public String toString() {
689 return typeProjection.toString();
690 }
691 }
692
693 static class TypeAndVariance {
694 public final JetType type;
695 public final Variance varianceOfPosition;
696
697 public TypeAndVariance(JetType type, Variance varianceOfPosition) {
698 this.type = type;
699 this.varianceOfPosition = varianceOfPosition;
700 }
701
702 public String toString() {
703 return type.toString();
704 }
705 }
706
707 private static class TypeAndName {
708 public final JetType type;
709 public final Name name;
710
711 public TypeAndName(JetType type, Name name) {
712 this.type = type;
713 this.name = name;
714 }
715 }
716
717 private static class ValueParameters {
718 private final JetType receiverType;
719 private final List<ValueParameterDescriptor> descriptors;
720 private final boolean hasStableParameterNames;
721
722 public ValueParameters(
723 @Nullable JetType receiverType,
724 @NotNull List<ValueParameterDescriptor> descriptors,
725 boolean hasStableParameterNames
726 ) {
727 this.receiverType = receiverType;
728 this.descriptors = descriptors;
729 this.hasStableParameterNames = hasStableParameterNames;
730 }
731 }
732 }