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    }