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