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