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