Compare commits

...

133 Commits

Author SHA1 Message Date
Pavel Punegov
d48a7a55c6 Reduce signal usage 2021-06-03 13:23:24 +03:00
Pavel Punegov
30639af5a3 move to native 2021-06-03 13:07:16 +03:00
Pavel Punegov
3add3f091d remove 2021-06-03 00:35:08 +03:00
Pavel Punegov
4583e31991 add configure after evaluation 2021-06-02 23:20:44 +03:00
Pavel Punegov
f49fe26632 Use configureEach 2021-06-02 23:15:41 +03:00
Pavel Punegov
73ec5d27a6 Use interpreter for all 1.6 java tasks 2021-06-02 23:02:14 +03:00
Pavel Punegov
ac0dc94800 Since 1.5.30-dev-1466 a new archive naming schema was introduced
Support both names in NativeCompilerDownloader
2021-06-02 18:30:52 +03:00
Pavel Punegov
789799ac17 Revert simpleOsName in HostManager
Support old naming in simpleOsName.
Introduce new platformName method for the new archive naming.
2021-06-02 18:30:52 +03:00
Leonid Startsev
1f837134bb Support for @EncodeDefault annotation 2021-06-02 13:43:39 +00:00
Alexander Dudinsky
e6e3c9b236 Use master name for tests with snapshot version Kotlin Gradle Plugin 2021-06-02 15:23:31 +03:00
Roman Artemev
5f65b46dfc [JS IR] Unmute fixed tests 2021-06-02 13:42:35 +03:00
Roman Artemev
a36135baf1 [JS IR] Fix reflection generation 2021-06-02 13:42:35 +03:00
Roman Artemev
974779e91b [JS IR] Support function reference to array inline constructor 2021-06-02 13:42:34 +03:00
Tianyu Geng
84334b087c FIR checkers: report SMARTCAST_IMPOSSIBLE 2021-06-02 13:19:12 +03:00
Tianyu Geng
62f7e8f71f FIR DFA: store stability in RealVariable
As part of this change, we also extend the usage of RealVariable in more
places during DFA. Now mutable properties, property with custom getters,
delegated properties, etc are also treatd as a `RealVariable`. In
general this is needed in order to carry out smartcast computation in
order to report `SMARTCAST_IMPOSSIBLE`. It seems to also have side
effects that improves behavior of some test files.
2021-06-02 13:19:12 +03:00
Tianyu Geng
96bd2c54f0 FIR: add smartcast stability to FIR 2021-06-02 13:19:12 +03:00
Tianyu Geng
931a637bdd FIR: use isReal() and isSynthetic() helper consistently 2021-06-02 13:19:11 +03:00
Vladimir Ivanov
2165cc8f0d [Native] Fix test data for testObjCExportNoGeneric (#4424) 2021-06-02 11:13:07 +03:00
Vladimir Ivanov
e06a60bda5 [Native] Clean up nested comment when exporting kdoc to objc header (#4410)
* [Native] Clean up nested comment when exporting kdoc to objc header

* [kdoc-export] Add test witg nested comment block

* Remove redundant assert

Co-authored-by: Vladimir Ivanov <vladimir.d.ivanov@jetbrains.com>
2021-06-02 10:18:32 +03:00
Alexander Udalov
61d5595790 Remove dependency of ir.serialization.common on frontend 2021-06-01 20:28:23 +02:00
Alexander Udalov
dfea915f92 Remove dependency of frontend on compiler.common.jvm
Looks like it was added accidentally in 564d382b9d; common frontend
shouldn't depend on JVM-specific modules.

Since then, it has been accidentally used in two places in
ir.serialization.common to refer to JVM specifics, and that should be
abstracted away in the future.
2021-06-01 20:28:23 +02:00
Alexander Udalov
81ce1da352 Move PsiSourceElement to psi 2021-06-01 20:28:23 +02:00
Alexander Udalov
bcf47ddc94 Move optional annotation utilities to module 'resolution'
To avoid depending on a heavy module 'frontend' in parts of the compiler
where checking for optional annotations is needed, such as in
'ir.serialization.common'.
2021-06-01 20:28:22 +02:00
Alexander Udalov
e790fa8ac9 Remove dependency of serialization on frontend
Move ApplicationExtensionDescriptor and ProjectExtensionDescriptor to
:compiler:util.
2021-06-01 20:28:22 +02:00
Alexander Udalov
8b3769b88e Remove dependency of ir.serialization.common on ir.backend.common 2021-06-01 20:28:22 +02:00
Alexander Udalov
a3ad03d1ad Slightly refactor module dependencies of backend.js/serialization.js
The comment in serialization.js/build.gradle.kts is not needed because
such dependency cannot be introduced accidentally, since Gradle does not
support cycles in module dependencies.
2021-06-01 20:28:22 +02:00
Leonid Startsev
b43e5a5e7d fixup! Fix tests and review notes 2021-06-01 16:41:56 +00:00
Leonid Startsev
6a5cf00d7a Optimize serializer instantiation: use Companion.serializer() when possible
Add test for sealed hierarchy
2021-06-01 16:41:55 +00:00
Leonid Startsev
b61277df97 Support annotations in constructor signatures of special serializers 2021-06-01 16:41:55 +00:00
Leonid Startsev
229085f3d1 Support default parameter values in @SerialInfo annotations
#KT-46739 Fixed
Fixes https://github.com/Kotlin/kotlinx.serialization/issues/1461
2021-06-01 16:41:54 +00:00
Mads Ager
f846dd8ea2 [JVM_IR] Avoid using special names in static inline class replacements.
Fixes KT-46952
2021-06-01 16:22:14 +02:00
Aleksei.Cherepanov
b1ab597616 Fix FIR tests after ee45aa6b 2021-06-01 15:59:17 +03:00
Pavel Punegov
3293a888ca [native] Archive naming: use $os-$arch convention 2021-06-01 10:20:05 +00:00
Pavel Punegov
48ef739525 [native] Rename Apple MacOS targets in simpleOsName
Use Arm64 suffix for Apple Arm arch and X64 for Intel X86_64
2021-06-01 10:20:04 +00:00
Alexander Shabalin
825b77cc82 Remove unused ostream 2021-06-01 07:01:11 +00:00
Mikhael Bogdanov
b72aa76415 Support class type parameters annotation checking 2021-06-01 06:33:51 +02:00
Mikhael Bogdanov
a8186d19d6 Support annotations on class type parameters
#KT-43714
2021-06-01 06:33:50 +02:00
Dmitry Petrov
9091ca7b51 JVM_IR KT-46864 handle "unused" LDC instructions properly 2021-05-31 21:12:35 +03:00
Andrey Uskov
be097244d4 fixup synchronizations 2021-05-31 20:23:54 +03:00
Aleksei.Cherepanov
b0d721c9d0 Fix synchronization in translation-result map
#KT-27660 Fixed
2021-05-31 20:23:53 +03:00
Aleksei.Cherepanov
290d424111 Fix synchronization in source-to-classes table 2021-05-31 20:23:52 +03:00
Aleksei.Cherepanov
ee45aa6b08 Fixed closing of cache storage
#KTIJ-7680 Fixed
#KT-45843 Fixed
2021-05-31 20:23:51 +03:00
Mads Ager
886ce055f5 [JVM_IR] Do not use invoke-dynamic for targeting inline-only methods.
Fixes https://youtrack.jetbrains.com/issue/KT-46962
2021-05-31 18:11:50 +03:00
pyos
5c2753b5d1 JVM_IR: use substituted return type in function reference invoke
#KT-46982 Fixed
2021-05-31 16:01:22 +03:00
Vasily Levchenko
84c10079e4 [kotlin-native][tests] kt-42208 test added. 2021-05-31 11:45:32 +00:00
Vasily Levchenko
1ff6dc1275 [kotlin][tests][compiler/testData/debug/stepping] kt-42208 test added. 2021-05-31 11:45:31 +00:00
Vasily Levchenko
ecbae02f17 [IR][provisional function expression] another line information provider added for func_expression -> function_reference conversion 2021-05-31 11:45:31 +00:00
Dmitriy Novozhilov
c6a2d85c87 [Build] Remove incorrect dependency
`intellijDep()` includes jars with JUnit3 and JUnit4. JUnit5 runner
  which is used in compiler tests sees old junit on classpath and checks
  if this version can be ran using Vintage test engine. Looks like recent
  changes in platform changed order of this jars on classpath, so now
  jar with JUnit3 is closer than JUnit4 (and they have same classes inside),
  so version checker from JUnit5 observes JUnit3 and fails with error
  of incompatible versions. Since old JUnits are not needed at all in those
  modules now only required jars from intellijDep are included
2021-05-31 14:03:37 +03:00
Dmitriy Novozhilov
6121d156a1 [Build] Add workarounds for JPS build
Compilation of `:kotlin-gradle-statistics:test` is broken in gradle
  too, so this module is removed from JPS to allow build project with
  "Rebuild project" action

Dependency on `:kotlin-uast-base` changed to `implementation` because
  project import assumes `shadow` dependency as _Provided_ instead of
  _Compile_ in module structure which leads to problem that this
  dependency is missing during build (this is bug inside JPS itself)
2021-05-31 14:03:37 +03:00
Abduqodiri Qurbonzoda
d934c97bf5 Equivalize isLowerCase and isUpperCase behavior in all platforms #KT-46184 2021-05-31 13:42:46 +03:00
Yahor Berdnikau
0b10f255d7 Update 'kotlinOptions.jdkHome' deprecation message.
Also mention java toolchains approach.

^KT-43095 Fixed
2021-05-31 10:22:50 +00:00
Yahor Berdnikau
c5e6215d27 Set UsesKotlinJavaToolchain interface to extend Task interface.
Limit use-case of UsesKotlinJavaToolchain interface to only Gradle tasks
and allow to query all tasks using
 'taskContainer.withType(UsesKotlinJavaToolchain.class)'.

^KT-43095 In Progress
2021-05-31 10:22:50 +00:00
Yahor Berdnikau
4c943e7cd1 Allow to configure non-default JDK using toolchain via extension.
Add method into "kotlin" extension to set toolchain for all tasks.
This will also set toolchain for java compile tasks. Also user may
set toolchain via "java" extension and it will be applied to Kotlin
tasks as well.

^KT-43092 In Progress
2021-05-31 10:22:49 +00:00
Yahor Berdnikau
8e1c420c9f Allow to set non-default JDK for tasks via java toolchain.
Has to split jdk/toolchain setters, because, when toolchain setter is
in the 'UsesKotlinJavaToolchain', Groovy fails to create meta class
on <Gradle 6.7 with ClassNotFoundException.

^KT-43092 In Progress
2021-05-31 10:22:48 +00:00
Ilya Matveev
de5dcfcbd8 [K/N][Runtime] Support suspending mutators in the new MM 2021-05-31 09:48:46 +00:00
Alexander Likhachev
94a94a557d [Gradle, JS] Add test for KT-47045 2021-05-31 11:43:18 +03:00
Alexander Likhachev
89f8c5a651 [Gradle, JS] Prevent adding unintended implicit dependencies
The way JS compilations are mapped to task requirements were changed from `compilation` objects to compilations's `disambiguatedName` in order to support Gradle configuration cache. This may lead to implicitly adding unwanted dependencies in multi-module projects since compilation's `disambiguatedName` is unique within a module, not within a whole multi-module project.
#KT-47045 Fixed
2021-05-31 11:43:18 +03:00
Andrey Zinovyev
78e20c1098 [KAPT] Keep original expressions in annotations vararg
#KT-29929 Fixed
2021-05-31 08:08:37 +00:00
Dmitriy Dolovov
e927764aaf [IR][Native] Fix invalid IR return statement generation
^KT-46836
2021-05-29 19:31:13 +00:00
Victor Petukhov
15b6a3c88c Temporary don't fail fir tests if a test passes but *.fir.fail exists (needs for DiagnosisCompilerTestFE10TestdataTestGenerated) 2021-05-29 11:30:55 +03:00
Nikita Bobko
3e892d3184 'idea-fir-fe10-binding' move fir tests into subpackage 'org.jetbrains.kotlin.idea.fir'
In intellij infrastructure we run tests by matching package pattern.
So in order to be able run FIR tests we need to place them into unique package
2021-05-29 00:11:28 +03:00
Nikita Bobko
65972fa64c 'idea-frontend-fir' move fir tests into subpackage 'org.jetbrains.kotlin.idea.fir'
In intellij infrastructure we run tests by matching package pattern.
So in order to be able run FIR tests we need to place them into unique package
2021-05-29 00:11:27 +03:00
Nikita Bobko
1ba6845b59 'idea-fir' move fir tests into subpackage 'org.jetbrains.kotlin.idea.fir'
In intellij infrastructure we run tests by matching package pattern.
So in order to be able run FIR tests we need to place them into unique package
2021-05-29 00:11:26 +03:00
Alexander Udalov
e7275a7cb0 Revert "Enable JVM IR for stdlib/reflect/test libraries"
This reverts commit 15e978dbd3.

Together with the previous revert, this led to multiple failures in
Gradle integration tests:

    ConfigurationCacheIT.testIncrementalKaptProject
    ConfigurationCacheForAndroidIT.testAndroidKaptProject
    KotlinAndroid34GradleIT.testParcelize
    KotlinAndroid34GradleIT.testAndroidExtensionsManyVariants
    KotlinAndroid36GradleIT.testAndroidWithNewMppApp
    KotlinAndroid36GradleIT.testParcelize
    KotlinAndroid36GradleIT.testAndroidIcepickProject
2021-05-28 21:36:24 +02:00
Alexander Udalov
e0cc6d44a7 Revert "Remove obsolete kotlin.build.useIR flag"
This reverts commit 91e47f1fd7.
2021-05-28 21:35:57 +02:00
Victor Petukhov
67d48d0150 Fix failing test 2021-05-28 21:38:27 +03:00
Alexander Udalov
96f0b53761 IR: get overridden directly from IrProperty when resolving fake override
The previous way of getting them either via getter or setter failed on
Java properties which only have a backing field. Now that IrProperty has
overriddenSymbols (after 53c1de172f), it makes sense to use it directly
instead. Use it only in SyntheticAccessorLowering though to avoid
breaking Kotlin/Native (see KT-47019).

 #KT-46900 Fixed
2021-05-28 17:24:20 +02:00
Mark Punzalan
af35892007 FIR IDE: Enable RemoveUselessIsCheckFix and
RemoveUselessIsCheckFixForWhen.
2021-05-28 18:21:32 +03:00
Mark Punzalan
639b7537da FIR IDE: Enable RemoveUselessCastFix. 2021-05-28 18:21:31 +03:00
Pavel Kirpichenkov
f5a53c82c5 Don't write type arguments of types replaced with Any to metadata
Anonymous types are not approximated by frontend for private declarations.
Class IDs for such types are replaced by StringTable before being written
to metadata. JVM string table mangles such types and keeps them generic
for reflection. For other purposes the types are replaced with `Any`.
Type arguments of the replaced type should be ignored in the latter case.
Otherwise decompiled text builder crashes on an attempt to restore `Any`
type with non-zero number of type arguments.

The code pretending to replace a type with its first supertype was dropped
from ApproximatingStringTable for two reasons:
- the first type from `getAllSuperClassifiers` is the original type itself
which doens't provide a ClassId for anonymous type, so it was a noop
- tracking potential type arguments of the first anonymous type's supertype
would be a complication with almost no practical value (types in decompiled
text would be slightly closer to the real type of a private declaration).

^KT-46393 Fixed
2021-05-28 14:42:47 +00:00
sebastian.sellmair
fefc6f9b53 [Gradle] :kotlin-test-js-runner: Update nodejs to 16.2.0
^KT-45302
2021-05-28 14:27:36 +00:00
sebastian.sellmair
d3b1ee42be [Gradle] Test project 'commonizeHierarchically': Use new 'macos' target shortcut
^KT-45302
2021-05-28 14:27:36 +00:00
sebastian.sellmair
cc571a876a [Gradle] Implement AppleSiliconIT
^KT-45302
2021-05-28 14:27:35 +00:00
sebastian.sellmair
242d79ded6 [Gradle] :kotlin-gradle-plugin-integration-tests: Include Commonizer tests into 'native' tests
^KT-45302
2021-05-28 14:27:34 +00:00
sebastian.sellmair
b9018e8888 [Gradle] :kotlin-gradle-plugin-integration-tests: Add 'includeTestsWithPattern' util function
^KT-45302
2021-05-28 14:27:33 +00:00
sebastian.sellmair
5dcaaf47cb [Gradle] Support for Apple Silicon targets
^KT-45302 Verification Pending
2021-05-28 14:27:32 +00:00
Alexander Udalov
91e47f1fd7 Remove obsolete kotlin.build.useIR flag 2021-05-28 15:41:57 +02:00
Alexander Udalov
15e978dbd3 Enable JVM IR for stdlib/reflect/test libraries 2021-05-28 15:41:56 +02:00
Alexander Udalov
1dfcec3a93 Build: add temporary option to suppress jdkHome warning 2021-05-28 15:41:17 +02:00
Victor Petukhov
aaffd73feb Take into account FE exceptions built as FromFrontendHandler to proper mute corresponding tests for DiagnosisCompilerTestFE10TestdataTestGenerated 2021-05-28 15:48:59 +03:00
Victor Petukhov
54b9f39b3a Update tests after rebase 2021-05-28 15:36:24 +03:00
Victor Petukhov
f4788b479c Fix incorrect builder inference usage 2021-05-28 15:36:23 +03:00
Victor Petukhov
76c15e4444 Don't update null recorded type prematurely in ResolvedAtomCompleter 2021-05-28 15:36:23 +03:00
Victor Petukhov
bd7fb56a24 Fix builder inference tests 2021-05-28 15:36:23 +03:00
Victor Petukhov
4a767c597e Don't report the same diagnsotics several times 2021-05-28 15:36:23 +03:00
Victor Petukhov
e942052eb6 Substitute stub type variables in local variable descriptors 2021-05-28 15:36:22 +03:00
Victor Petukhov
758eb8f851 Fix builder inference tests 2021-05-28 15:36:22 +03:00
Victor Petukhov
be22078bd1 Return empty NotFixedToInferredTypesSubstitutor if the current substitutor is empty 2021-05-28 15:36:22 +03:00
Victor Petukhov
d8c68aacdd Split setting substitutor descriptor for entire resolved call into two parts: setting resulting substitutor and setting substitutor for resolved call's types 2021-05-28 15:36:22 +03:00
Victor Petukhov
fd5169186e Update test for the builder inference and add new ones 2021-05-28 15:36:21 +03:00
Victor Petukhov
31ed1ad5d9 Use recorded into descriptor inferred callable reference input/output types, to prevent leaking raw type parameter's types of reflectionCandidateType into the back-end 2021-05-28 15:36:21 +03:00
Victor Petukhov
84bd580f92 Complete block expressions to substitute stub type variables into last callable references there 2021-05-28 15:36:21 +03:00
Victor Petukhov
472ab09511 Do stub types substitution for property initializer's type 2021-05-28 15:36:20 +03:00
Victor Petukhov
ac222fdb41 Update type for both version of expression: parenthesis and not 2021-05-28 15:36:20 +03:00
Victor Petukhov
c0ad1c9b18 Do substitution of stub types inside smartcast types to further write it into trace and prevent dealing with that in the back-end 2021-05-28 15:36:20 +03:00
Victor Petukhov
26cbb020db Use resulting descriptor for old callable references to substitute stub type variables 2021-05-28 15:36:20 +03:00
Victor Petukhov
3ff22b67f7 Substitute type arguments of old callable references as well 2021-05-28 15:36:20 +03:00
Victor Petukhov
d5be258291 Do substitution for receivers of old (by passing though OI) callable references properly, with avoiding premature returning from the method 2021-05-28 15:36:19 +03:00
Victor Petukhov
9fd1cbd2e7 Inject stub type variables of a different builder inference call properly 2021-05-28 15:36:19 +03:00
Victor Petukhov
d486f7e188 Don't report TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE if unrestricted build inference was enabled 2021-05-28 15:36:19 +03:00
Victor Petukhov
0c427555cf Support definitely not null stub types and proper subtyping on them 2021-05-28 15:36:19 +03:00
Victor Petukhov
0f317b01b4 Rename language feature StableBuilderInference to UnrestrictedBuilderInference 2021-05-28 15:36:19 +03:00
Victor Petukhov
0b37b2be6a Add addtional tests for builder inference 2021-05-28 15:36:19 +03:00
Victor Petukhov
ecde5414dc Reuse error type constructor for stub types 2021-05-28 15:36:18 +03:00
Victor Petukhov
ee927a15a9 Compute nullability for stub types properly 2021-05-28 15:36:18 +03:00
Victor Petukhov
afbda75581 Set member scope for builder inference stub types equivalent to Any 2021-05-28 15:36:18 +03:00
Victor Petukhov
6356b9d501 Put removing builder inference restrictions under the compiler flag 2021-05-28 15:36:17 +03:00
Victor Petukhov
5a11450d77 Split stub types into stub type for subtyping and for builder inference and use them in the proper way 2021-05-28 15:36:17 +03:00
Victor Petukhov
703a353d2e Determine empty constraint system for a builder inference call by presense of not fixed type variables 2021-05-28 15:36:17 +03:00
Victor Petukhov
c5faf532f5 Allow builder inference calls with labeled lambda
^KT-24993 Fixed
2021-05-28 15:36:16 +03:00
Victor Petukhov
90066d7e50 Add expected type constraints in a builder inference call 2021-05-28 15:36:16 +03:00
Victor Petukhov
7da47dcde8 Add type variables into common system of a builder inference call properly 2021-05-28 15:36:15 +03:00
Victor Petukhov
ac7b459f2a Do subtyping with stub types properly
1) Return stub type if we are calculating super type between two same stub types
2) Return nullable Any if those stub types are different
2021-05-28 15:36:15 +03:00
Victor Petukhov
5d0461c722 Remove restrictions for builder inference internal calls 2021-05-28 15:36:14 +03:00
Victor Petukhov
26b8e86fe1 Render stub types properly 2021-05-28 15:36:14 +03:00
Nikita Bobko
af12b2fdf0 [imltogradle] Replace "Exported transitive dependency" with original module name reference 2021-05-28 14:03:07 +02:00
Nikita Bobko
6a7770573c [imltogradle] Support attaching 211 IDEA 2021-05-28 14:03:07 +02:00
Roman Artemev
8a856e440e [KLIB] Fix linker diagnostic message 2021-05-28 13:37:30 +03:00
Roman Artemev
720edfa6aa [IR] Fix branch offests
Seems logic that right bound of branch is result's right bound,
not condition's.
2021-05-28 13:23:52 +03:00
Andrey Zinovyev
ebf6ce133b [FIR] Fix kotlin version check in annotations
@RequireKotlin has more than one string parameter, so you need to check
 'version' only
