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