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