2021-05-28 12:24:58 +03:00
Elena Lepilkina
3a22761d02 [K/N] Fix MutationCheck calls for inlined property accessors 2021-05-28 06:45:53 +00:00
Elena Lepilkina
b6f35ac44d [K/N] Fix inlining of property setters by replacing ReturnsInsertion lowering 2021-05-28 06:45:52 +00:00
Yahor Berdnikau
3387615d4a Fix test requires more later Gradle version. 2021-05-27 18:12:02 +00:00
Yahor Berdnikau
cdb04f9cd7 Add 'kgpSimpleTests' task.
This task run all JUnit5 tests with annotated with '@SimpleKGPTests`
annotation and also will be used in CI configuration.

^KT-45745 In Progress
2021-05-27 18:12:02 +00:00
Alexander Shabalin
af1f57007a https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2 2021-05-27 17:18:55 +00:00
Nikolay Krasko
0b1884c994 Print memory consumption in the failure for GradleDaemonMemoryIT test 2021-05-27 20:13:10 +03:00
Nikolay Krasko
166f0a597b Run tests only for unique gradle versions 2021-05-27 20:13:09 +03:00
Nikolay Krasko
b5f71bacaf Never spam to log during the normal test execution in Gradle tests 2021-05-27 20:13:08 +03:00
Nikolay Krasko
9d1a6ebb18 Minor: narrow extracting functions scope 2021-05-27 20:13:07 +03:00
Mark Punzalan
d12a24418e FIR IDE: Remove multiple nested params in RemoveUselessElvisFix and
RemoveUselessCastFix.
2021-05-27 19:32:03 +03:00
Mark Punzalan
a778cc673e FIR IDE: Enable RemoveUselessElvisFix. 2021-05-27 19:32:01 +03:00
Ilya Goncharov
157046153f [Gradle, JS] Add test with dynamic webpack.config.d 2021-05-27 19:18:13 +03:00
Hung Nguyen
01c14a709a KotlinCompile: Add kotlin.incremental.useClasspathSnapshot flag
We are planning to improve incremental Kotlin compile with a new
approach using classpath snapshot (see
https://youtrack.jetbrains.com/issue/KT-45777 for more details).

The estimated steps will be as follows:
  [x] Add a flag for the new approach, disabled by default
  [ ] Add tests for the new approach, and update them as we go
  [ ] Add computation of classpath snapshot using artifact transforms
  [ ] Add computation of classpath snapshot changes
  [ ] Ensure incremental compile is fully functional with the new approach
  [ ] Measure performance + optimize: Repeat until we see evidence that
      the new approach is clearly better than the current approach
  [ ] Advertise the flag, and later on enable it by default

This commit is the first step. Although it's simple, it allows further
changes to be made safely without impacting the current approach.

Bug: KT-45777
Test: N/A (will be added in a subsequent change)
2021-05-27 19:05:26 +03:00
708 changed files with 14049 additions and 2156 deletions

View File

@@ -234,17 +234,20 @@ private class TranslationResultMap(
override fun dumpValue(value: TranslationResultValue): String =
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}, InlineData: ${value.inlineData.md5()}"
@Synchronized
fun put(sourceFile: File, newMetadata: ByteArray, newBinaryAst: ByteArray, newInlineData: ByteArray) {
storage[pathConverter.toPath(sourceFile)] =
TranslationResultValue(metadata = newMetadata, binaryAst = newBinaryAst, inlineData = newInlineData)
}
@Synchronized
operator fun get(sourceFile: File): TranslationResultValue? =
storage[pathConverter.toPath(sourceFile)]
fun keys(): Collection<File> =
storage.keys.map { pathConverter.toFile(it) }
@Synchronized
fun remove(sourceFile: File, changesCollector: ChangesCollector) {
val path = pathConverter.toPath(sourceFile)
val protoBytes = storage[path]!!.metadata
@@ -378,6 +381,7 @@ private class InlineFunctionsMap(
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
@Synchronized
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
val key = pathConverter.toPath(srcFile)
val oldMap = storage[key] ?: emptyMap()
@@ -395,6 +399,7 @@ private class InlineFunctionsMap(
}
}
@Synchronized
fun remove(sourceFile: File) {
storage.remove(pathConverter.toPath(sourceFile))
}

View File

@@ -47,10 +47,16 @@ abstract class BasicMap<K : Comparable<K>, V>(
storage.flush(memoryCachesOnly)
}
// avoid unsynchronized close
fun close() {
storage.close()
}
@TestOnly
fun closeForTest() {
close()
}
@TestOnly
fun dump(): String {
return with(StringBuilder()) {

View File

@@ -34,7 +34,6 @@ class CachingLazyStorage<K, V>(
) : LazyStorage<K, V> {
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
@@ -46,32 +45,36 @@ class CachingLazyStorage<K, V>(
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
override val keys: Collection<K>
@Synchronized
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
@Synchronized
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
@Synchronized
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
@Synchronized
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
@Synchronized
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
@Synchronized
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key, { valueExternalizer.save(it, value) })
}
@@ -103,7 +106,11 @@ class CachingLazyStorage<K, V>(
@Synchronized
override fun close() {
storage?.close()
try {
storage?.close()
} finally {
storage = null
}
}
private fun createMap(): PersistentHashMap<K, V> = PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)

View File

@@ -28,6 +28,7 @@ internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collec
storage.append(key.asString(), listOf(value.asString()))
}
@Synchronized
operator fun get(key: FqName): Collection<FqName> =
storage[key.asString()]?.map(::FqName) ?: setOf()

View File

@@ -31,7 +31,6 @@ class NonCachingLazyStorage<K, V>(
) : LazyStorage<K, V> {
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
@@ -43,7 +42,6 @@ class NonCachingLazyStorage<K, V>(
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
@@ -53,22 +51,28 @@ class NonCachingLazyStorage<K, V>(
}
override val keys: Collection<K>
@Synchronized
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
@Synchronized
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
@Synchronized
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
@Synchronized
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
@Synchronized
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
@Synchronized
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
}
@@ -100,7 +104,11 @@ class NonCachingLazyStorage<K, V>(
@Synchronized
override fun close() {
storage?.close()
try {
storage?.close()
} finally {
storage = null
}
}
private fun createMap(): PersistentHashMap<K, V> =

View File

@@ -1135,7 +1135,7 @@ fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
}
tasks.withType<KotlinCompile> {
kotlinOptions.jdkHome = javaHome
kotlinOptions.jdkHome = javaHome.takeUnless { kotlinBuildProperties.suppressJdkHomeWarning }
kotlinOptions.jvmTarget = javaVersion
kotlinOptions.freeCompilerArgs += "-Xjvm-default=compatibility"
}

View File

@@ -20,3 +20,5 @@ val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.bui
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
val KotlinBuildProperties.disableWerror: Boolean get() = getBoolean("kotlin.build.disable.werror", false)
val KotlinBuildProperties.suppressJdkHomeWarning: Boolean get() = getBoolean("kotlin.suppress.jdkHome.warning", false)

View File

@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.AnnotationChecker;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
import org.jetbrains.kotlin.types.FlexibleType;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
@@ -376,7 +376,7 @@ public abstract class AnnotationCodegen {
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
// (Otherwise we would've resolved the entry to the actual annotation class.)
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(classDescriptor)) {
if (OptionalAnnotationUtil.isOptionalAnnotationClass(classDescriptor)) {
return null;
}

View File

@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.lazy.descriptors.PackageDescriptorUtilKt;
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
import org.jetbrains.org.objectweb.asm.Type;
@@ -91,8 +91,8 @@ public class PackageCodegenImpl implements PackageCodegen {
if (declaration instanceof KtClassOrObject) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, declaration);
if (PsiUtilsKt.hasExpectModifier(declaration)) {
if (descriptor != null && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor)) {
assert ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor) :
if (descriptor != null && OptionalAnnotationUtil.shouldGenerateExpectClass(descriptor)) {
assert OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor) :
"Expect class should be generated only if it's an optional annotation: " + descriptor;
state.getFactory().getPackagePartRegistry().getOptionalAnnotations().add(descriptor);
}

View File

@@ -189,7 +189,7 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
Pair(it, typeArguments[candidateDescriptor.typeParameters[it.index]]!!.asTypeProjection())
}.toMap()
newCall.setResultingSubstitutor(
newCall.setSubstitutor(
TypeConstructorSubstitution.createByParametersMap(newTypeArguments).buildSubstitutor()
)

View File

@@ -19,14 +19,12 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.*
class StackPeepholeOptimizationsTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (transformOnce(methodNode)) {
while (true) {
if (!transformOnce(methodNode)) break
}
}
@@ -115,20 +113,26 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() {
opcode == Opcodes.DUP
private fun AbstractInsnNode.isPurePushOfSize1(): Boolean =
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance()
!isLdcOfSize2() && (
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance()
)
private fun AbstractInsnNode.isEliminatedByPop2() =
isPurePushOfSize2() ||
opcode == Opcodes.DUP2
private fun AbstractInsnNode.isPurePushOfSize2(): Boolean =
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
isLdcOfSize2() ||
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1 ||
opcode == Opcodes.LLOAD ||
opcode == Opcodes.DLOAD
private fun AbstractInsnNode.isLdcOfSize2(): Boolean =
opcode == Opcodes.LDC && this is LdcInsnNode && (this.cst is Double || this.cst is Long)
}

View File

@@ -29,4 +29,7 @@ class JvmCodegenStringTable @JvmOverloads constructor(
ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
}
}
override val isLocalClassIdReplacementKeptGeneric: Boolean
get() = true
}

View File

@@ -13,7 +13,6 @@ plugins {
dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
testApi(intellijDep())
testApi(projectTests(":compiler:test-infrastructure"))
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:tests-compiler-utils"))

View File

@@ -492,11 +492,11 @@ digraph nullability_kt {
176 [label="Access variable R|/Q.data|"];
177 [label="Access variable R|<local>/q|"];
178 [label="Access variable R|/Q.data|"];
179 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
179 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
180 [label="Access variable R|<local>/q|"];
181 [label="Access variable R|/Q.data|"];
182 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
183 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
182 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
183 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
184 [label="Exit block"];
}
185 [label="Exit when branch result"];
@@ -566,11 +566,11 @@ digraph nullability_kt {
208 [label="Access variable R|/Q.data|"];
209 [label="Access variable R|<local>/q|"];
210 [label="Access variable R|/Q.data|"];
211 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
211 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
212 [label="Access variable R|<local>/q|"];
213 [label="Access variable R|/Q.data|"];
214 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
215 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
214 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
215 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
216 [label="Exit block"];
}
217 [label="Exit function test_6" style="filled" fillcolor=red];
@@ -1280,11 +1280,11 @@ digraph nullability_kt {
490 [label="Access variable R|/QImplWithCustomGetter.data|"];
491 [label="Access variable R|<local>/q|"];
492 [label="Access variable R|/QImplWithCustomGetter.data|"];
493 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
493 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
494 [label="Access variable R|<local>/q|"];
495 [label="Access variable R|/QImplWithCustomGetter.data|"];
496 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
497 [label="Function call: R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
496 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
497 [label="Function call: R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
498 [label="Exit block"];
}
499 [label="Exit when branch result"];
@@ -1363,11 +1363,11 @@ digraph nullability_kt {
524 [label="Access variable R|/QImplMutable.data|"];
525 [label="Access variable R|<local>/q|"];
526 [label="Access variable R|/QImplMutable.data|"];
527 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
527 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
528 [label="Access variable R|<local>/q|"];
529 [label="Access variable R|/QImplMutable.data|"];
530 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
531 [label="Function call: R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
530 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
531 [label="Function call: R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
532 [label="Exit block"];
}
533 [label="Exit when branch result"];

View File

@@ -102,8 +102,8 @@ FILE: nullability.kt
when () {
!=(R|<local>/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
R|<local>/q|.R|/Q.data|
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
}
}
@@ -111,8 +111,8 @@ FILE: nullability.kt
public final fun test_6(q: R|Q?|): R|kotlin/Unit| {
R|<local>/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() } ?: ^test_6 Unit
R|<local>/q|.R|/Q.data|
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
}
public final fun test_7(q: R|Q?|): R|kotlin/Unit| {
when () {
@@ -216,8 +216,8 @@ FILE: nullability.kt
when () {
!=(R|<local>/q|?.{ $subj$.R|/QImplWithCustomGetter.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
R|<local>/q|.R|/QImplWithCustomGetter.data|
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
}
}
@@ -226,8 +226,8 @@ FILE: nullability.kt
when () {
!=(R|<local>/q|?.{ $subj$.R|/QImplMutable.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
R|<local>/q|.R|/QImplMutable.data|
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
}
}

View File

@@ -67,8 +67,8 @@ fun test_5(q: Q?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
}
}
@@ -76,8 +76,8 @@ fun test_6(q: Q?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
q?.data?.s?.inc() ?: return
q.data // good
q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
}
fun test_7(q: Q?) {
@@ -162,8 +162,8 @@ fun test_12(q: QImplWithCustomGetter?) {
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
}
}
@@ -171,7 +171,7 @@ fun test_13(q: QImplMutable?) {
// `q.data` is a property that is mutable, so we can NOT smartcast it to non-nullable MyData.
if (q?.data?.s?.inc() != null) {
q.data // good
q.data<!UNSAFE_CALL!>.<!>s // should be bad
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
}
}

View File

@@ -20,7 +20,7 @@ FILE: KtFirCompositeScope.kt
public final fun getAllNames(): R|kotlin/collections/Set<kotlin/String>| {
^getAllNames R|/withValidityAssertion|<R|kotlin/collections/Set<kotlin/String>|>(<L> = withValidityAssertion@fun <anonymous>(): R|kotlin/collections/Set<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
^ R|/buildSet|<R|kotlin/String|>(<L> = buildSet@fun R|kotlin/collections/MutableSet<kotlin/String>|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
this@R|/KtFirCompositeScope|.R|/KtFirCompositeScope.subScopes|.R|kotlin/collections/flatMapTo|<R|KtScope|, R|kotlin/String|, R|kotlin/collections/MutableCollection<in kotlin/String>|>(this@R|special/anonymous|, <L> = flatMapTo@fun <anonymous>(it: R|KtScope|): R|kotlin/collections/Iterable<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
this@R|/KtFirCompositeScope|.R|/KtFirCompositeScope.subScopes|.R|kotlin/collections/flatMapTo|<R|KtScope|, R|kotlin/String|, R|kotlin/collections/MutableSet<kotlin/String>|>(this@R|special/anonymous|, <L> = flatMapTo@fun <anonymous>(it: R|KtScope|): R|kotlin/collections/Iterable<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
^ R|<local>/it|.R|/KtScope.getAllNames|()
}
)

View File

@@ -990,9 +990,21 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
}
@Test
@TestMetadata("AnnotationForClassTypeParameter.kt")
public void testAnnotationForClassTypeParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter.kt");
@TestMetadata("AnnotationForClassTypeParameter_15.kt")
public void testAnnotationForClassTypeParameter_15() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_15.kt");
}
@Test
@TestMetadata("AnnotationForClassTypeParameter_16.kt")
public void testAnnotationForClassTypeParameter_16() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt");
}
@Test
@TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt")
public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt");
}
@Test
@@ -1343,6 +1355,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/annotations/RecursivelyIncorrectlyAnnotatedParameter.kt");
}
@Test
@TestMetadata("requireKotlin.kt")
public void testRequireKotlin() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/requireKotlin.kt");
}
@Test
@TestMetadata("RetentionsOfAnnotationWithExpressionTarget_after.kt")
public void testRetentionsOfAnnotationWithExpressionTarget_after() throws Exception {
@@ -12632,6 +12650,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("labaledCall.kt")
public void testLabaledCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/labaledCall.kt");
}
@Test
@TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt")
public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception {
@@ -12668,17 +12692,115 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorType.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesErrorTypeUnrestricted.kt")
public void testSpecialCallsWithCallableReferencesErrorTypeUnrestricted() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorTypeUnrestricted.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt")
public void testSpecialCallsWithCallableReferencesNonStrictOnlyInputTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesUnrestricted.kt")
public void testSpecialCallsWithCallableReferencesUnrestricted() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesUnrestricted.kt");
}
@Test
@TestMetadata("specialCallsWithLambdas.kt")
public void testSpecialCallsWithLambdas() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/constraints")
@TestDataPath("$PROJECT_ROOT")
public class Constraints {
@Test
public void testAllFilesPresentInConstraints() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/constraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("violating.kt")
public void testViolating() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/constraints/violating.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
@TestDataPath("$PROJECT_ROOT")
public class StubTypes {
@Test
public void testAllFilesPresentInStubTypes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("capturedTypes.kt")
public void testCapturedTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/capturedTypes.kt");
}
@Test
@TestMetadata("commonSuperType.kt")
public void testCommonSuperType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperType.kt");
}
@Test
@TestMetadata("commonSuperTypeContravariant.kt")
public void testCommonSuperTypeContravariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeContravariant.kt");
}
@Test
@TestMetadata("commonSuperTypeCovariant.kt")
public void testCommonSuperTypeCovariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeCovariant.kt");
}
@Test
@TestMetadata("commonSuperTypeInvariant.kt")
public void testCommonSuperTypeInvariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeInvariant.kt");
}
@Test
@TestMetadata("commonSuperTypeNullable.kt")
public void testCommonSuperTypeNullable() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeNullable.kt");
}
@Test
@TestMetadata("intersect.kt")
public void testIntersect() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/intersect.kt");
}
@Test
@TestMetadata("memberScope.kt")
public void testMemberScope() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/nullability.kt");
}
@Test
@TestMetadata("renderingStubTypes.kt")
public void testRenderingStubTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt");
}
}
}
@Nested
@@ -32230,6 +32352,48 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testCompleteIrrelevantCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt");
}
@Test
@TestMetadata("incorrectCalls.kt")
public void testIncorrectCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCalls.kt");
}
@Test
@TestMetadata("incorrectCallsWithRestrictions.kt")
public void testIncorrectCallsWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCallsWithRestrictions.kt");
}
@Test
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
public void testInferCoroutineTypeInOldVersion() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/inferCoroutineTypeInOldVersion.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
public void testResolveUsualCallWithBuilderInference() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInference.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInferenceWithRestrictions.kt")
public void testResolveUsualCallWithBuilderInferenceWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtension.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtensionWithRestrictions.kt")
public void testUseInferenceInformationFromExtensionWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtensionWithRestrictions.kt");
}
}
@Nested
@@ -33420,18 +33584,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionsWithNonValuableConstraints_1_2.kt");
}
@Test
@TestMetadata("incorrectCalls.kt")
public void testIncorrectCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/incorrectCalls.kt");
}
@Test
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
public void testInferCoroutineTypeInOldVersion() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/inferCoroutineTypeInOldVersion.kt");
}
@Test
@TestMetadata("inferenceFromMethodInsideLocalVariable.kt")
public void testInferenceFromMethodInsideLocalVariable() throws Exception {
@@ -33576,12 +33728,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
public void testResolveUsualCallWithBuilderInference() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/resolveUsualCallWithBuilderInference.kt");
}
@Test
@TestMetadata("returnTypeInference.kt")
public void testReturnTypeInference() throws Exception {
@@ -33630,12 +33776,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/useInferenceInformationFromExtension.kt");
}
@Test
@TestMetadata("variableCallInsideBuilderFunction.kt")
public void testVariableCallInsideBuilderFunction() throws Exception {

View File

@@ -990,9 +990,21 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
}
@Test
@TestMetadata("AnnotationForClassTypeParameter.kt")
public void testAnnotationForClassTypeParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter.kt");
@TestMetadata("AnnotationForClassTypeParameter_15.kt")
public void testAnnotationForClassTypeParameter_15() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_15.kt");
}
@Test
@TestMetadata("AnnotationForClassTypeParameter_16.kt")
public void testAnnotationForClassTypeParameter_16() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt");
}
@Test
@TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt")
public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt");
}
@Test
@@ -1343,6 +1355,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/annotations/RecursivelyIncorrectlyAnnotatedParameter.kt");
}
@Test
@TestMetadata("requireKotlin.kt")
public void testRequireKotlin() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/requireKotlin.kt");
}
@Test
@TestMetadata("RetentionsOfAnnotationWithExpressionTarget_after.kt")
public void testRetentionsOfAnnotationWithExpressionTarget_after() throws Exception {
@@ -12632,6 +12650,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("labaledCall.kt")
public void testLabaledCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/labaledCall.kt");
}
@Test
@TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt")
public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception {
@@ -12668,17 +12692,115 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorType.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesErrorTypeUnrestricted.kt")
public void testSpecialCallsWithCallableReferencesErrorTypeUnrestricted() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorTypeUnrestricted.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt")
public void testSpecialCallsWithCallableReferencesNonStrictOnlyInputTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesUnrestricted.kt")
public void testSpecialCallsWithCallableReferencesUnrestricted() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesUnrestricted.kt");
}
@Test
@TestMetadata("specialCallsWithLambdas.kt")
public void testSpecialCallsWithLambdas() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/constraints")
@TestDataPath("$PROJECT_ROOT")
public class Constraints {
@Test
public void testAllFilesPresentInConstraints() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/constraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("violating.kt")
public void testViolating() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/constraints/violating.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
@TestDataPath("$PROJECT_ROOT")
public class StubTypes {
@Test
public void testAllFilesPresentInStubTypes() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("capturedTypes.kt")
public void testCapturedTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/capturedTypes.kt");
}
@Test
@TestMetadata("commonSuperType.kt")
public void testCommonSuperType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperType.kt");
}
@Test
@TestMetadata("commonSuperTypeContravariant.kt")
public void testCommonSuperTypeContravariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeContravariant.kt");
}
@Test
@TestMetadata("commonSuperTypeCovariant.kt")
public void testCommonSuperTypeCovariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeCovariant.kt");
}
@Test
@TestMetadata("commonSuperTypeInvariant.kt")
public void testCommonSuperTypeInvariant() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeInvariant.kt");
}
@Test
@TestMetadata("commonSuperTypeNullable.kt")
public void testCommonSuperTypeNullable() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeNullable.kt");
}
@Test
@TestMetadata("intersect.kt")
public void testIntersect() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/intersect.kt");
}
@Test
@TestMetadata("memberScope.kt")
public void testMemberScope() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/nullability.kt");
}
@Test
@TestMetadata("renderingStubTypes.kt")
public void testRenderingStubTypes() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt");
}
}
}
@Nested
@@ -32230,6 +32352,48 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
public void testCompleteIrrelevantCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt");
}
@Test
@TestMetadata("incorrectCalls.kt")
public void testIncorrectCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCalls.kt");
}
@Test
@TestMetadata("incorrectCallsWithRestrictions.kt")
public void testIncorrectCallsWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCallsWithRestrictions.kt");
}
@Test
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
public void testInferCoroutineTypeInOldVersion() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/inferCoroutineTypeInOldVersion.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
public void testResolveUsualCallWithBuilderInference() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInference.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInferenceWithRestrictions.kt")
public void testResolveUsualCallWithBuilderInferenceWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtension.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtensionWithRestrictions.kt")
public void testUseInferenceInformationFromExtensionWithRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtensionWithRestrictions.kt");
}
}
@Nested
@@ -33420,18 +33584,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionsWithNonValuableConstraints_1_2.kt");
}
@Test
@TestMetadata("incorrectCalls.kt")
public void testIncorrectCalls() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/incorrectCalls.kt");
}
@Test
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
public void testInferCoroutineTypeInOldVersion() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/inferCoroutineTypeInOldVersion.kt");
}
@Test
@TestMetadata("inferenceFromMethodInsideLocalVariable.kt")
public void testInferenceFromMethodInsideLocalVariable() throws Exception {
@@ -33576,12 +33728,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt");
}
@Test
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
public void testResolveUsualCallWithBuilderInference() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/resolveUsualCallWithBuilderInference.kt");
}
@Test
@TestMetadata("returnTypeInference.kt")
public void testReturnTypeInference() throws Exception {
@@ -33630,12 +33776,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/useInferenceInformationFromExtension.kt");
}
@Test
@TestMetadata("variableCallInsideBuilderFunction.kt")
public void testVariableCallInsideBuilderFunction() throws Exception {

View File

@@ -465,6 +465,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<Variance>("variance")
parameter<ConeKotlinType>("containingType")
}
val SMARTCAST_IMPOSSIBLE by error<KtExpression> {
parameter<ConeKotlinType>("desiredType")
parameter<FirExpression>("subject")
parameter<String>("description")
}
}
val REFLECTION by object : DiagnosticGroup("Reflection") {

View File

@@ -303,6 +303,7 @@ object FirErrors {
val INCOMPATIBLE_TYPES_WARNING by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val TYPE_VARIANCE_CONFLICT by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val SMARTCAST_IMPOSSIBLE by error3<KtExpression, ConeKotlinType, FirExpression, String>()
// Reflection
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)

View File

@@ -156,30 +156,34 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
variableStorage: VariableStorage,
flow: Flow,
context: CheckerContext
): MutableTypeStatements? = when (this) {
is ConeBinaryLogicExpression -> {
val left = left.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
val right = right.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
if (left != null && right != null) {
if (kind == LogicOperationKind.AND) {
left.apply { mergeTypeStatements(right) }
} else logicSystem.orForTypeStatements(left, right)
} else (left ?: right)
}
is ConeIsInstancePredicate -> {
): MutableTypeStatements? {
fun buildTypeStatements(arg: ConeValueParameterReference, exactType: Boolean, type: ConeKotlinType): MutableTypeStatements? {
val fir = function.getParameterSymbol(arg.parameterIndex, context).fir
val realVar = variableStorage.getOrCreateRealVariable(flow, fir.symbol, fir)
realVar?.to(simpleTypeStatement(realVar, !isNegated, type))?.let { mutableMapOf(it) }
?.takeIf {
it.stability == PropertyStability.STABLE_VALUE ||
// TODO: consider removing the part below
it.stability == PropertyStability.LOCAL_VAR
}
return realVar?.to(simpleTypeStatement(realVar, exactType, type))?.let { mutableMapOf(it) }
}
is ConeIsNullPredicate -> {
val fir = function.getParameterSymbol(arg.parameterIndex, context).fir
val realVar = variableStorage.getOrCreateRealVariable(flow, fir.symbol, fir)
realVar?.to(simpleTypeStatement(realVar, isNegated, context.session.builtinTypes.anyType.type))?.let { mutableMapOf(it) }
}
is ConeLogicalNot -> arg.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
?.mapValuesTo(mutableMapOf()) { (_, value) -> value.invert() }
return when (this) {
is ConeBinaryLogicExpression -> {
val left = left.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
val right = right.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
if (left != null && right != null) {
if (kind == LogicOperationKind.AND) {
left.apply { mergeTypeStatements(right) }
} else logicSystem.orForTypeStatements(left, right)
} else (left ?: right)
}
is ConeIsInstancePredicate -> buildTypeStatements(arg, !isNegated, type)
is ConeIsNullPredicate -> buildTypeStatements(arg, isNegated, context.session.builtinTypes.anyType.type)
is ConeLogicalNot -> arg.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
?.mapValuesTo(mutableMapOf()) { (_, value) -> value.invert() }
else -> null
else -> null
}
}
private fun ConeKotlinType.isInapplicableWith(operation: Operation, session: FirSession): Boolean {

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
@@ -20,17 +21,18 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
private val versionArgumentName = Name.identifier("version")
private val deprecatedSinceKotlinFqName = FqName("kotlin.DeprecatedSinceKotlin")
private val sinceKotlinFqName = FqName("kotlin.SinceKotlin")
private val annotationFqNamesWithVersion = setOf(
FqName("kotlin.internal.RequireKotlin"),
RequireKotlinConstants.FQ_NAME,
sinceKotlinFqName,
deprecatedSinceKotlinFqName
)
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -38,10 +40,11 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
val fqName = expression.fqName(context.session)
for ((arg, _) in argumentMapping) {
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
checkAnnotationArgumentWithSubElements(argExpression, fqName, context.session, reporter, context)
checkAnnotationArgumentWithSubElements(argExpression, context.session, reporter, context)
?.let { reporter.reportOn(argExpression.source, it, context) }
}
checkAnnotationsWithVersion(fqName, expression, context, reporter)
checkDeprecatedSinceKotlin(expression.source, fqName, argumentMapping, context, reporter)
val args = expression.argumentList.arguments
@@ -54,7 +57,6 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
private fun checkAnnotationArgumentWithSubElements(
expression: FirExpression,
fqName: FqName?,
session: FirSession,
reporter: DiagnosticReporter,
context: CheckerContext
@@ -66,7 +68,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
for (arg in args.arguments) {
val sourceForReport = arg.source
when (val err = checkAnnotationArgumentWithSubElements(arg, fqName, session, reporter, context)) {
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter, context)) {
null -> {
//DO NOTHING
}
@@ -86,12 +88,12 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
is FirVarargArgumentsExpression -> {
for (arg in expression.arguments) {
val unwrappedArg = if (arg is FirSpreadArgumentExpression) arg.expression else arg
checkAnnotationArgumentWithSubElements(unwrappedArg, fqName, session, reporter, context)
checkAnnotationArgumentWithSubElements(unwrappedArg, session, reporter, context)
?.let { reporter.reportOn(unwrappedArg.source, it, context) }
}
}
else -> {
val error = when (checkConstantArguments(expression, session)) {
return when (checkConstantArguments(expression, session)) {
ConstantArgumentKind.NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
ConstantArgumentKind.ENUM_NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
ConstantArgumentKind.NOT_KCLASS_LITERAL -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
@@ -103,33 +105,47 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
if (expression is FirFunctionCall) checkArgumentList(expression.argumentList)
else null
}
if (error != null) {
return error
} else if (annotationFqNamesWithVersion.contains(fqName)) {
val argSource = expression.source
if (argSource != null) {
val stringValue = (expression as? FirConstExpression<*>)?.value as? String
if (stringValue != null) {
if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) {
reporter.reportOn(argSource, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
} else if (fqName == sinceKotlinFqName) {
val version = ApiVersion.parse(stringValue)
val specified = context.session.languageVersionSettings.apiVersion
if (version != null && version > specified) {
reporter.report(
FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.on(argSource, specified.versionString),
context
)
}
}
}
}
}
}
}
return null
}
private fun parseVersionExpressionOrReport(
expression: FirExpression,
context: CheckerContext,
reporter: DiagnosticReporter
): ApiVersion? {
val constantExpression = (expression as? FirConstExpression<*>)
?: ((expression as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>) ?: return null
val stringValue = constantExpression.value as? String ?: return null
if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) {
reporter.reportOn(expression.source, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
return null
}
val version = ApiVersion.parse(stringValue)
if (version == null) {
reporter.reportOn(expression.source, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
}
return version
}
private fun checkAnnotationsWithVersion(
fqName: FqName?,
annotationCall: FirAnnotationCall,
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (!annotationFqNamesWithVersion.contains(fqName)) return
val versionExpression = annotationCall.findSingleArgumentByName(versionArgumentName) ?: return
val version = parseVersionExpressionOrReport(versionExpression, context, reporter) ?: return
if (fqName == sinceKotlinFqName) {
val specified = context.session.languageVersionSettings.apiVersion
if (version > specified) {
reporter.reportOn(versionExpression.source, FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN, specified.versionString, context)
}
}
}
private fun checkDeprecatedSinceKotlin(
source: FirSourceElement?,
fqName: FqName?,
@@ -150,12 +166,8 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
for (argument in argumentMapping) {
val identifier = argument.value.name.identifier
if (identifier == "warningSince" || identifier == "errorSince" || identifier == "hiddenSince") {
val argKey = argument.key
val constExpression = (argKey as? FirConstExpression<*>)
?: ((argKey as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
val stringValue = constExpression?.value as? String
if (stringValue != null) {
val version = ApiVersion.parse(stringValue)
val version = parseVersionExpressionOrReport(argument.key, context, reporter)
if (version != null) {
when (identifier) {
"warningSince" -> warningSince = version
"errorSince" -> errorSince = version

View File

@@ -10,13 +10,16 @@ import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULL_FOR_NONNULL_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.isExhaustive
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.SmartcastStability
object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -36,10 +39,23 @@ object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
if (resultExpression.isNullLiteral && functionReturnType.nullability == ConeNullability.NOT_NULL) {
reporter.reportOn(resultExpression.source, NULL_FOR_NONNULL_TYPE, context)
} else {
reporter.report(
RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType, targetElement),
context
)
if (resultExpression is FirExpressionWithSmartcast && resultExpression.smartcastStability != SmartcastStability.STABLE_VALUE &&
isSubtypeForTypeMismatch(typeContext, subtype = resultExpression.smartcastType.coneType, supertype = functionReturnType)
) {
reporter.reportOn(
returnExpressionSource,
SMARTCAST_IMPOSSIBLE,
functionReturnType,
resultExpression,
resultExpression.smartcastStability.description,
context
)
} else {
reporter.report(
RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType, targetElement),
context
)
}
}
}
}

View File

@@ -273,6 +273,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLETON_IN_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_APPEARS_TWICE
@@ -634,6 +635,13 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE, "Extension function type can not be used as an upper bound")
map.put(INCOMPATIBLE_TYPES, "Incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE)
map.put(INCOMPATIBLE_TYPES_WARNING, "Potentially incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE)
map.put(
SMARTCAST_IMPOSSIBLE,
"Smart cast to ''{0}'' is impossible, because ''{1}'' is a {2}",
RENDER_TYPE,
FIR,
TO_STRING
)
map.put(
TYPE_VARIANCE_CONFLICT,

View File

@@ -46,6 +46,15 @@ private fun ConeDiagnostic.toFirDiagnostic(
val candidate = candidates.first { it.currentApplicability == CandidateApplicability.UNSAFE_CALL }
val unsafeCall = candidate.diagnostics.firstIsInstance<UnsafeCall>()
mapUnsafeCallError(candidate, unsafeCall, source, qualifiedAccessSource)
} else if (this.applicability == CandidateApplicability.UNSTABLE_SMARTCAST) {
val unstableSmartcast =
this.candidates.first { it.currentApplicability == CandidateApplicability.UNSTABLE_SMARTCAST }.diagnostics.firstIsInstance<UnstableSmartCast>()
FirErrors.SMARTCAST_IMPOSSIBLE.on(
unstableSmartcast.argument.source,
unstableSmartcast.targetType,
unstableSmartcast.argument,
unstableSmartcast.argument.smartcastStability.description
)
} else {
FirErrors.NONE_APPLICABLE.on(source, this.candidates.map { it.symbol })
}
@@ -134,8 +143,8 @@ private fun mapInapplicableCandidateError(
source: FirSourceElement,
qualifiedAccessSource: FirSourceElement?,
): List<FirDiagnostic<FirSourceElement>> {
// TODO: Need to distinguish SMARTCAST_IMPOSSIBLE
return diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)
val diagnostics = diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
when (rootCause) {
is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on(
rootCause.argument.source ?: qualifiedAccessSource
@@ -166,9 +175,21 @@ private fun mapInapplicableCandidateError(
is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.on(source, rootCause.function)
is OperatorCallOfNonOperatorFunction ->
FirErrors.OPERATOR_MODIFIER_REQUIRED.on(source, rootCause.function, rootCause.function.fir.name.asString())
else -> null
is UnstableSmartCast -> FirErrors.SMARTCAST_IMPOSSIBLE.on(
rootCause.argument.source,
rootCause.targetType,
rootCause.argument,
rootCause.argument.smartcastStability.description
)
else -> genericDiagnostic
}
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
}.distinct()
return if (diagnostics.size > 1) {
// If there are more specific diagnostics, filter out the generic diagnostic.
diagnostics.filter { it != genericDiagnostic }
} else {
diagnostics
}
}
@OptIn(ExperimentalStdlibApi::class)

View File

@@ -17,10 +17,6 @@ dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testCompileOnly(intellijDep())
testRuntimeOnly(intellijDep())
testCompileOnly(project(":kotlin-test:kotlin-test-jvm"))
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
testApi(projectTests(":compiler:test-infrastructure"))
@@ -39,6 +35,33 @@ dependencies {
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
testRuntimeOnly(intellijDep()) {
includeJars(
"jps-model",
"extensions",
"util",
"platform-api",
"platform-impl",
"idea",
"guava",
"trove4j",
"asm-all",
"log4j",
"jdom",
"streamex",
"bootstrap",
"jna",
rootProject = rootProject
)
}
Platform[202] {
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-1") }
}
Platform[203].orHigher {
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-3") }
}
}
val generationRoot = projectDir.resolve("tests-gen")

View File

@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.SmartcastStability
class Fir2IrImplicitCastInserter(
private val components: Fir2IrComponents,
@@ -274,7 +275,11 @@ class Fir2IrImplicitCastInserter(
}
override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: IrElement): IrExpression {
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
return if (expressionWithSmartcast.smartcastStability == SmartcastStability.STABLE_VALUE) {
implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
} else {
data as IrExpression
}
}
override fun visitExpressionWithSmartcastToNull(

View File

@@ -2446,6 +2446,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("arrayConstructor.kt")
public void testArrayConstructor() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/arrayConstructor.kt");
}
@Test
@TestMetadata("arrayConstructorArgument.kt")
public void testArrayConstructorArgument() throws Exception {
@@ -15282,6 +15288,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/extensionProperties/inClassWithSetter.kt");
}
@Test
@TestMetadata("kt46952.kt")
public void testKt46952() throws Exception {
runTest("compiler/testData/codegen/box/extensionProperties/kt46952.kt");
}
@Test
@TestMetadata("kt9897.kt")
public void testKt9897() throws Exception {
@@ -17587,18 +17599,78 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/builderInference/callableReferencesProperCompletion.kt");
}
@Test
@TestMetadata("capturedTypes.kt")
public void testCapturedTypes() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/capturedTypes.kt");
}
@Test
@TestMetadata("commonSuperType.kt")
public void testCommonSuperType() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperType.kt");
}
@Test
@TestMetadata("commonSuperTypeContravariant.kt")
public void testCommonSuperTypeContravariant() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeContravariant.kt");
}
@Test
@TestMetadata("commonSuperTypeCovariant.kt")
public void testCommonSuperTypeCovariant() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeCovariant.kt");
}
@Test
@TestMetadata("commonSuperTypeInvariant.kt")
public void testCommonSuperTypeInvariant() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeInvariant.kt");
}
@Test
@TestMetadata("commonSuperTypeNullable.kt")
public void testCommonSuperTypeNullable() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeNullable.kt");
}
@Test
@TestMetadata("intersect.kt")
public void testIntersect() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/intersect.kt");
}
@Test
@TestMetadata("kt41164.kt")
public void testKt41164() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/kt41164.kt");
}
@Test
@TestMetadata("labaledCall.kt")
public void testLabaledCall() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/labaledCall.kt");
}
@Test
@TestMetadata("lackOfNullCheckOnNullableInsideBuild.kt")
public void testLackOfNullCheckOnNullableInsideBuild() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
}
@Test
@TestMetadata("memberScope.kt")
public void testMemberScope() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/memberScope.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/nullability.kt");
}
@Test
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
@@ -17617,6 +17689,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontCareTypeInBlockExpression.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesDontCareTypeInBlockExression.kt")
public void testSpecialCallsWithCallableReferencesDontCareTypeInBlockExression() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontCareTypeInBlockExression.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesDontRewriteAtSlice.kt")
public void testSpecialCallsWithCallableReferencesDontRewriteAtSlice() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontRewriteAtSlice.kt");
}
@Test
@TestMetadata("specialCallsWithCallableReferencesErrorType.kt")
public void testSpecialCallsWithCallableReferencesErrorType() throws Exception {
@@ -17682,6 +17766,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testTopDownCompletionWithTwoBuilderInferenceCalls() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/topDownCompletionWithTwoBuilderInferenceCalls.kt");
}
@Test
@TestMetadata("withExpectedType.kt")
public void testWithExpectedType() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/withExpectedType.kt");
}
}
}
@@ -21133,6 +21223,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt");
}
@Test
@TestMetadata("inlineOnly.kt")
public void testInlineOnly() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt");
}
@Test
@TestMetadata("insideInitBlock.kt")
public void testInsideInitBlock() throws Exception {
@@ -27908,6 +28004,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/primitiveTypes/kt446.kt");
}
@Test
@TestMetadata("kt46864_double.kt")
public void testKt46864_double() throws Exception {
runTest("compiler/testData/codegen/box/primitiveTypes/kt46864_double.kt");
}
@Test
@TestMetadata("kt46864_long.kt")
public void testKt46864_long() throws Exception {
runTest("compiler/testData/codegen/box/primitiveTypes/kt46864_long.kt");
}
@Test
@TestMetadata("kt518.kt")
public void testKt518() throws Exception {
@@ -40552,6 +40660,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testKt46578_propertyRef() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedJavaFieldAccessor/kt46578_propertyRef.kt");
}
@Test
@TestMetadata("kt46900_jkk_inheritance.kt")
public void testKt46900_jkk_inheritance() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedJavaFieldAccessor/kt46900_jkk_inheritance.kt");
}
}
@Nested

