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