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