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