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 }