View File

@@ -131,7 +131,7 @@ class JvmMappedScope(
// NOTE: No-arg constructors
@OptIn(ExperimentalStdlibApi::class)
private val additionalHiddenConstructors = buildSet {
private val additionalHiddenConstructors = buildSet<String> {
// kotlin.text.String pseudo-constructors should be used instead of java.lang.String constructors
listOf(
"",

View File

@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -23,12 +26,12 @@ import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.providers.*
import org.jetbrains.kotlin.fir.resolve.providers.getSymbolByTypeRef
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -36,6 +39,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
import org.jetbrains.kotlin.types.SmartcastStability
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
asReversed().flatMap { it.typeArgumentList.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
@@ -246,7 +250,8 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
qualifiedAccessExpression: FirQualifiedAccessExpression
): FirQualifiedAccessExpression {
val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression
val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression)
?: return qualifiedAccessExpression
val originalType = qualifiedAccessExpression.resultType.coneType
// For example, if (x == null) { ... },
// we don't want to smartcast to Nothing?, but we want to record the nullability to its own kind of node.
@@ -267,9 +272,11 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
return buildExpressionWithSmartcastToNull {
originalExpression = qualifiedAccessExpression
// TODO: Use Nothing? during resolution?
typeRef = intersectedTypeRefWithoutNullableNothing
smartcastType = intersectedTypeRefWithoutNullableNothing
// NB: Nothing? in types from smartcast in DFA is recorded here (and the expression kind itself).
this.typesFromSmartCast = typesFromSmartCast
// TODO: differentiate capture local variable
this.smartcastStability = stability.impliedSmartcastStability ?: SmartcastStability.STABLE_VALUE
}
}
val allTypes = typesFromSmartCast.also {
@@ -285,8 +292,10 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
}
return buildExpressionWithSmartcast {
originalExpression = qualifiedAccessExpression
typeRef = intersectedTypeRef
smartcastType = intersectedTypeRef
this.typesFromSmartCast = typesFromSmartCast
// TODO: differentiate capture local variable
this.smartcastStability = stability.impliedSmartcastStability ?: SmartcastStability.STABLE_VALUE
}
}

View File

@@ -10,9 +10,11 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
@@ -25,6 +27,25 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.SmartcastStability
fun FirExpressionWithSmartcast.smartcastScope(
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirTypeScope? {
val smartcastType = smartcastType.coneType
val smartcastScope = smartcastType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
if (smartcastStability == SmartcastStability.STABLE_VALUE) {
return smartcastScope
}
val originalScope = originalType.coneType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
?: return smartcastScope
if (smartcastScope == null) {
return originalScope
}
return FirUnstableSmartcastTypeScope(smartcastType, smartcastScope, originalScope)
}
fun ConeKotlinType.scope(
useSiteSession: FirSession,

View File

@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.SmartcastStability
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.model.TypeSystemCommonSuperTypesContext
import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -358,17 +358,7 @@ private fun checkApplicabilityForArgumentType(
) {
if (expectedType == null) return
fun unstableSmartCastOrSubtypeError(
unstableType: ConeKotlinType?,
actualExpectedType: ConeKotlinType,
position: ConstraintPosition
): ResolutionDiagnostic {
if (unstableType != null) {
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, actualExpectedType, position)) {
return UnstableSmartCast.ResolutionError(argument, unstableType)
}
}
fun subtypeError(actualExpectedType: ConeKotlinType): ResolutionDiagnostic {
if (argument.isNullLiteral && actualExpectedType.nullability == ConeNullability.NOT_NULL) {
return NullForNotNullType(argument)
}
@@ -406,14 +396,17 @@ private fun checkApplicabilityForArgumentType(
}
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
val smartcastExpression = argument as? FirExpressionWithSmartcast
if (smartcastExpression != null && smartcastExpression.smartcastStability != SmartcastStability.STABLE_VALUE) {
val unstableType = smartcastExpression.smartcastType.coneType
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
sink.reportDiagnostic(UnstableSmartCast(smartcastExpression, expectedType))
return
}
}
if (!isReceiver) {
sink.reportDiagnosticIfNotNull(
unstableSmartCastOrSubtypeError(
unstableType = null, // TODO: handle unstable smartcasts
expectedType,
position
)
)
sink.reportDiagnosticIfNotNull(subtypeError(expectedType))
return
}

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.builder.buildThisReceiverExpression
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.smartcastScope
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
@@ -27,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.types.SmartcastStability
interface Receiver
@@ -56,7 +59,11 @@ abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplic
class ExpressionReceiverValue(
override val explicitReceiver: FirExpression
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue {
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
(receiverExpression as? FirExpressionWithSmartcast)?.smartcastScope(useSiteSession, scopeSession)
?: type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
}
sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
val boundSymbol: S,
@@ -89,8 +96,9 @@ sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
} else {
buildExpressionWithSmartcast {
originalExpression = originalReceiverExpression
typeRef = originalReceiverExpression.typeRef.resolvedTypeFromPrototype(type)
smartcastType = originalReceiverExpression.typeRef.resolvedTypeFromPrototype(type)
typesFromSmartCast = listOf(type)
smartcastStability = SmartcastStability.STABLE_VALUE
}
}
implicitScope = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -74,21 +75,7 @@ object LowerPriorityToPreserveCompatibilityDiagnostic : ResolutionDiagnostic(RES
object CandidateChosenUsingOverloadResolutionByLambdaAnnotation : ResolutionDiagnostic(RESOLVED)
sealed class UnstableSmartCast(
val argument: FirExpression,
val targetType: ConeKotlinType,
applicability: CandidateApplicability
) : ResolutionDiagnostic(applicability) {
class ResolutionError(
argument: FirExpression,
targetType: ConeKotlinType,
) : UnstableSmartCast(argument, targetType, MAY_THROW_RUNTIME_ERROR)
class DiagnosticError(
argument: FirExpression,
targetType: ConeKotlinType,
) : UnstableSmartCast(argument, targetType, RESOLVED_WITH_ERROR)
}
class UnstableSmartCast(val argument: FirExpressionWithSmartcast, val targetType: ConeKotlinType) : ResolutionDiagnostic(UNSTABLE_SMARTCAST)
class ArgumentTypeMismatch(
val expectedType: ConeKotlinType,

View File

@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.SmartcastStability
abstract class ResolutionStage {
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
@@ -105,6 +107,19 @@ object CheckDispatchReceiver : ResolutionStage() {
}
}
if (explicitReceiverExpression is FirExpressionWithSmartcast && explicitReceiverExpression.smartcastStability != SmartcastStability.STABLE_VALUE) {
val expectedDispatchReceiverType = (candidate.symbol.fir as? FirCallableMemberDeclaration)?.dispatchReceiverType
if (expectedDispatchReceiverType != null &&
!AbstractTypeChecker.isSubtypeOf(
context.session.typeContext,
explicitReceiverExpression.originalType.coneType,
expectedDispatchReceiverType
)
) {
sink.yieldDiagnostic(UnstableSmartCast(explicitReceiverExpression, expectedDispatchReceiverType))
}
}
val dispatchReceiverValueType = candidate.dispatchReceiverValue?.type ?: return
if (!AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType)) {

View File

@@ -16,24 +16,27 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.buildContractFir
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.createArgumentsMapping
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -159,7 +162,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
// ----------------------------------- Requests -----------------------------------
fun getTypeUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): MutableList<ConeKotlinType>? {
fun getTypeUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): Pair<PropertyStability, MutableList<ConeKotlinType>>? {
/*
* DataFlowAnalyzer holds variables only for declarations that have some smartcast (or can have)
* If there is no useful information there is no data flow variable also
@@ -167,13 +170,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val symbol: AbstractFirBasedSymbol<*> = qualifiedAccessExpression.symbol ?: return null
val flow = graphBuilder.lastNode.flow
var variable = variableStorage.getRealVariableWithoutUnwrappingAlias(symbol, qualifiedAccessExpression, flow) ?: return null
val stability = variable.stability
val result = mutableListOf<ConeKotlinType>()
flow.directAliasMap[variable]?.let {
result.addIfNotNull(it.originalType)
variable = it.variable
}
flow.getTypeStatement(variable)?.exactType?.let { result += it }
return result.takeIf { it.isNotEmpty() }
return result.takeIf { it.isNotEmpty() }?.let { stability to it }
}
fun returnExpressionsOfAnonymousFunction(function: FirAnonymousFunction): Collection<FirStatement> {
@@ -441,7 +445,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
// expression == const -> expression != null
flow.addImplication((expressionVariable eq isEq) implies (operandVariable notEq null))
if (operandVariable is RealVariable) {
if (operandVariable.isReal()) {
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeEq any))
}
@@ -820,7 +824,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
?: return@let
val variable = variableStorage.getOrCreateVariable(flow, receiver)
if (variable is RealVariable) {
if (variable.isReal()) {
if (shouldFork) {
flow = logicSystem.forkFlow(flow)
}
@@ -1006,7 +1010,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
assignment: FirVariableAssignment?
) {
val flow = node.flow
val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias(flow, property.symbol, assignment ?: property)
val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias(
flow,
property.symbol,
assignment ?: property,
if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR
)
val isAssignment = assignment != null
if (isAssignment) {
logicSystem.removeLocalVariableAlias(flow, propertyVariable)
@@ -1014,13 +1023,21 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex())
}
variableStorage.getOrCreateRealVariable(flow, initializer.symbol, initializer)?.let { initializerVariable ->
logicSystem.addLocalVariableAlias(
flow, propertyVariable,
RealVariableAndType(initializerVariable, initializer.coneType)
)
// node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
}
variableStorage.getOrCreateRealVariable(flow, initializer.symbol, initializer)
?.let { initializerVariable ->
// TODO: handle capture variable
if ((initializerVariable.stability == PropertyStability.STABLE_VALUE || initializerVariable.stability == PropertyStability.LOCAL_VAR) &&
(propertyVariable.stability == PropertyStability.STABLE_VALUE || propertyVariable.stability == PropertyStability.LOCAL_VAR)
) {
logicSystem.addLocalVariableAlias(
flow, propertyVariable,
RealVariableAndType(initializerVariable, initializer.coneType)
)
// node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
} else {
logicSystem.replaceVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
}
}
variableStorage.getSyntheticVariable(initializer)?.let { initializerVariable ->
/*

View File

@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.fir.resolve.dfa
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.fir.expressions.*
@@ -34,14 +36,24 @@ class VariableStorage(private val session: FirSession) {
fun clear(): VariableStorage = VariableStorage(session)
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
fun getOrCreateRealVariableWithoutUnwrappingAlias(
flow: Flow,
symbol: AbstractFirBasedSymbol<*>,
fir: FirElement,
stability: PropertyStability
): RealVariable {
val realFir = fir.unwrapElement()
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir, stability) }
}
private fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
val variable = getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir)
private fun getOrCreateRealVariable(
flow: Flow,
symbol: AbstractFirBasedSymbol<*>,
fir: FirElement,
stability: PropertyStability
): RealVariable {
val variable = getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir, stability)
return flow.directAliasMap[variable]?.variable ?: variable
}
@@ -69,7 +81,12 @@ class VariableStorage(private val session: FirSession) {
/**
* [originalFir] used for extracting expression under <when_subject> and extracting receiver
*/
private fun createRealVariableInternal(flow: Flow, identifier: Identifier, originalFir: FirElement): RealVariable {
private fun createRealVariableInternal(
flow: Flow,
identifier: Identifier,
originalFir: FirElement,
stability: PropertyStability
): RealVariable {
val receiver: FirExpression?
val isThisReference: Boolean
val expression: FirQualifiedAccess? = when (originalFir) {
@@ -88,12 +105,12 @@ class VariableStorage(private val session: FirSession) {
}
val receiverVariable = receiver?.let { getOrCreateVariable(flow, it) }
return RealVariable(identifier, isThisReference, receiverVariable, counter++)
return RealVariable(identifier, isThisReference, receiverVariable, counter++, stability)
}
@JvmName("getOrCreateRealVariableOrNull")
fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>?, fir: FirElement): RealVariable? =
symbol.takeIf { it.isStable(fir) }?.let { getOrCreateRealVariable(flow, it, fir) }
symbol.getStability(fir)?.let { getOrCreateRealVariable(flow, symbol!!, fir, it) }
fun createSyntheticVariable(fir: FirElement): SyntheticVariable =
SyntheticVariable(fir, counter++).also { syntheticVariables[fir] = it }
@@ -101,8 +118,9 @@ class VariableStorage(private val session: FirSession) {
fun getOrCreateVariable(flow: Flow, fir: FirElement): DataFlowVariable {
val realFir = fir.unwrapElement()
val symbol = realFir.symbol
return if (symbol.isStable(realFir)) {
getOrCreateRealVariable(flow, symbol!!, realFir)
val stability = symbol.getStability(realFir)
return if (stability != null) {
getOrCreateRealVariable(flow, symbol!!, realFir, stability)
} else {
syntheticVariables[realFir] ?: createSyntheticVariable(realFir)
}
@@ -110,7 +128,7 @@ class VariableStorage(private val session: FirSession) {
fun getRealVariableWithoutUnwrappingAlias(symbol: AbstractFirBasedSymbol<*>?, fir: FirElement, flow: Flow): RealVariable? {
val realFir = fir.unwrapElement()
return symbol.takeIf { it.isStable(realFir) }?.let {
return symbol.takeIf { it.getStability(realFir) != null }?.let {
_realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
}
}
@@ -126,7 +144,8 @@ class VariableStorage(private val session: FirSession) {
fun getVariable(fir: FirElement, flow: Flow): DataFlowVariable? {
val realFir = fir.unwrapElement()
val symbol = realFir.symbol
return if (symbol.isStable(fir)) {
val stability = symbol.getStability(fir)
return if (stability != null) {
getRealVariable(symbol, realFir, flow)
} else {
getSyntheticVariable(fir)
@@ -138,44 +157,45 @@ class VariableStorage(private val session: FirSession) {
}
fun removeSyntheticVariable(variable: DataFlowVariable) {
if (variable !is SyntheticVariable) return
if (!variable.isSynthetic()) return
syntheticVariables.remove(variable.fir)
}
@OptIn(ExperimentalContracts::class)
fun AbstractFirBasedSymbol<*>?.isStable(originalFir: FirElement): Boolean {
fun AbstractFirBasedSymbol<*>?.getStability(originalFir: FirElement): PropertyStability? {
contract {
returns(true) implies(this@isStable != null)
returnsNotNull() implies (this@getStability != null)
}
when (this) {
is FirAnonymousObjectSymbol -> return false
is FirAnonymousObjectSymbol -> return null
is FirFunctionSymbol<*>,
is FirClassSymbol<*>,
is FirBackingFieldSymbol -> return true
null -> return false
is FirBackingFieldSymbol -> return PropertyStability.STABLE_VALUE
null -> return null
}
if (originalFir is FirThisReceiverExpression) return true
if (this !is FirVariableSymbol<*>) return false
if (originalFir is FirThisReceiverExpression) return PropertyStability.STABLE_VALUE
if (this !is FirVariableSymbol<*>) return null
val property = this.fir as? FirProperty ?: return true
val property = this.fir as? FirProperty ?: return PropertyStability.STABLE_VALUE
return when {
property.isLocal -> true
property.isVar -> false
property.receiverTypeRef != null -> false
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> false
property.delegate != null -> PropertyStability.DELEGATED_PROPERTY
property.isLocal -> if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR
property.isVar -> PropertyStability.MUTABLE_PROPERTY
property.receiverTypeRef != null -> PropertyStability.PROPERTY_WITH_GETTER
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER
property.moduleData.session != session -> PropertyStability.ALIEN_PUBLIC_PROPERTY
property.modality != Modality.FINAL -> {
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return false
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return false
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return false
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return null
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
when (val receiverFir = receiverSymbol.fir) {
is org.jetbrains.kotlin.fir.declarations.FirAnonymousObject -> true
is org.jetbrains.kotlin.fir.declarations.FirRegularClass -> receiverFir.modality == Modality.FINAL
is FirAnonymousObject -> PropertyStability.STABLE_VALUE
is FirRegularClass -> if (receiverFir.modality == Modality.FINAL) PropertyStability.STABLE_VALUE else PropertyStability.PROPERTY_WITH_GETTER
else -> throw IllegalStateException("Should not be here: $receiverFir")
}
}
else -> true
else -> PropertyStability.STABLE_VALUE
}
}
}

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.types.SmartcastStability
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@@ -33,11 +34,37 @@ sealed class DataFlowVariable(private val variableIndexForDebug: Int) {
}
}
enum class PropertyStability(val impliedSmartcastStability: SmartcastStability?) {
// Immutable and no custom getter or local.
// Smartcast is definitely safe regardless of usage.
STABLE_VALUE(SmartcastStability.STABLE_VALUE),
// Open or custom getter.
// Smartcast is always unsafe regardless of usage.
PROPERTY_WITH_GETTER(SmartcastStability.PROPERTY_WITH_GETTER),
// Protected / public member value from another module.
// Smartcast is always unsafe regardless of usage.
ALIEN_PUBLIC_PROPERTY(SmartcastStability.ALIEN_PUBLIC_PROPERTY),
// Smartcast may or may not be safe, depending on whether there are concurrent writes to this local variable.
LOCAL_VAR(null),
// Mutable member property of a class or object.
// Smartcast is always unsafe regardless of usage.
MUTABLE_PROPERTY(SmartcastStability.MUTABLE_PROPERTY),
// Delegated property of a class or object.
// Smartcast is always unsafe regardless of usage.
DELEGATED_PROPERTY(SmartcastStability.DELEGATED_PROPERTY),
}
class RealVariable(
val identifier: Identifier,
val isThisReference: Boolean,
val explicitReceiverVariable: DataFlowVariable?,
variableIndexForDebug: Int
variableIndexForDebug: Int,
val stability: PropertyStability,
) : DataFlowVariable(variableIndexForDebug) {
override fun equals(other: Any?): Boolean {
return this === other

View File

@@ -63,7 +63,7 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
val checkers = buildList {
exhaustivenessCheckers.filterTo(this) { it.isApplicable(cleanSubjectType, session) }
if (isNotEmpty() && cleanSubjectType.isMarkedNullable) {
if (isNotEmpty<WhenExhaustivenessChecker>() && cleanSubjectType.isMarkedNullable) {
add(WhenOnNullableExhaustivenessChecker)
}
}

View File

@@ -251,11 +251,15 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
)
}
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
override fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker {
require(typeVariable is ConeTypeVariable) { "$typeVariable should subtype of ${ConeTypeVariable::class.qualifiedName}" }
return ConeStubType(typeVariable, ConeNullability.create(typeVariable.defaultType().isMarkedNullable()))
}
// TODO
override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker) =
createStubTypeForBuilderInference(typeVariable)
override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker {
require(this is ConeKotlinType)
return withAttributes(ConeAttributes.Empty, this@ConeInferenceContext)

View File

@@ -380,7 +380,15 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
override fun SimpleTypeMarker.isStubType(): Boolean {
return this is StubTypeMarker
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
}
override fun SimpleTypeMarker.isStubTypeForVariableInSubtyping(): Boolean {
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
}
override fun SimpleTypeMarker.isStubTypeForBuilderInference(): Boolean {
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
}
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.SmartcastStability
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
@@ -31,6 +32,8 @@ abstract class FirExpressionWithSmartcast : FirQualifiedAccessExpression() {
abstract val originalExpression: FirQualifiedAccessExpression
abstract val typesFromSmartCast: Collection<ConeKotlinType>
abstract val originalType: FirTypeRef
abstract val smartcastType: FirTypeRef
abstract val smartcastStability: SmartcastStability
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcast(this, data)

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.SmartcastStability
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
@@ -31,6 +32,8 @@ abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
abstract override val originalExpression: FirQualifiedAccessExpression
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
abstract override val originalType: FirTypeRef
abstract override val smartcastType: FirTypeRef
abstract override val smartcastStability: SmartcastStability
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data)

View File

@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.SmartcastStability
class FirExpressionWithSmartcastBuilder {
lateinit var originalExpression: FirQualifiedAccessExpression
lateinit var typeRef: FirTypeRef
lateinit var smartcastType: FirTypeRef
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
lateinit var smartcastStability: SmartcastStability
fun build(): FirExpressionWithSmartcast {
return FirExpressionWithSmartcastImpl(originalExpression, typeRef, typesFromSmartCast)
return FirExpressionWithSmartcastImpl(originalExpression, smartcastType, typesFromSmartCast, smartcastStability)
}
}

View File

@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastToNullImpl
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.SmartcastStability
class FirExpressionWithSmartcastToNullBuilder {
lateinit var originalExpression: FirQualifiedAccessExpression
lateinit var typeRef: FirTypeRef
lateinit var smartcastType: FirTypeRef
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
lateinit var smartcastStability: SmartcastStability
fun build(): FirExpressionWithSmartcastToNull {
return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast)
return FirExpressionWithSmartcastToNullImpl(originalExpression, smartcastType, typesFromSmartCast, smartcastStability)
}
}

View File

@@ -19,11 +19,13 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.types.SmartcastStability
internal class FirExpressionWithSmartcastImpl(
override var originalExpression: FirQualifiedAccessExpression,
override val typeRef: FirTypeRef,
override val typesFromSmartCast: Collection<ConeKotlinType>
override val smartcastType: FirTypeRef,
override val typesFromSmartCast: Collection<ConeKotlinType>,
override val smartcastStability: SmartcastStability
) : FirExpressionWithSmartcast() {
init {
assert(originalExpression.typeRef is FirResolvedTypeRef)
@@ -37,6 +39,10 @@ internal class FirExpressionWithSmartcastImpl(
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
override val calleeReference: FirReference get() = originalExpression.calleeReference
override val originalType: FirTypeRef get() = originalExpression.typeRef
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
// purpose only.
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcast {
originalExpression = originalExpression.transformSingle(transformer, data)

View File

@@ -16,11 +16,13 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.types.SmartcastStability
class FirExpressionWithSmartcastToNullImpl(
override var originalExpression: FirQualifiedAccessExpression,
override val typeRef: FirTypeRef,
override val typesFromSmartCast: Collection<ConeKotlinType>
override val smartcastType: FirTypeRef,
override val typesFromSmartCast: Collection<ConeKotlinType>,
override val smartcastStability: SmartcastStability
) : FirExpressionWithSmartcastToNull() {
init {
assert(originalExpression.typeRef is FirResolvedTypeRef)
@@ -34,6 +36,10 @@ class FirExpressionWithSmartcastToNullImpl(
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
override val calleeReference: FirReference get() = originalExpression.calleeReference
override val originalType: FirTypeRef get() = originalExpression.typeRef
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
// purpose only.
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
originalExpression = originalExpression.transformSingle(transformer, data)

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name
/**
* Special type scope for unstable smartcast. The purpose of this scope is only to report "SMARTCAST_IMPOSSIBLE" diagnostics.
*
* This scope will serve all candidates available in the original scope. In addition, it also serve all additional members that are
* available from the smartcast type. This way, these additional members can be resolved. Later in
* [org.jetbrains.kotlin.fir.resolve.calls.CheckDispatchReceiver], these additional members are rejected with "UnstableSmartcast"
* diagnostic, which surfaces as "SMARTCAST_IMPOSSIBLE" diagnostic.
*/
class FirUnstableSmartcastTypeScope(
private val smartcastType: ConeKotlinType,
private val smartcastScope: FirTypeScope,
private val originalScope: FirTypeScope
) : FirTypeScope(), FirContainingNamesAwareScope {
private val scopes = listOf(smartcastScope, originalScope)
override fun processClassifiersByNameWithSubstitution(
name: Name,
processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit
) {
for (scope in scopes) {
scope.processClassifiersByNameWithSubstitution(name, processor)
}
}
private inline fun <T> processComposite(
process: FirTypeScope.(Name, (T) -> Unit) -> Unit,
name: Name,
noinline processor: (T) -> Unit
) {
val unique = mutableSetOf<T>()
for (scope in scopes) {
scope.process(name) {
if (unique.add(it)) {
processor(it)
}
}
}
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
return processComposite(FirScope::processFunctionsByName, name, processor)
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
return processComposite(FirScope::processPropertiesByName, name, processor)
}
private inline fun <N, T : FirCallableSymbol<*>> processTypedComposite(
process: FirTypeScope.(N, (T, FirTypeScope) -> ProcessorAction) -> ProcessorAction,
name: N,
noinline processor: (T, FirTypeScope) -> ProcessorAction
): ProcessorAction {
originalScope.process(name) { symbol, firTypeScope ->
processor(symbol, firTypeScope)
}.let { if (it == ProcessorAction.STOP) return ProcessorAction.STOP }
smartcastScope.process(name) { symbol, firTypeScope ->
// Only process the symbol if the dispatcher type is exactly the smartcast type. This way, we don't add any additional
// symbols that already exists in the original scope.
if ((symbol.fir as? FirCallableMemberDeclaration)?.dispatchReceiverType == smartcastType) {
processor(symbol, firTypeScope)
} else {
ProcessorAction.NEXT
}
}.let { if (it == ProcessorAction.STOP) return ProcessorAction.STOP }
return ProcessorAction.NEXT
}
override fun processDirectOverriddenFunctionsWithBaseScope(
functionSymbol: FirNamedFunctionSymbol,
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return processTypedComposite(FirTypeScope::processDirectOverriddenFunctionsWithBaseScope, functionSymbol, processor)
}
override fun processDirectOverriddenPropertiesWithBaseScope(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return processTypedComposite(FirTypeScope::processDirectOverriddenPropertiesWithBaseScope, propertySymbol, processor)
}
override fun getCallableNames(): Set<Name> {
return scopes.flatMapTo(hashSetOf()) { it.getContainingCallableNamesIfPresent() }
}
override fun getClassifierNames(): Set<Name> {
return scopes.flatMapTo(hashSetOf()) { it.getContainingClassifierNamesIfPresent() }
}
override val scopeOwnerLookupNames: List<String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
scopes.flatMap { it.scopeOwnerLookupNames }
}
}

View File

@@ -83,4 +83,6 @@ object FieldSets {
val modality = field(modalityType, nullable = true)
val scopeProvider = field("scopeProvider", firScopeProviderType)
val smartcastStability = field(smartcastStabilityType)
}

View File

@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.tree.generator.FieldSets.name
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.receivers
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.returnTypeRef
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.scopeProvider
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.smartcastStability
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.status
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.superTypeRefs
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.symbol
@@ -458,12 +459,16 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("originalExpression", qualifiedAccessExpression)
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
+field("originalType", typeRef)
+field("smartcastType", typeRef)
+smartcastStability
}
expressionWithSmartcastToNull.configure {
+field("originalExpression", qualifiedAccessExpression)
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
+field("originalType", typeRef)
+field("smartcastType", typeRef)
+smartcastStability
}
safeCallExpression.configure {

View File

@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SmartcastStability
import org.jetbrains.kotlin.types.Variance
val sourceElementType = type("fir", "FirSourceElement")
@@ -31,6 +32,7 @@ val nameType = type(Name::class)
val visibilityType = type(Visibility::class)
val effectiveVisibilityType = type("descriptors", "EffectiveVisibility")
val modalityType = type(Modality::class)
val smartcastStabilityType = type(SmartcastStability::class)
val fqNameType = type(FqName::class)
val classIdType = type(ClassId::class)
val annotationUseSiteTargetType = type(AnnotationUseSiteTarget::class)

View File

@@ -103,7 +103,7 @@ object RuntimeAssertionsTypeChecker : AdditionalTypeChecker {
expressionTypeWithSmartCast: KotlinType,
c: ResolutionContext<*>
) {
if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubType) return
if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubTypeForBuilderInference) return
val assertionInfo = RuntimeAssertionInfo.create(
c.expectedType,

View File

@@ -15,7 +15,6 @@ dependencies {
compile(project(":compiler:frontend.common"))
compile(project(":kotlin-script-runtime"))
compile(commonDep("io.javaslang","javaslang"))
api(project(":core:compiler.common.jvm"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(intellijDep()) { includeJars("trove4j", "guava", rootProject = rootProject) }
}

View File

@@ -110,7 +110,7 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
}
fun BindingTrace.reportDiagnosticOnce(diagnostic: Diagnostic) {
if (bindingContext.diagnostics.forElement(diagnostic.psiElement).any { it.factory == diagnostic.factory }) return
if (bindingContext.diagnostics.noSuppression().forElement(diagnostic.psiElement).any { it.factory == diagnostic.factory }) return
report(diagnostic)
}
@@ -119,8 +119,10 @@ fun BindingTrace.reportDiagnosticOnceWrtDiagnosticFactoryList(
diagnosticToReport: Diagnostic,
vararg diagnosticFactories: DiagnosticFactory<*>,
) {
val hasAlreadyReportedDiagnosticFromListOrSameType = bindingContext.diagnostics.forElement(diagnosticToReport.psiElement)
.any { diagnostic -> diagnostic.factory == diagnosticToReport.factory || diagnosticFactories.any { it == diagnostic.factory } }
val hasAlreadyReportedDiagnosticFromListOrSameType =
bindingContext.diagnostics.noSuppression()
.forElement(diagnosticToReport.psiElement)
.any { diagnostic -> diagnostic.factory == diagnosticToReport.factory || diagnosticFactories.any { it == diagnostic.factory } }
if (hasAlreadyReportedDiagnosticFromListOrSameType) return

View File

@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
@@ -53,8 +54,16 @@ class AnnotationChecker(
}
if (
annotated is KtTypeParameterListOwner &&
(annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions))
(annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions) ||
(annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations)))
) {
if (annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations)) {
(descriptor as? ClassDescriptor)?.declaredTypeParameters?.forEach {
//force annotation resolve to obtain targets
ForceResolveUtil.forceResolveAllContents(it.annotations)
}
}
annotated.typeParameters.forEach { check(it, trace) }
for (typeParameter in annotated.typeParameters) {
typeParameter.extendsBound?.let {

View File

@@ -518,9 +518,10 @@ class DeclarationsChecker(
}
private fun checkTypeParameters(typeParameterListOwner: KtTypeParameterListOwner) {
// TODO: Support annotation for type parameters
for (jetTypeParameter in typeParameterListOwner.typeParameters) {
AnnotationResolverImpl.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace)
if (!languageVersionSettings.supportsFeature(LanguageFeature.ClassTypeParameterAnnotations)) {
AnnotationResolverImpl.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace)
}
trace.get(TYPE_PARAMETER, jetTypeParameter)?.let { DescriptorResolver.checkConflictingUpperBounds(trace, it, jetTypeParameter) }
}

View File

@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
@@ -189,6 +190,9 @@ class LocalVariableResolver(
initializeWithDefaultGetterSetter(propertyDescriptor)
trace.record(BindingContext.VARIABLE, variable, propertyDescriptor)
result = propertyDescriptor
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
} else {
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
// For a local variable the type must not be deferred
@@ -196,6 +200,9 @@ class LocalVariableResolver(
variableDescriptor, scope, variable, dataFlowInfo, inferenceSession, trace, local = true
)
variableDescriptor.setOutType(type)
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
result = variableDescriptor
}
variableTypeAndInitializerResolver

View File

@@ -254,7 +254,7 @@ class CallCompleter(
system.resultingSubstitutor.replaceWithContravariantApproximatingSubstitution()
} else system.resultingSubstitutor
setResultingSubstitutor(resultingSubstitutor)
setSubstitutor(resultingSubstitutor)
}
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(

View File

@@ -108,7 +108,7 @@ class CandidateResolver(
private fun CallCandidateResolutionContext<*>.processTypeArguments() = check {
val ktTypeArguments = call.typeArguments
if (candidateCall.knownTypeParametersSubstitutor != null) {
candidateCall.setResultingSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
candidateCall.setSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
} else if (ktTypeArguments.isNotEmpty()) {
// Explicit type arguments passed
@@ -137,7 +137,7 @@ class CandidateResolver(
checkGenericBoundsInAFunctionCall(ktTypeArguments, typeArguments, candidateDescriptor, substitutor, trace)
}
candidateCall.setResultingSubstitutor(substitutor)
candidateCall.setSubstitutor(substitutor)
}
}

View File

@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.reportTrailingLambdaErrorOr
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceExpectedTypeConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -396,6 +397,13 @@ class DiagnosticReporterByTrackingStrategy(
}
}
(position as? BuilderInferenceExpectedTypeConstraintPosition)?.let {
val inferredType =
if (!error.lowerKotlinType.isNullableNothing()) error.lowerKotlinType
else error.upperKotlinType.makeNullable()
trace.report(TYPE_MISMATCH.on(it.topLevelCall, error.upperKotlinType, inferredType))
}
(position as? ExplicitTypeParameterConstraintPositionImpl)?.let {
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
val diagnosticFactory = if (error.isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED

View File

@@ -353,7 +353,7 @@ class GenericCandidateResolver(
resultingSystem.resultingSubstitutor.replaceWithContravariantApproximatingSubstitution()
} else resultingSystem.resultingSubstitutor
resolvedCall.setResultingSubstitutor(resultingSubstitutor)
resolvedCall.setSubstitutor(resultingSubstitutor)
}
// See KT-5385

View File

@@ -15,23 +15,27 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.callUtil.shouldBeSubstituteWithStubTypes
import org.jetbrains.kotlin.resolve.calls.callUtil.toOldSubstitution
import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.hasBuilderInferenceAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.shouldBeSubstituteWithStubTypes
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.model.freshTypeConstructor
import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.shouldBeUpdated
import org.jetbrains.kotlin.utils.addToStdlib.cast
class BuilderInferenceSession(
@@ -41,7 +45,7 @@ class BuilderInferenceSession(
callComponents: KotlinCallComponents,
builtIns: KotlinBuiltIns,
private val topLevelCallContext: BasicCallResolutionContext,
private val stubsForPostponedVariables: Map<NewTypeVariable, StubType>,
private val stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
private val trace: BindingTrace,
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
private val expressionTypingServices: ExpressionTypingServices,
@@ -50,23 +54,27 @@ class BuilderInferenceSession(
private val deprecationResolver: DeprecationResolver,
private val moduleDescriptor: ModuleDescriptor,
private val typeApproximator: TypeApproximator,
private val missingSupertypesResolver: MissingSupertypesResolver
private val missingSupertypesResolver: MissingSupertypesResolver,
private val lambdaArgument: LambdaKotlinCallArgument
) : ManyCandidatesResolver<CallableDescriptor>(
psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns
) {
private var nestedBuilderInferenceSessions: MutableSet<BuilderInferenceSession> = mutableSetOf()
private lateinit var lambda: ResolvedLambdaAtom
private lateinit var commonSystem: NewConstraintSystemImpl
private val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns)
init {
if (topLevelCallContext.inferenceSession is BuilderInferenceSession) {
topLevelCallContext.inferenceSession.nestedBuilderInferenceSessions.add(this)
}
stubsForPostponedVariables.keys.forEach(commonSystem::registerVariable)
}
private val commonCalls = arrayListOf<PSICompletedCallInfo>()
private val localVariables = arrayListOf<KtVariableDeclaration>()
// These calls come from the old type inference
private val oldDoubleColonExpressionCalls = arrayListOf<KtExpression>()
@@ -112,7 +120,7 @@ class BuilderInferenceSession(
private fun KotlinType.containsStubType(): Boolean {
return this.contains {
it is StubType
it is StubTypeForBuilderInference
}
}
@@ -134,20 +142,23 @@ class BuilderInferenceSession(
if (!checkCall) return
val isApplicableCall =
callComponents.statelessCallbacks.isApplicableCallForBuilderInference(
resultingDescriptor,
callComponents.languageVersionSettings
)
val isApplicableCall = callComponents.statelessCallbacks.isApplicableCallForBuilderInference(
resultingDescriptor,
callComponents.languageVersionSettings
)
if (!isApplicableCall) {
hasInapplicableCall = true
}
}
fun addLocalVariable(variable: KtVariableDeclaration) {
localVariables.add(variable)
}
private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean {
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubType } == true ||
descriptor.extensionReceiverParameter?.type?.contains { it is StubType } == true
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true ||
descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true
}
private fun isTopLevelBuilderInferenceCall() = findParentBuildInferenceSession() == null
@@ -163,6 +174,16 @@ class BuilderInferenceSession(
return null
}
@OptIn(ExperimentalStdlibApi::class)
private fun findAllParentBuildInferenceSessions() = buildList {
var currentSession: BuilderInferenceSession? = findParentBuildInferenceSession()
while (currentSession != null) {
add(currentSession)
currentSession = currentSession.findParentBuildInferenceSession()
}
}
fun hasInapplicableCall(): Boolean = hasInapplicableCall
override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean {
@@ -190,8 +211,12 @@ class BuilderInferenceSession(
return lhs.isAncestor(callElement)
}
override fun currentConstraintSystem(): ConstraintStorage {
return ConstraintStorage.Empty
override fun currentConstraintSystem() = ConstraintStorage.Empty
fun getNotFixedToInferredTypesSubstitutor(): NewTypeSubstitutor {
val currentSubstitutor =
commonSystem.buildCurrentSubstitutor().cast<NewTypeSubstitutor>().takeIf { !it.isEmpty } ?: return EmptySubstitutor
return ComposedSubstitutor(currentSubstitutor, createNonFixedTypeToVariableSubstitutor())
}
override fun inferPostponedVariables(
@@ -200,15 +225,18 @@ class BuilderInferenceSession(
completionMode: ConstraintSystemCompletionMode,
diagnosticsHolder: KotlinDiagnosticsHolder,
): Map<TypeConstructor, UnwrappedType>? {
val (commonSystem, effectivelyEmptyConstraintSystem) = buildCommonSystem(initialStorage)
val initialStorageSubstitutor = initialStorage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
this.lambda = lambda
this.commonSystem = commonSystem
fun getResultingSubstitutor(): NewTypeSubstitutor {
val storageSubstitutor = initialStorage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
return ComposedSubstitutor(storageSubstitutor, commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor)
}
val effectivelyEmptyConstraintSystem = initializeCommonSystem(initialStorage)
if (effectivelyEmptyConstraintSystem) {
if (isTopLevelBuilderInferenceCall()) {
updateAllCalls(initialStorageSubstitutor)
updateAllCalls(getResultingSubstitutor())
}
return null
}
@@ -222,7 +250,7 @@ class BuilderInferenceSession(
)
if (isTopLevelBuilderInferenceCall()) {
updateAllCalls(initialStorageSubstitutor)
updateAllCalls(getResultingSubstitutor())
}
return commonSystem.fixedTypeVariables.cast() // TODO: SUB
@@ -237,12 +265,15 @@ class BuilderInferenceSession(
private fun updateAllCalls(substitutor: NewTypeSubstitutor) {
updateCalls(
lambda,
substitutor = ComposedSubstitutor(substitutor, commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor),
substitutor = substitutor,
commonSystem.errors
)
for (nestedSession in nestedBuilderInferenceSessions) {
nestedSession.updateAllCalls(substitutor)
// TODO: exclude injected variables
nestedSession.updateAllCalls(
ComposedSubstitutor(nestedSession.commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor, substitutor)
)
}
}
@@ -267,12 +298,26 @@ class BuilderInferenceSession(
private fun createNonFixedTypeToVariableSubstitutor() = NewTypeSubstitutorByConstructorMap(createNonFixedTypeToVariableMap())
private fun integrateConstraints(
commonSystem: NewConstraintSystemImpl,
storage: ConstraintStorage,
nonFixedToVariablesSubstitutor: NewTypeSubstitutor,
shouldIntegrateAllConstraints: Boolean
): Boolean {
storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) }
) {
storage.notFixedTypeVariables.values.forEach {
if (it.typeVariable.freshTypeConstructor(commonSystem.typeSystemContext) !in commonSystem.allTypeVariables) {
commonSystem.registerVariable(it.typeVariable)
}
}
for (parentSession in findAllParentBuildInferenceSessions()) {
for ((variable, stubType) in parentSession.stubsForPostponedVariables) {
commonSystem.registerVariable(variable)
commonSystem.addSubtypeConstraint(
variable.defaultType,
stubType,
InjectedAnotherStubTypeConstraintPositionImpl(lambdaArgument)
)
}
}
/*
* storage can contain the following substitutions:
@@ -283,16 +328,14 @@ class BuilderInferenceSession(
* */
val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
var introducedConstraint = false
for (initialConstraint in storage.initialConstraints) {
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB
val lowerCallSubstituted = callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)
val upperCallSubstituted = callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)
val (lower, upper) = substituteNotFixedVariables(lowerCallSubstituted, upperCallSubstituted, nonFixedToVariablesSubstitutor)
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
introducedConstraint = true
when (initialConstraint.constraintKind) {
ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER")
@@ -311,34 +354,73 @@ class BuilderInferenceSession(
val typeVariable = storage.allTypeVariables.getValue(variableConstructor)
commonSystem.registerVariable(typeVariable)
commonSystem.addEqualityConstraint((typeVariable as NewTypeVariable).defaultType, type, CoroutinePosition)
introducedConstraint = true
}
}
return introducedConstraint
}
private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair<NewConstraintSystemImpl, Boolean> {
val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns)
fun addExpectedTypeConstraint(
callExpression: KtExpression,
a: KotlinType,
b: KotlinType
) {
val nonFixedToVariablesSubstitutor: NewTypeSubstitutor = createNonFixedTypeToVariableSubstitutor()
val (lower, upper) = substituteNotFixedVariables(a, b, nonFixedToVariablesSubstitutor)
val position = BuilderInferenceExpectedTypeConstraintPosition(callExpression)
val currentSubstitutor = commonSystem.buildCurrentSubstitutor()
commonSystem.addSubtypeConstraint(
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, lower),
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, upper),
position
)
}
private fun substituteNotFixedVariables(
lowerType: KotlinType,
upperType: KotlinType,
nonFixedToVariablesSubstitutor: NewTypeSubstitutor
): Pair<KotlinType, KotlinType> {
val commonCapTypes = extractCommonCapturedTypes(lowerType, upperType)
val substitutedCommonCapType = commonCapTypes.associate {
it.constructor as TypeConstructor to nonFixedToVariablesSubstitutor.safeSubstitute(it).asTypeProjection()
}
val capTypesSubstitutor = TypeConstructorSubstitution.createByConstructorsMap(substitutedCommonCapType).buildSubstitutor()
val substitutedLowerType = nonFixedToVariablesSubstitutor.safeSubstitute(capTypesSubstitutor.substitute(lowerType.unwrap()))
val substitutedUpperType = nonFixedToVariablesSubstitutor.safeSubstitute(capTypesSubstitutor.substitute(upperType.unwrap()))
return substitutedLowerType to substitutedUpperType
}
private fun extractCommonCapturedTypes(a: KotlinType, b: KotlinType): List<NewCapturedType> {
val extractedCapturedTypes = mutableSetOf<NewCapturedType>().also { extractCapturedTypesTo(a, it) }
return extractedCapturedTypes.filter { capturedType -> b.contains { it.constructor === capturedType.constructor } }
}
private fun extractCapturedTypesTo(type: KotlinType, to: MutableSet<NewCapturedType>) {
if (type is NewCapturedType) {
to.add(type)
}
for (typeArgument in type.arguments) {
if (typeArgument.isStarProjection) continue
extractCapturedTypesTo(typeArgument.type, to)
}
}
private fun initializeCommonSystem(initialStorage: ConstraintStorage): Boolean {
val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor()
integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor, false)
var effectivelyEmptyCommonSystem = true
integrateConstraints(initialStorage, nonFixedToVariablesSubstitutor, false)
for (call in commonCalls) {
val hasConstraints =
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false)
if (hasConstraints) effectivelyEmptyCommonSystem = false
integrateConstraints(call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false)
}
for (call in partiallyResolvedCallsInfo) {
val hasConstraints =
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true)
if (hasConstraints) effectivelyEmptyCommonSystem = false
integrateConstraints(call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true)
}
return commonSystem to effectivelyEmptyCommonSystem
return commonSystem.notFixedTypeVariables.all { it.value.constraints.isEmpty() }
}
private fun reportErrors(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, errors: List<ConstraintSystemError>) {
@@ -351,6 +433,13 @@ class BuilderInferenceSession(
)
}
private fun updateLocalVariable(localVariable: KtVariableDeclaration, substitutor: NewTypeSubstitutor) {
val descriptor = trace[BindingContext.VARIABLE, localVariable] as? LocalVariableDescriptor
if (descriptor != null && descriptor.type.shouldBeUpdated()) {
descriptor.setOutType(substitutor.safeSubstitute(descriptor.type.unwrap()))
}
}
private fun updateCall(
completedCall: PSICompletedCallInfo,
nonFixedTypesToResultSubstitutor: NewTypeSubstitutor,
@@ -378,7 +467,7 @@ class BuilderInferenceSession(
return currentSession.topLevelCallContext.trace
}
private fun completeDoubleColonExpression(expression: KtDoubleColonExpression, substitutor: NewTypeSubstitutor) {
fun completeDoubleColonExpression(expression: KtDoubleColonExpression, substitutor: NewTypeSubstitutor) {
val atomCompleter = createResolvedAtomCompleter(substitutor, topLevelCallContext)
val declarationDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression)
@@ -402,7 +491,13 @@ class BuilderInferenceSession(
val resolvedCall = trace.get(BindingContext.RESOLVED_CALL, call)
if (resolvedCall is ResolvedCallImpl<*>) {
resolvedCall.setResultingSubstitutor(substitutor.toOldSubstitution().buildSubstitutor())
val oldSubstitutor = substitutor.toOldSubstitution().buildSubstitutor()
if (resolvedCall.resultingDescriptor.shouldBeSubstituteWithStubTypes()) {
resolvedCall.setResultingSubstitutor(oldSubstitutor)
}
if (resolvedCall.shouldBeSubstituteWithStubTypes()) {
resolvedCall.setResolvedCallSubstitutor(oldSubstitutor)
}
}
}
@@ -463,6 +558,10 @@ class BuilderInferenceSession(
topLevelCallContext.replaceBindingTrace(findTopLevelTrace()).replaceInferenceSession(this)
)
for (localVariable in localVariables) {
updateLocalVariable(localVariable, nonFixedTypesToResultSubstitutor)
}
for (completedCall in commonCalls) {
updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
reportErrors(completedCall, completedCall.resolvedCall, errors)
@@ -493,3 +592,5 @@ class ComposedSubstitutor(val left: NewTypeSubstitutor, val right: NewTypeSubsti
override val isEmpty: Boolean get() = left.isEmpty && right.isEmpty
}
class BuilderInferenceExpectedTypeConstraintPosition(callElement: KtExpression) : ExpectedTypeConstraintPosition<KtExpression>(callElement)

View File

@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
@@ -299,9 +296,11 @@ class CoroutineInferenceSupport(
}
}
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubType }
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubTypeForBuilderInference }
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
if (languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)) return true
if (!languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference)) {
return isGoodCallForOldCoroutines(descriptor)
}
@@ -335,8 +334,11 @@ fun isCoroutineCallWithAdditionalInference(
else
parameterDescriptor.hasSuspendFunctionType
val pureExpression = argument.getArgumentExpression()
val baseExpression = if (pureExpression is KtLabeledExpression) pureExpression.baseExpression else pureExpression
return parameterHasOptIn &&
argument.getArgumentExpression() is KtLambdaExpression &&
baseExpression is KtLambdaExpression &&
parameterDescriptor.type.let { it.isBuiltinFunctionalType && it.getReceiverTypeFromFunctionType() != null }
}

View File

@@ -64,7 +64,7 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
void setConstraintSystem(@NotNull ConstraintSystem constraintSystem);
void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor);
void setSubstitutor(@NotNull TypeSubstitutor substitutor);
@Nullable
TypeSubstitutor getKnownTypeParametersSubstitutor();

View File

@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeProjection;
@@ -42,6 +43,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
import org.jetbrains.kotlin.types.Variance;
import java.util.*;
import java.util.stream.Collectors;
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE;
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
@@ -68,7 +70,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
private final TypeSubstitutor knownTypeParametersSubstitutor;
@NotNull
private final Map<TypeParameterDescriptor, KotlinType> typeArguments;
private Map<TypeParameterDescriptor, KotlinType> typeArguments;
@NotNull
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments;
private final MutableDataFlowInfoForArguments dataFlowInfoForArguments;
@@ -193,19 +195,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
return resultingDescriptor == null ? candidateDescriptor : resultingDescriptor;
}
@Override
@SuppressWarnings("unchecked")
public void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor) {
resultingDescriptor = (D) candidateDescriptor.substitute(substitutor);
//noinspection ConstantConditions
if (resultingDescriptor == null) {
throw new AssertionError(
"resultingDescriptor shouldn't be null:\n" +
"candidateDescriptor: " + DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(candidateDescriptor) + "\n" +
"substitution: " + substitutor.getSubstitution()
);
}
D descriptorToSubstitute = resultingDescriptor != null && DescriptorUtilsKt.shouldBeSubstituteWithStubTypes(resultingDescriptor)
? resultingDescriptor
: candidateDescriptor;
resultingDescriptor = (D) descriptorToSubstitute.substitute(substitutor);
}
public void setResolvedCallSubstitutor(@NotNull TypeSubstitutor substitutor) {
for (TypeParameterDescriptor typeParameter : candidateDescriptor.getTypeParameters()) {
TypeProjection typeArgumentProjection = substitutor.getSubstitution().get(typeParameter.getDefaultType());
if (typeArgumentProjection != null) {
@@ -213,6 +211,17 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
}
}
typeArguments = typeArguments.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> substitutor.safeSubstitute(e.getValue(), e.getKey().getVariance())));
if (dispatchReceiver instanceof ExpressionReceiver) {
dispatchReceiver = dispatchReceiver.replaceType(substitutor.safeSubstitute(dispatchReceiver.getType(), Variance.IN_VARIANCE));
}
if (extensionReceiver instanceof ExtensionReceiver) {
extensionReceiver =
extensionReceiver.replaceType(substitutor.safeSubstitute(extensionReceiver.getType(), Variance.IN_VARIANCE));
}
if (candidateDescriptor.getValueParameters().isEmpty()) return;
List<ValueParameterDescriptor> substitutedParameters = resultingDescriptor.getValueParameters();
@@ -239,14 +248,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
assert substitutedVersion != null : valueParameterDescriptor;
argumentToParameterMap.put(entry.getKey(), argumentMatch.replaceValueParameter(substitutedVersion));
}
}
if (dispatchReceiver instanceof ExpressionReceiver) {
dispatchReceiver = dispatchReceiver.replaceType(substitutor.safeSubstitute(dispatchReceiver.getType(), Variance.IN_VARIANCE));
}
if (extensionReceiver instanceof ExtensionReceiver) {
extensionReceiver =
extensionReceiver.replaceType(substitutor.safeSubstitute(extensionReceiver.getType(), Variance.IN_VARIANCE));
}
@Override
public void setSubstitutor(@NotNull TypeSubstitutor substitutor) {
setResultingSubstitutor(substitutor);
setResolvedCallSubstitutor(substitutor);
}
@Override

View File

@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
@@ -136,7 +137,10 @@ class SmartCastManager(private val argumentTypeResolver: ArgumentTypeResolver) {
else
listOf(expectedType)
val collectedTypes = c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings).toMutableList()
val builderInferenceSubstitutor = (c.inferenceSession as? BuilderInferenceSession)?.getNotFixedToInferredTypesSubstitutor()
val collectedTypes = c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings).let { types ->
if (builderInferenceSubstitutor != null) types.map { builderInferenceSubstitutor.safeSubstitute(it.unwrap()) } else types
}.toMutableList()
if (collectedTypes.isNotEmpty() && c.languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) {
// Sometime expected type may be inferred to be an intersection of all of the smart-cast types

View File

@@ -90,7 +90,7 @@ class KotlinResolutionCallbacksImpl(
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?,
annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>,
stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
): ReturnArgumentsAnalysisResult {
val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument
val outerCallContext = psiCallArgument.outerCallContext
@@ -167,7 +167,7 @@ class KotlinResolutionCallbacksImpl(
callComponents, builtIns, topLevelCallContext, stubsForPostponedVariables, trace,
kotlinToResolvedCallTransformer, expressionTypingServices, argumentTypeResolver,
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, typeApproximator,
missingSupertypesResolver
missingSupertypesResolver, lambdaArgument
)
} else {
null

View File

@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -355,6 +356,7 @@ class KotlinToResolvedCallTransformer(
} ?: return null
val recordedType = context.trace.getType(deparenthesized)
val recordedTypeForParenthesized = context.trace.getType(expression)
var updatedType = convertedArgumentType ?: getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
makeNullableTypeIfSafeReceiver(resultingDescriptor.returnType, context)
@@ -384,7 +386,7 @@ class KotlinToResolvedCallTransformer(
context.trace.report(Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.on(deparenthesized))
}
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, recordedTypeForParenthesized, expression, context)
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, reportErrorDuringTypeCheck)
@@ -410,10 +412,12 @@ class KotlinToResolvedCallTransformer(
private fun updateRecordedTypeForArgument(
updatedType: KotlinType?,
recordedType: KotlinType?,
recordedTypeForParenthesized: KotlinType?,
argumentExpression: KtExpression,
context: BasicCallResolutionContext,
): KotlinType? {
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType) || updatedType == null) return updatedType
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType && recordedType == recordedTypeForParenthesized) || updatedType == null)
return updatedType
val expressions = ArrayList<KtExpression>().also { expressions ->
var expression: KtExpression? = argumentExpression
@@ -551,6 +555,8 @@ class TrackingBindingTrace(val trace: BindingTrace) : BindingTrace by trace {
var reported: Boolean = false
override fun report(diagnostic: Diagnostic) {
if (bindingContext.diagnostics.noSuppression().forElement(diagnostic.psiElement).any { it == diagnostic }) return
trace.report(diagnostic)
reported = true
}
@@ -989,7 +995,7 @@ private fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
it is NewCapturedType ||
it.constructor is IntegerLiteralTypeConstructor ||
it is DefinitelyNotNullType ||
it is StubType
it is StubTypeForBuilderInference
}
} ?: false)

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
@@ -14,10 +15,7 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.MissingSupertypesResolver
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.resolve.calls.callUtil.toOldSubstitution
@@ -29,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -46,9 +45,7 @@ import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.shouldBeUpdated
import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ResolvedAtomCompleter(
@@ -89,9 +86,22 @@ class ResolvedAtomCompleter(
is ResolvedLambdaAtom -> completeLambda(resolvedAtom)
is ResolvedCallAtom -> completeResolvedCall(resolvedAtom, emptyList())
is ResolvedSubCallArgument -> completeSubCallArgument(resolvedAtom)
is ResolvedExpressionAtom -> completeExpression(resolvedAtom)
}
}
// We run completion on expressions only for last statements of block expression to substitute freshly inferred stub types variables
fun completeExpression(resolvedAtom: ResolvedExpressionAtom) {
val argumentExpression = resolvedAtom.atom.psiExpression
val inferenceSession = topLevelCallContext.inferenceSession
if (argumentExpression !is KtBlockExpression || inferenceSession !is BuilderInferenceSession) return
val callableReference = argumentExpression.statements.lastOrNull() as? KtCallableReferenceExpression ?: return
inferenceSession.completeDoubleColonExpression(callableReference, inferenceSession.getNotFixedToInferredTypesSubstitutor())
}
fun completeAll(resolvedAtom: ResolvedAtom) {
if (!resolvedAtom.analyzed)
return
@@ -142,6 +152,14 @@ class ResolvedAtomCompleter(
else -> atom.psiKotlinCall.psiCall
}
val callElement = psiCallForResolutionContext.callElement
if (callElement is KtExpression) {
val recordedType = topLevelCallContext.trace.getType(callElement)
if (recordedType != null && recordedType.shouldBeUpdated() && resolvedCall.resultingDescriptor.returnType != null) {
topLevelCallContext.trace.recordType(callElement, resolvedCall.resultingDescriptor.returnType)
}
}
val resolutionContextForPartialCall =
topLevelCallContext.trace[BindingContext.PARTIAL_CALL_RESOLUTION_CONTEXT, psiCallForResolutionContext]
@@ -383,7 +401,7 @@ class ResolvedAtomCompleter(
private fun extractCallableReferenceResultTypeInfoFromDescriptor(
callableCandidate: CallableReferenceCandidate,
recorderDescriptor: CallableDescriptor
recordedDescriptor: CallableDescriptor
): CallableReferenceResultTypeInfo {
val explicitCallableReceiver = when (callableCandidate.explicitReceiverKind) {
ExplicitReceiverKind.DISPATCH_RECEIVER -> callableCandidate.dispatchReceiver
@@ -391,14 +409,31 @@ class ResolvedAtomCompleter(
else -> null
}
return CallableReferenceResultTypeInfo(
recorderDescriptor.dispatchReceiverParameter?.value,
recorderDescriptor.extensionReceiverParameter?.value,
recordedDescriptor.dispatchReceiverParameter?.value,
recordedDescriptor.extensionReceiverParameter?.value,
explicitCallableReceiver?.receiver?.receiverValue,
TypeSubstitutor.EMPTY,
callableCandidate.reflectionCandidateType
callableCandidate.reflectionCandidateType.replaceFunctionTypeArgumentsByDescriptor(recordedDescriptor)
)
}
@OptIn(ExperimentalStdlibApi::class)
private fun KotlinType.replaceFunctionTypeArgumentsByDescriptor(descriptor: CallableDescriptor) =
when (descriptor) {
is CallableMemberDescriptor -> {
val newArgumentTypes = buildList {
descriptor.extensionReceiverParameter?.let { add(it.type) }
addAll(descriptor.valueParameters.map { it.type })
add(descriptor.returnType)
}
if (newArgumentTypes.size == arguments.size) {
replace(arguments.mapIndexed { i, type -> newArgumentTypes[i]?.let { type.replaceType(it) } ?: type })
} else this
}
is ValueDescriptor -> replace(descriptor.type.arguments)
else -> this
}
private fun completeCallableReference(resolvedAtom: ResolvedCallableReferenceAtom) {
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
@@ -415,7 +450,10 @@ class ResolvedAtomCompleter(
val rawExtensionReceiver = callableCandidate.extensionReceiver
if (rawExtensionReceiver != null && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubType }) {
val unrestrictedBuilderInferenceSupported =
topLevelCallContext.languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)
if (rawExtensionReceiver != null && !unrestrictedBuilderInferenceSupported && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubTypeForBuilderInference }) {
topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression))
return
}
@@ -439,7 +477,7 @@ class ResolvedAtomCompleter(
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
)
resolvedCall.setResultingSubstitutor(resultTypeInfo.substitutor)
resolvedCall.setSubstitutor(resultTypeInfo.substitutor)
recordArgumentAdaptationForCallableReference(resolvedCall, callableCandidate.callableReferenceAdaptation)

View File

@@ -37,11 +37,9 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstituto
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.TypeSubstitution
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.sure
@@ -335,3 +333,9 @@ fun NewTypeSubstitutor.toOldSubstitution(): TypeSubstitution = object : TypeSubs
return isEmpty
}
}
fun <D : CallableDescriptor> ResolvedCallImpl<D>.shouldBeSubstituteWithStubTypes() =
typeArguments.any { argument -> argument.value.contains { it is StubTypeForBuilderInference } }
|| dispatchReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|| extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|| valueArguments.any { argument -> argument.key.type.contains { it is StubTypeForBuilderInference } }

View File

@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compati
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -171,7 +172,7 @@ class ExpectedActualDeclarationChecker(
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
// Only strong incompatibilities, but this is an OptionalExpectation -- don't report it
if (compatibility.allStrongIncompatibilities() && isOptionalAnnotationClass(descriptor)) return
if (compatibility.allStrongIncompatibilities() && OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor)) return
// Only strong incompatibilities, or error won't be reported on actual: report NO_ACTUAL_FOR_EXPECT here
if (compatibility.allStrongIncompatibilities() ||
@@ -389,41 +390,7 @@ class ExpectedActualDeclarationChecker(
}
companion object {
val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation")
@JvmStatic
fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean =
descriptor is ClassDescriptor &&
descriptor.kind == ClassKind.ANNOTATION_CLASS &&
descriptor.isExpect &&
descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
// TODO: move to some other place which is accessible both from backend-common and js.serializer
@JvmStatic
fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean {
assert(descriptor.isExpect) { "Not an expected class: $descriptor" }
if (isOptionalAnnotationClass(descriptor)) {
with(ExpectedActualResolver) {
return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty()
}
}
return false
}
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
private fun <K, V> LinkedHashMap<K, List<V>>.merge(other: Map<K, List<V>>): LinkedHashMap<K, List<V>> {
for ((key, newValue) in other) {
val oldValue = this[key] ?: emptyList()
this[key] = oldValue + newValue
}
return this
}
private fun ModuleInfo.unwrapModuleInfo(): List<ModuleInfo> = if (this is CombinedModuleInfo) this.containedModules else listOf(this)
}
}

View File

@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
object OptionalExpectationChecker {
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
@@ -34,6 +35,6 @@ object OptionalExpectationChecker {
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
declaration.annotationEntries.find { entry ->
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry)
annotationDescriptor?.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME
annotationDescriptor?.fqName == OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME
}
}

View File

@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.resolve.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
if (!ExpectedActualDeclarationChecker.isOptionalAnnotationClass(targetDescriptor)) return
if (!OptionalAnnotationUtil.isOptionalAnnotationClass(targetDescriptor)) return
if (!element.isUsageAsAnnotationOrImport()) {
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))

View File

@@ -252,10 +252,32 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
if (typeParameters.isEmpty()) return Collections.emptyList();
boolean supportClassTypeParameterAnnotations = c.getLanguageVersionSettings().supportsFeature(LanguageFeature.ClassTypeParameterAnnotations);
List<TypeParameterDescriptor> parameters = new ArrayList<>(typeParameters.size());
for (int i = 0; i < typeParameters.size(); i++) {
parameters.add(new LazyTypeParameterDescriptor(c, this, typeParameters.get(i), i));
KtTypeParameter parameter = typeParameters.get(i);
Annotations lazyAnnotations;
if (supportClassTypeParameterAnnotations) {
lazyAnnotations = new LazyAnnotations(
new LazyAnnotationsContext(
c.getAnnotationResolver(),
storageManager,
c.getTrace()
) {
@NotNull
@Override
public LexicalScope getScope() {
return getOuterScope();
}
},
parameter.getAnnotationEntries()
);
} else {
lazyAnnotations = Annotations.Companion.getEMPTY();
}
parameters.add(new LazyTypeParameterDescriptor(c, this, parameter, lazyAnnotations, i));
}
return parameters;

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -43,11 +44,13 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri
@NotNull LazyClassContext c,
@NotNull LazyClassDescriptor containingDeclaration,
@NotNull KtTypeParameter typeParameter,
@NotNull Annotations annotations,
int index
) {
super(
c.getStorageManager(),
containingDeclaration,
annotations,
typeParameter.getNameAsSafeName(),
typeParameter.getVariance(),
typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD),

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.resolve.source
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtPureElement
@@ -24,5 +23,3 @@ import org.jetbrains.kotlin.psi.KtPureElement
class KotlinSourceElement(override val psi: KtElement) : PsiSourceElement
fun KtPureElement?.toSourceElement(): SourceElement = if (this == null) SourceElement.NO_SOURCE else KotlinSourceElement(psiOrParent)
fun SourceElement.getPsi(): PsiElement? = (this as? PsiSourceElement)?.psi

View File

@@ -35,15 +35,14 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession;
import org.jetbrains.kotlin.resolve.calls.smartcasts.*;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.KotlinTypeKt;
import org.jetbrains.kotlin.types.TypeConstructor;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import java.util.Collection;
@@ -287,6 +286,11 @@ public class DataFlowAnalyzer {
@NotNull Ref<Boolean> hasError,
boolean reportErrorForTypeMismatch
) {
if (!noExpectedType(c.expectedType) && TypeUtilsKt.contains(expressionType, (type) -> type instanceof StubTypeForBuilderInference)) {
if (c.inferenceSession instanceof BuilderInferenceSession) {
((BuilderInferenceSession) c.inferenceSession).addExpectedTypeConstraint(expression, expressionType, c.expectedType);
}
}
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
kotlinTypeChecker.isSubtypeOf(expressionType, c.expectedType)) {
return expressionType;

View File

@@ -114,7 +114,7 @@ class DoubleColonExpressionResolver(
} else {
val result = resolveDoubleColonLHS(expression, c)
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubType } == true) {
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression)
}
@@ -548,17 +548,19 @@ class DoubleColonExpressionResolver(
val result = getCallableReferenceType(expression, lhs, resolutionResults, c)
val doesSomeExtensionReceiverContainsStubType =
resolutionResults != null && resolutionResults.resultingCalls.any { resolvedCall ->
resolvedCall.extensionReceiver?.type?.contains { it is StubType } == true
resolvedCall.extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
}
if (doesSomeExtensionReceiverContainsStubType) {
val unrestrictedBuilderInferenceSupported = languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)
if (doesSomeExtensionReceiverContainsStubType && !unrestrictedBuilderInferenceSupported) {
c.trace.reportDiagnosticOnce(TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(expression))
return noTypeInfo(c)
}
val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubType } == true) {
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubTypeForBuilderInference } == true) {
c.inferenceSession.addOldCallableReferenceCalls(expression)
}

View File

@@ -13,7 +13,6 @@ class SourceToOutputFilesMap(
private val pathConverter: FileToPathConverter
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
@Synchronized
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
}
@@ -24,7 +23,6 @@ class SourceToOutputFilesMap(
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()
@Synchronized
fun remove(file: File): Collection<File> =
get(file).also { storage.remove(pathConverter.toPath(file)) }
}

View File

@@ -31,7 +31,7 @@ class FileSnapshotMapTest : TestWithWorkingDir() {
@After
override fun tearDown() {
snapshotMap.flush(false)
snapshotMap.close()
snapshotMap.closeForTest()
super.tearDown()
}

View File

@@ -29,7 +29,7 @@ class SourceToOutputFilesMapTest : TestWithWorkingDir() {
@After
override fun tearDown() {
stofMap.flush(false)
stofMap.close()
stofMap.closeForTest()
super.tearDown()
}

View File

@@ -697,7 +697,3 @@ fun IrExpression?.isPure(
return false
}
fun IrDeclaration.isFromJava(): Boolean =
origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
parent is IrDeclaration && (parent as IrDeclaration).isFromJava()

View File

@@ -9,20 +9,27 @@ import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.asInlinable
import org.jetbrains.kotlin.backend.common.ir.copyValueParametersFrom
import org.jetbrains.kotlin.backend.common.ir.inline
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
class ArrayConstructorLowering(val context: CommonBackendContext) : BodyLoweringPass {
@@ -37,18 +44,20 @@ private class ArrayConstructorTransformer(
) : IrElementTransformerVoidWithContext() {
// Array(size, init) -> Array(size)
private fun arrayInlineToSizeConstructor(irConstructor: IrConstructor): IrFunctionSymbol? {
val clazz = irConstructor.constructedClass.symbol
return when {
irConstructor.valueParameters.size != 2 -> null
clazz == context.irBuiltIns.arrayClass -> context.ir.symbols.arrayOfNulls // Array<T> has no unary constructor: it can only exist for Array<T?>
context.irBuiltIns.primitiveArrays.contains(clazz) -> clazz.constructors.single { it.owner.valueParameters.size == 1 }
else -> null
companion object {
internal fun arrayInlineToSizeConstructor(context: CommonBackendContext, irConstructor: IrConstructor): IrFunctionSymbol? {
val clazz = irConstructor.constructedClass.symbol
return when {
irConstructor.valueParameters.size != 2 -> null
clazz == context.irBuiltIns.arrayClass -> context.ir.symbols.arrayOfNulls // Array<T> has no unary constructor: it can only exist for Array<T?>
context.irBuiltIns.primitiveArrays.contains(clazz) -> clazz.constructors.single { it.owner.valueParameters.size == 1 }
else -> null
}
}
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val sizeConstructor = arrayInlineToSizeConstructor(expression.symbol.owner)
val sizeConstructor = arrayInlineToSizeConstructor(context, expression.symbol.owner)
?: return super.visitConstructorCall(expression)
// inline fun <reified T> Array(size: Int, invokable: (Int) -> T): Array<T> {
// val result = arrayOfNulls<T>(size)
@@ -90,3 +99,80 @@ private class ArrayConstructorTransformer(
}
}
}
object arrayConstuctorWrapper : IrDeclarationOriginImpl("arrayConstuctorWrapper") {}
class ArrayConstructorReferenceLowering(val context: CommonBackendContext) : BodyLoweringPass {
override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(ArrayConstructorReferenceTransformer(context, container as IrSymbolOwner))
}
private class ArrayConstructorReferenceTransformer(val context: CommonBackendContext, val container: IrSymbolOwner) : IrElementTransformerVoid() {
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildrenVoid()
val target = expression.symbol.owner
if (target !is IrConstructor) return expression
if (ArrayConstructorTransformer.arrayInlineToSizeConstructor(context, target) == null) return expression
return expression.run {
IrCompositeImpl(startOffset, endOffset, type, origin).apply {
val wrapper = createFunctionReferenceWrapper(expression, target)
statements.add(wrapper)
statements.add(
IrFunctionReferenceImpl(
startOffset,
endOffset,
type,
wrapper.symbol,
0,
valueArgumentsCount,
target.symbol,
origin
)
)
}
}
}
private fun createFunctionReferenceWrapper(expression: IrFunctionReference, target: IrConstructor): IrSimpleFunction {
val typeArguments = with(expression.type as IrSimpleType) { arguments }
assert(typeArguments.size == 3)
val arrayType = (typeArguments[2] as IrTypeProjection).type
val arrayElementType = ((arrayType as IrSimpleType).arguments.singleOrNull() as? IrTypeProjection)?.type
val wrapper = context.irFactory.buildFun {
startOffset = expression.startOffset
endOffset = expression.endOffset
origin = arrayConstuctorWrapper
name = Name.special("<array_inline_constructor_wrapper>")
visibility = DescriptorVisibilities.LOCAL
}
val substitutionMap = target.typeParameters.singleOrNull()?.let { mapOf(it.symbol to arrayElementType!!) } ?: emptyMap()
wrapper.copyValueParametersFrom(target, substitutionMap)
wrapper.returnType = arrayType
wrapper.parent = container as IrDeclarationParent
wrapper.body = context.irFactory.createBlockBody(expression.startOffset, expression.endOffset).also { body ->
with(context.createIrBuilder(wrapper.symbol)) {
body.statements.add(irReturn(
irCall(target.symbol, arrayType).also { call ->
if (call.typeArgumentsCount != 0) {
assert(call.typeArgumentsCount == 1)
call.putTypeArgument(0, arrayElementType)
}
call.putValueArgument(0, irGet(wrapper.valueParameters[0]))
call.putValueArgument(1, irGet(wrapper.valueParameters[1]))
}
))
}
}
return wrapper
}
}
}

View File

@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
// `doRemove` means should expect-declaration be removed from IR
@OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -70,7 +70,7 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
private fun isOptionalAnnotationClass(klass: IrClass): Boolean {
return klass.kind == ClassKind.ANNOTATION_CLASS &&
klass.isExpect &&
klass.annotations.hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
klass.annotations.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
}
private fun tryCopyDefaultArguments(declaration: IrValueParameter) {

View File

@@ -23,8 +23,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
interface InnerClassesSupport {
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS", isSynthetic = true)
fun getOuterThisField(innerClass: IrClass): IrField
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor
fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor?

View File

@@ -785,9 +785,6 @@ class LocalDeclarationsLowering(
}
}
private fun Name.stripSpecialMarkers(): String =
if (isSpecial) asString().substring(1, asString().length - 1) else asString()
private fun suggestNameForCapturedValue(declaration: IrValueDeclaration, usedNames: MutableSet<String>, isExplicitLocalFunction: Boolean = false): Name {
if (declaration is IrValueParameter) {
if (declaration.name.asString() == "<this>" && declaration.isDispatchReceiver()) {
@@ -808,7 +805,7 @@ class LocalDeclarationsLowering(
}
val base = if (declaration.name.isSpecial) {
declaration.name.stripSpecialMarkers()
declaration.name.asStringStripSpecialMarkers()
} else {
declaration.name.asString()
}
@@ -859,9 +856,9 @@ class LocalDeclarationsLowering(
val correspondingProperty = parentFun.safeAs<IrSimpleFunction>()?.correspondingPropertySymbol?.owner
return when {
correspondingProperty != null ->
correspondingProperty.name.stripSpecialMarkers()
correspondingProperty.name.asStringStripSpecialMarkers()
else ->
parentFun.name.stripSpecialMarkers()
parentFun.name.asStringStripSpecialMarkers()
}
}

View File

@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.util.remapTypes
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -32,9 +32,23 @@ class ProvisionalFunctionExpressionLowering :
irBody.transformChildren(this, ProvisionalFunctionExpressionLoweringContext())
}
override fun visitCall(expression: IrCall, data: ProvisionalFunctionExpressionLoweringContext): IrElement {
return super.visitCall(expression, ProvisionalFunctionExpressionLoweringContext(data, expression.startOffset, expression.endOffset))
}
override fun visitCall(expression: IrCall, data: ProvisionalFunctionExpressionLoweringContext) = super.visitCall(
expression,
ProvisionalFunctionExpressionLoweringContext(
data,
expression.startOffset,
expression.endOffset
)
)
override fun visitVariable(declaration: IrVariable, data: ProvisionalFunctionExpressionLoweringContext) = super.visitVariable(
declaration,
ProvisionalFunctionExpressionLoweringContext(
data,
declaration.startOffset,
declaration.endOffset
)
)
override fun visitFunctionExpression(expression: IrFunctionExpression, data: ProvisionalFunctionExpressionLoweringContext): IrElement {
expression.transformChildren(this, ProvisionalFunctionExpressionLoweringContext(data))

View File

@@ -8,7 +8,6 @@ dependencies {
compile(project(":compiler:frontend"))
compile(project(":compiler:backend-common"))
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:ir.serialization.common"))
compile(project(":compiler:ir.serialization.js"))

View File

@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.cleanup.CleanupLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.CopyInlineFunctionBodyLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.jsRecordExtractedLocalClasses
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineDeclarationsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.jsRecordExtractedLocalClasses
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -192,10 +192,17 @@ private val jsCodeOutliningPhase = makeBodyLoweringPhase(
description = "Outline js() calls where JS code references Kotlin locals"
)
private val arrayConstructorReferencePhase = makeBodyLoweringPhase(
::ArrayConstructorReferenceLowering,
name = "ArrayConstructorReference",
description = "Transform `::Array` into a lambda"
)
private val arrayConstructorPhase = makeBodyLoweringPhase(
::ArrayConstructorLowering,
name = "ArrayConstructor",
description = "Transform `Array(size) { index -> value }` into a loop"
description = "Transform `Array(size) { index -> value }` into a loop",
prerequisite = setOf(arrayConstructorReferencePhase)
)
private val sharedVariablesLoweringPhase = makeBodyLoweringPhase(
@@ -721,6 +728,7 @@ private val loweringList = listOf<Lowering>(
expectDeclarationsRemovingPhase,
stripTypeAliasDeclarationsPhase,
jsCodeOutliningPhase,
arrayConstructorReferencePhase,
arrayConstructorPhase,
lateinitNullableFieldsPhase,
lateinitDeclarationLoweringPhase,

View File

@@ -91,20 +91,24 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
}
private fun buildFunctionReference(expression: IrFunctionReference): Pair<IrClass, IrConstructor> {
return CallableReferenceBuilder(expression.symbol.owner, expression, false).build()
val target = expression.symbol.owner
val reflectionTarget = expression.reflectionTarget?.owner ?: target
return CallableReferenceBuilder(target, expression, reflectionTarget).build()
}
private fun buildLambdaReference(function: IrSimpleFunction, expression: IrFunctionExpression): Pair<IrClass, IrConstructor> {
return CallableReferenceBuilder(function, expression, true).build()
return CallableReferenceBuilder(function, expression, null).build()
}
}
private inner class CallableReferenceBuilder(
private val function: IrFunction,
private val reference: IrExpression,
private val isLambda: Boolean
private val reflectionTarget: IrFunction?
) {
private val isLambda: Boolean get() = reflectionTarget == null
private val isSuspendLambda = isLambda && function.isSuspend
private val superClass = if (isSuspendLambda) context.ir.symbols.coroutineImpl.owner.defaultType else context.irBuiltIns.anyType
@@ -362,11 +366,12 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
type = clazz.defaultType
}
// TODO: What name should be in case of constructor? <init> or class name?
getter.body = context.irFactory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrReturnImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingType, getter.symbol, IrConstImpl.string(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, stringType, function.name.asString()
UNDEFINED_OFFSET, UNDEFINED_OFFSET, stringType, reflectionTarget!!.name.asString()
)
)
)

View File

@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.name.Name
@@ -37,7 +34,7 @@ class JsInnerClassesSupport(mapping: JsMapping, private val irFactory: IrFactory
?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
irFactory.buildField {
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
name = Name.identifier("\$this")
type = outerClass.defaultType
visibility = DescriptorVisibilities.PROTECTED

View File

@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.org.objectweb.asm.*
@@ -480,4 +480,4 @@ private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTar
private val IrClass.isOptionalAnnotationClass: Boolean
get() = kind == ClassKind.ANNOTATION_CLASS &&
isExpect &&
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)

View File

@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.common.ir.isFromJava
import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER
import org.jetbrains.kotlin.backend.common.lower.SYNTHESIZED_INIT_BLOCK
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.common.ir.isFromJava
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf

View File

@@ -36,10 +36,10 @@ import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -334,7 +334,7 @@ fun IrClass.getVisibilityAccessFlagForClass(): Int {
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
fun IrClass.isOptionalAnnotationClass(): Boolean =
isAnnotationClass &&
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
val IrDeclaration.isAnnotatedWithDeprecated: Boolean
get() = annotations.hasAnnotation(FqNames.deprecated)

View File

@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -113,7 +112,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
addField {
name = Name.identifier("this$0")
type = it.type
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
isFinal = true
}

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isFromJava
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext

View File

@@ -383,6 +383,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
// The type of the reference is KFunction<in A1, ..., in An, out R>
private val parameterTypes = (irFunctionReference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
private val argumentTypes = parameterTypes.dropLast(1)
private val referenceReturnType = parameterTypes.last()
private val typeArgumentsMap = irFunctionReference.typeSubstitutionMap
@@ -671,7 +672,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
functionReferenceClass.addFunction {
setSourceRange(if (isLambda) callee else irFunctionReference)
name = superMethod.name
returnType = callee.returnType
returnType = referenceReturnType
isSuspend = callee.isSuspend
}.apply {
overriddenSymbols += superMethod.symbol
@@ -703,7 +704,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
body = context.createJvmIrBuilder(symbol, startOffset, endOffset).run {
var unboundIndex = 0
val call = irCall(callee).apply {
val call = irCall(callee.symbol, referenceReturnType).apply {
for (typeParameter in irFunctionReference.symbol.owner.allTypeParameters) {
putTypeArgument(typeParameter.index, typeArgumentsMap[typeParameter.symbol])
}

View File

@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -36,7 +33,7 @@ class JvmInnerClassesSupport(private val irFactory: IrFactory) : InnerClassesSup
irFactory.buildField {
name = Name.identifier("this$0")
type = innerClass.parentAsClass.defaultType
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
isFinal = true
}.apply {

Some files were not shown because too many files have changed in this diff Show More