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 }